From bb91cdfce52cb12ccdf3535beea0fb16fdf88337 Mon Sep 17 00:00:00 2001 From: walkerka Date: Jun 15 2016 15:27:23 +0000 Subject: Merge branch 'master' of https://github.com/opentoonz/opentoonz # Conflicts: # toonz/sources/tnztools/brushtool.cpp # toonz/sources/tnztools/brushtool.h --- diff --git a/toonz/sources/.clang-format b/toonz/sources/.clang-format new file mode 100644 index 0000000..f1dcf57 --- /dev/null +++ b/toonz/sources/.clang-format @@ -0,0 +1,14 @@ +BasedOnStyle: Google +Standard: C++11 +UseTab: Never +AccessModifierOffset: -2 +AlignAfterOpenBracket: true +AlignConsecutiveAssignments: true +AlignEscapedNewlinesLeft: false +AlignTrailingComments: true +IndentCaseLabels: false +BreakConstructorInitializersBeforeComma: true +PointerAlignment: Left +SortIncludes: false + + diff --git a/toonz/sources/CMakeLists.txt b/toonz/sources/CMakeLists.txt index 3010fae..7e7ae24 100644 --- a/toonz/sources/CMakeLists.txt +++ b/toonz/sources/CMakeLists.txt @@ -25,6 +25,8 @@ if(WIN32) endif() set(QT_LIB_PATH ${QT_PATH}) set(CMAKE_PREFIX_PATH "${QT_PATH}/lib/cmake/") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4251") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4251") add_definitions(-DVC_EXTRALEAN -DNOMINMAX -D_USE_MATH_DEFINES) elseif(APPLE) message("Apple System") diff --git a/toonz/sources/beautification.bat b/toonz/sources/beautification.bat new file mode 100644 index 0000000..46134aa --- /dev/null +++ b/toonz/sources/beautification.bat @@ -0,0 +1,5 @@ +@echo off + +for /R %%F in (*.cpp;*.hpp;*.c;*.h) do ( + clang-format -i "%%F" +) diff --git a/toonz/sources/beautification.sh b/toonz/sources/beautification.sh new file mode 100644 index 0000000..1d6939b --- /dev/null +++ b/toonz/sources/beautification.sh @@ -0,0 +1,2 @@ +#!/bin/sh +git ls-files | egrep \\.\(c\|cpp\|h\|hpp\)$ | xargs clang-format -i diff --git a/toonz/sources/colorfx/colorfx.cpp b/toonz/sources/colorfx/colorfx.cpp index 89ba15e..f6cedc9 100644 --- a/toonz/sources/colorfx/colorfx.cpp +++ b/toonz/sources/colorfx/colorfx.cpp @@ -10,94 +10,92 @@ //------------------------------------------------------------------- -namespace -{ +namespace { //------------------------------------------------------------------- -void add(TColorStyle *s) -{ - TColorStyle::declare(s); -} +void add(TColorStyle *s) { TColorStyle::declare(s); } //------------------------------------------------------------------- -} // namespace +} // namespace //------------------------------------------------------------------- -void initColorFx() -{ - //add(new TFriezeStrokeStyle); +void initColorFx() { + // add(new TFriezeStrokeStyle); - add(new TRopeStrokeStyle); + add(new TRopeStrokeStyle); - add(new TChainStrokeStyle); - add(new TFurStrokeStyle); - //add(new TChalkStrokeStyle); - //add(new TBumpStrokeStyle); - //add(new TBlendStrokeStyle); + add(new TChainStrokeStyle); + add(new TFurStrokeStyle); + // add(new TChalkStrokeStyle); + // add(new TBumpStrokeStyle); + // add(new TBlendStrokeStyle); - add(new TDottedLineStrokeStyle); + add(new TDottedLineStrokeStyle); - add(new TBraidStrokeStyle); - add(new TSketchStrokeStyle); - add(new TBubbleStrokeStyle); - add(new TGraphicPenStrokeStyle); - add(new TCrystallizeStrokeStyle); - add(new TSprayStrokeStyle); - add(new TTissueStrokeStyle); - //add(new TMultiLineStrokeStyle); - add(new TBiColorStrokeStyle); - add(new TNormal2StrokeStyle); - //add(new TNormalStrokeStyle); - //add(new TLongBlendStrokeStyle); - add(new TChalkStrokeStyle2); - //add(new TDualColorStrokeStyle); + add(new TBraidStrokeStyle); + add(new TSketchStrokeStyle); + add(new TBubbleStrokeStyle); + add(new TGraphicPenStrokeStyle); + add(new TCrystallizeStrokeStyle); + add(new TSprayStrokeStyle); + add(new TTissueStrokeStyle); + // add(new TMultiLineStrokeStyle); + add(new TBiColorStrokeStyle); + add(new TNormal2StrokeStyle); + // add(new TNormalStrokeStyle); + // add(new TLongBlendStrokeStyle); + add(new TChalkStrokeStyle2); + // add(new TDualColorStrokeStyle); - add(new TBlendStrokeStyle2); - add(new TTwirlStrokeStyle); + add(new TBlendStrokeStyle2); + add(new TTwirlStrokeStyle); - add(new TMultiLineStrokeStyle2); - add(new TZigzagStrokeStyle); //non funziona su linux, rivedere - add(new TSinStrokeStyle); + add(new TMultiLineStrokeStyle2); + add(new TZigzagStrokeStyle); // non funziona su linux, rivedere + add(new TSinStrokeStyle); - add(new TFriezeStrokeStyle2); - add(new TDualColorStrokeStyle2()); // non funziona (massimo) su linux, rivedere - add(new TLongBlendStrokeStyle2()); + add(new TFriezeStrokeStyle2); + add(new TDualColorStrokeStyle2()); // non funziona (massimo) su linux, + // rivedere + add(new TLongBlendStrokeStyle2()); - add(new TMatrioskaStrokeStyle()); + add(new TMatrioskaStrokeStyle()); #ifdef _DEBUG - add(new OutlineViewerStyle()); + add(new OutlineViewerStyle()); #endif - add(new MovingSolidColor(TPixel32::Blue, TPointD(10, 10))); //ok - //add(new MovingTexture(readTexture("chessboard.bmp"),TTextureStyle::NONE,TPointD(10,10) )); + add(new MovingSolidColor(TPixel32::Blue, TPointD(10, 10))); // ok + // add(new + // MovingTexture(readTexture("chessboard.bmp"),TTextureStyle::NONE,TPointD(10,10) + // )); - add(new ShadowStyle(TPixel32::White, TPixel32::Black)); - add(new ShadowStyle2(TPixel32::Yellow, TPixel32::Magenta)); + add(new ShadowStyle(TPixel32::White, TPixel32::Black)); + add(new ShadowStyle2(TPixel32::Yellow, TPixel32::Magenta)); - add(new TRubberFillStyle(TPixel32(255, 0, 255, 127), 25.0)); - add(new TPointShadowFillStyle(TPixel32(255, 255, 200), TPixel32(215, 0, 0))); + add(new TRubberFillStyle(TPixel32(255, 0, 255, 127), 25.0)); + add(new TPointShadowFillStyle(TPixel32(255, 255, 200), TPixel32(215, 0, 0))); - add(new TDottedFillStyle(TPixel32::Green)); + add(new TDottedFillStyle(TPixel32::Green)); - add(new TCheckedFillStyle(TPixel32(255, 0, 0, 128))); - add(new ArtisticSolidColor(TPixel32(0, 130, 255), TPointD(10, 10), 100)); + add(new TCheckedFillStyle(TPixel32(255, 0, 0, 128))); + add(new ArtisticSolidColor(TPixel32(0, 130, 255), TPointD(10, 10), 100)); - add(new TChalkFillStyle(TPixel32::White, TPixel32::Black)); //non funziona - add(new TChessFillStyle(TPixel32::Red)); + add(new TChalkFillStyle(TPixel32::White, TPixel32::Black)); // non funziona + add(new TChessFillStyle(TPixel32::Red)); - add(new TSawToothStrokeStyle); - add(new TStripeFillStyle(TPixel32::Green)); + add(new TSawToothStrokeStyle); + add(new TStripeFillStyle(TPixel32::Green)); - add(new TLinGradFillStyle(TPixel32::Green)); - add(new TRadGradFillStyle(TPixel32::Green)); - add(new TCircleStripeFillStyle(TPixel32::Green)); - add(new TMosaicFillStyle(TPixel32::Red)); - add(new TPatchFillStyle(TPixel32::Blue)); - add(new TAirbrushRasterStyle(TPixel32::Black, 10)); - add(new TBlendRasterStyle(TPixel32::Black, 10)); - add(new TNoColorRasterStyle()); + add(new TLinGradFillStyle(TPixel32::Green)); + add(new TRadGradFillStyle(TPixel32::Green)); + add(new TCircleStripeFillStyle(TPixel32::Green)); + add(new TMosaicFillStyle(TPixel32::Red)); + add(new TPatchFillStyle(TPixel32::Blue)); + add(new TAirbrushRasterStyle(TPixel32::Black, 10)); + add(new TBlendRasterStyle(TPixel32::Black, 10)); + add(new TNoColorRasterStyle()); } diff --git a/toonz/sources/colorfx/colorfxutils.cpp b/toonz/sources/colorfx/colorfxutils.cpp index ee6a545..3dcbae1 100644 --- a/toonz/sources/colorfx/colorfxutils.cpp +++ b/toonz/sources/colorfx/colorfxutils.cpp @@ -7,401 +7,376 @@ #include "tregion.h" #include "tflash.h" -RubberDeform::RubberDeform() : m_pPolyOri(0), m_polyLoc() -{ +RubberDeform::RubberDeform() : m_pPolyOri(0), m_polyLoc() {} + +RubberDeform::RubberDeform(std::vector *pPolyOri, const double rf) + : m_pPolyOri(pPolyOri), m_polyLoc() { + copyOri2Loc(); + TRectD bbox; + getBBox(bbox); + double d = tdistance(TPointD(bbox.x0, bbox.y0), TPointD(bbox.x1, bbox.y1)); + d = d / 20; + refinePoly(d); } -RubberDeform::RubberDeform(std::vector *pPolyOri, const double rf) : m_pPolyOri(pPolyOri), - m_polyLoc() -{ - copyOri2Loc(); - TRectD bbox; - getBBox(bbox); - double d = tdistance(TPointD(bbox.x0, bbox.y0), TPointD(bbox.x1, bbox.y1)); - d = d / 20; - refinePoly(d); +RubberDeform::~RubberDeform() {} + +void RubberDeform::deformStep() { + std::vector tmpv; + std::vector::iterator itb = m_polyLoc.begin(); + std::vector::iterator ite = m_polyLoc.end(); + for (std::vector::iterator it = itb; it != ite; ++it) { + std::vector::iterator it1 = it == (ite - 1) ? itb : it + 1; + double q = 0.5; + double qq = 1.0 - q; + tmpv.push_back(T3DPointD(qq * it->x + q * it1->x, qq * it->y + q * it1->y, + qq * it->z + q * it1->z)); + } + m_polyLoc = tmpv; } -RubberDeform::~RubberDeform() -{ +void RubberDeform::deform(const double n) { + if (n <= 0 || n >= 100) return; + double q = (double)n / 100.0; + TRectD bbox; + getBBox(bbox); + double d0 = ((bbox.y1 - bbox.y0) * 0.5 + (bbox.x1 - bbox.x0) * 0.5) * 0.5; + double d = d0; + while ((d / d0) > q) { + deformStep(); + getBBox(bbox); + d = ((bbox.y1 - bbox.y0) * 0.5 + (bbox.x1 - bbox.x0) * 0.5) * 0.5; + } + copyLoc2Ori(); } -void RubberDeform::deformStep() -{ - std::vector tmpv; - std::vector::iterator itb = m_polyLoc.begin(); - std::vector::iterator ite = m_polyLoc.end(); - for (std::vector::iterator it = itb; it != ite; ++it) { - std::vector::iterator it1 = it == (ite - 1) ? itb : it + 1; - double q = 0.5; - double qq = 1.0 - q; - tmpv.push_back(T3DPointD(qq * it->x + q * it1->x, qq * it->y + q * it1->y, qq * it->z + q * it1->z)); - } - m_polyLoc = tmpv; +double RubberDeform::avgLength() { + if (m_polyLoc.size() <= 0) return 0.0; + + double avgD = 0.0; + std::vector::iterator itb = m_polyLoc.begin(); + std::vector::iterator ite = m_polyLoc.end(); + for (std::vector::iterator it = itb; it != ite; ++it) { + std::vector::iterator it1 = it == (ite - 1) ? itb : it + 1; + avgD += tdistance(*it, *it1); + } + return avgD / (double)m_polyLoc.size(); } -void RubberDeform::deform(const double n) -{ - if (n <= 0 || n >= 100) - return; - double q = (double)n / 100.0; - TRectD bbox; - getBBox(bbox); - double d0 = ((bbox.y1 - bbox.y0) * 0.5 + (bbox.x1 - bbox.x0) * 0.5) * 0.5; - double d = d0; - while ((d / d0) > q) { - deformStep(); - getBBox(bbox); - d = ((bbox.y1 - bbox.y0) * 0.5 + (bbox.x1 - bbox.x0) * 0.5) * 0.5; - } - copyLoc2Ori(); +void RubberDeform::getBBox(TRectD &bbox) { + if (m_polyLoc.size() <= 0) { + bbox.x0 = bbox.y0 = 0; + bbox.x1 = bbox.y1 = -1; + return; + } + bbox.x0 = bbox.x1 = m_polyLoc[0].x; + bbox.y0 = bbox.y1 = m_polyLoc[0].y; + for (int i = 1; i < (int)m_polyLoc.size(); i++) { + bbox.x0 = std::min(bbox.x0, m_polyLoc[i].x); + bbox.x1 = std::max(bbox.x1, m_polyLoc[i].x); + bbox.y0 = std::min(bbox.y0, m_polyLoc[i].y); + bbox.y1 = std::max(bbox.y1, m_polyLoc[i].y); + } } -double RubberDeform::avgLength() -{ - if (m_polyLoc.size() <= 0) - return 0.0; - - double avgD = 0.0; - std::vector::iterator itb = m_polyLoc.begin(); - std::vector::iterator ite = m_polyLoc.end(); - for (std::vector::iterator it = itb; it != ite; ++it) { - std::vector::iterator it1 = it == (ite - 1) ? itb : it + 1; - avgD += tdistance(*it, *it1); - } - return avgD / (double)m_polyLoc.size(); -} - -void RubberDeform::getBBox(TRectD &bbox) -{ - if (m_polyLoc.size() <= 0) { - bbox.x0 = bbox.y0 = 0; - bbox.x1 = bbox.y1 = -1; - return; - } - bbox.x0 = bbox.x1 = m_polyLoc[0].x; - bbox.y0 = bbox.y1 = m_polyLoc[0].y; - for (int i = 1; i < (int)m_polyLoc.size(); i++) { - bbox.x0 = std::min(bbox.x0, m_polyLoc[i].x); - bbox.x1 = std::max(bbox.x1, m_polyLoc[i].x); - bbox.y0 = std::min(bbox.y0, m_polyLoc[i].y); - bbox.y1 = std::max(bbox.y1, m_polyLoc[i].y); - } -} - -void RubberDeform::refinePoly(const double rf) -{ - - double refineL = rf <= 0.0 ? avgLength() : rf; - std::vector tmpv; - int nb = m_polyLoc.size(); - for (int j = 0; j < nb; j++) { - T3DPointD a(m_polyLoc[j]); - T3DPointD b(j == (nb - 1) ? m_polyLoc[0] : m_polyLoc[j + 1]); - tmpv.push_back(a); - double d = tdistance(a, b); - if (d > refineL) { - int n = (int)(d / refineL) + 1; - double q = 1.0 / (double)n; - for (int i = 1; i < n; i++) { - double qq = q * (double)i; - double qq1 = 1.0 - qq; - T3DPointD p(T3DPointD(qq1 * a.x + qq * b.x, qq1 * a.y + qq * b.y, qq1 * a.z + qq * b.z)); - tmpv.push_back(p); - } - } - } - m_polyLoc = tmpv; +void RubberDeform::refinePoly(const double rf) { + double refineL = rf <= 0.0 ? avgLength() : rf; + std::vector tmpv; + int nb = m_polyLoc.size(); + for (int j = 0; j < nb; j++) { + T3DPointD a(m_polyLoc[j]); + T3DPointD b(j == (nb - 1) ? m_polyLoc[0] : m_polyLoc[j + 1]); + tmpv.push_back(a); + double d = tdistance(a, b); + if (d > refineL) { + int n = (int)(d / refineL) + 1; + double q = 1.0 / (double)n; + for (int i = 1; i < n; i++) { + double qq = q * (double)i; + double qq1 = 1.0 - qq; + T3DPointD p(T3DPointD(qq1 * a.x + qq * b.x, qq1 * a.y + qq * b.y, + qq1 * a.z + qq * b.z)); + tmpv.push_back(p); + } + } + } + m_polyLoc = tmpv; } // ------------------- SFlashUtils ------------------------------------------- void SFlashUtils::computeOutline(const TRegion *region, - TRegionOutline::PointVector &polyline) const -{ - if (!region) - return; - - const double pixelSize = 1.0; - polyline.clear(); - - std::vector polyline2d; - - int edgeSize = region->getEdgeCount(); - - for (int i = 0; i < edgeSize; i++) { - TEdge &edge = *region->getEdge(i); - stroke2polyline(polyline2d, *edge.m_s, pixelSize, edge.m_w0, edge.m_w1); - } - int pointNumber = polyline2d.size(); - polyline.reserve(pointNumber); - for (int j = 0; j < pointNumber; j++) { - polyline.push_back(T3DPointD(polyline2d[j], 0.0)); - } + TRegionOutline::PointVector &polyline) const { + if (!region) return; + + const double pixelSize = 1.0; + polyline.clear(); + + std::vector polyline2d; + + int edgeSize = region->getEdgeCount(); + + for (int i = 0; i < edgeSize; i++) { + TEdge &edge = *region->getEdge(i); + stroke2polyline(polyline2d, *edge.m_s, pixelSize, edge.m_w0, edge.m_w1); + } + int pointNumber = polyline2d.size(); + polyline.reserve(pointNumber); + for (int j = 0; j < pointNumber; j++) { + polyline.push_back(T3DPointD(polyline2d[j], 0.0)); + } } -void SFlashUtils::computeRegionOutline() -{ - if (!m_r) - return; +void SFlashUtils::computeRegionOutline() { + if (!m_r) return; - int subRegionNumber = m_r->getSubregionCount(); - TRegionOutline::PointVector app; + int subRegionNumber = m_r->getSubregionCount(); + TRegionOutline::PointVector app; - m_ro.m_exterior.clear(); - computeOutline(m_r, app); + m_ro.m_exterior.clear(); + computeOutline(m_r, app); - m_ro.m_exterior.push_back(app); - m_ro.m_interior.clear(); - m_ro.m_interior.reserve(subRegionNumber); - for (int i = 0; i < subRegionNumber; i++) { - app.clear(); - computeOutline(m_r->getSubregion(i), app); - m_ro.m_interior.push_back(app); - } + m_ro.m_exterior.push_back(app); + m_ro.m_interior.clear(); + m_ro.m_interior.reserve(subRegionNumber); + for (int i = 0; i < subRegionNumber; i++) { + app.clear(); + computeOutline(m_r->getSubregion(i), app); + m_ro.m_interior.push_back(app); + } - m_ro.m_bbox = m_r->getBBox(); + m_ro.m_bbox = m_r->getBBox(); } void SFlashUtils::PointVector2QuadsArray(const std::vector &pv, - std::vector &quadArray, - std::vector &toBeDeleted, - const bool isRounded) const -{ - std::vector::const_iterator ipv = pv.begin(); - std::vector::const_iterator ipve = pv.end(); - int nbPv = pv.size(); - quadArray.clear(); - - if (isRounded) { - if (nbPv <= 2) { - if (nbPv == 1) { - TPointD p0, p1, p2; - p0 = TPointD(pv[0].x, pv[0].y); - p1 = TPointD(pv[0].x, pv[0].y); - p2 = TPointD(pv[0].x, pv[0].y); - quadArray.push_back(new TQuadratic(p0, p1, p2)); - toBeDeleted.push_back(quadArray.back()); - } - if (nbPv == 2) { - TPointD p0, p1, p2; - p0 = TPointD(pv[0].x, pv[0].y); - p1 = TPointD((pv[0].x + pv[1].x) / 2, (pv[0].y + pv[1].y) / 2); - p2 = TPointD(pv[1].x, pv[1].y); - quadArray.push_back(new TQuadratic(p0, p1, p2)); - toBeDeleted.push_back(quadArray.back()); - } - return; - } - - for (int i = 0; i < (nbPv - 2); i++) { - TPointD p0, p1, p2; - p0 = TPointD((pv[i].x + pv[i + 1].x) / 2, (pv[i].y + pv[i + 1].y) / 2); - p1 = TPointD(pv[i + 1].x, pv[i + 1].y); - p2 = TPointD((pv[i + 1].x + pv[i + 2].x) / 2, (pv[i + 1].y + pv[i + 2].y) / 2); - quadArray.push_back(new TQuadratic(p0, p1, p2)); - toBeDeleted.push_back(quadArray.back()); - } - TPointD p0, p1, p2; - p0 = TPointD((pv[nbPv - 2].x + pv[nbPv - 1].x) / 2, (pv[nbPv - 2].y + pv[nbPv - 1].y) / 2); - p1 = TPointD(pv[nbPv - 1].x, pv[nbPv - 1].y); - p2 = TPointD((pv[0].x + pv[1].x) / 2, (pv[0].y + pv[1].y) / 2); - quadArray.push_back(new TQuadratic(p0, p1, p2)); - toBeDeleted.push_back(quadArray.back()); - } else { - for (int i = 0; i < (nbPv - 1); i++) { - TPointD p0, p1, p2; - p0 = TPointD(pv[i].x, pv[i].y); - p2 = TPointD(pv[i + 1].x, pv[i + 1].y); - p1 = TPointD((p0.x + p2.x) * 0.5, (p0.y + p2.y) * 0.5); - quadArray.push_back(new TQuadratic(p0, p1, p2)); - toBeDeleted.push_back(quadArray.back()); - } - TPointD p0, p1, p2; - p0 = TPointD(pv[nbPv - 1].x, pv[nbPv - 1].y); - p2 = TPointD(pv[0].x, pv[0].y); - p1 = TPointD((p0.x + p2.x) * 0.5, (p0.y + p2.y) * 0.5); - quadArray.push_back(new TQuadratic(p0, p1, p2)); - toBeDeleted.push_back(quadArray.back()); - } + std::vector &quadArray, + std::vector &toBeDeleted, + const bool isRounded) const { + std::vector::const_iterator ipv = pv.begin(); + std::vector::const_iterator ipve = pv.end(); + int nbPv = pv.size(); + quadArray.clear(); + + if (isRounded) { + if (nbPv <= 2) { + if (nbPv == 1) { + TPointD p0, p1, p2; + p0 = TPointD(pv[0].x, pv[0].y); + p1 = TPointD(pv[0].x, pv[0].y); + p2 = TPointD(pv[0].x, pv[0].y); + quadArray.push_back(new TQuadratic(p0, p1, p2)); + toBeDeleted.push_back(quadArray.back()); + } + if (nbPv == 2) { + TPointD p0, p1, p2; + p0 = TPointD(pv[0].x, pv[0].y); + p1 = TPointD((pv[0].x + pv[1].x) / 2, (pv[0].y + pv[1].y) / 2); + p2 = TPointD(pv[1].x, pv[1].y); + quadArray.push_back(new TQuadratic(p0, p1, p2)); + toBeDeleted.push_back(quadArray.back()); + } + return; + } + + for (int i = 0; i < (nbPv - 2); i++) { + TPointD p0, p1, p2; + p0 = TPointD((pv[i].x + pv[i + 1].x) / 2, (pv[i].y + pv[i + 1].y) / 2); + p1 = TPointD(pv[i + 1].x, pv[i + 1].y); + p2 = TPointD((pv[i + 1].x + pv[i + 2].x) / 2, + (pv[i + 1].y + pv[i + 2].y) / 2); + quadArray.push_back(new TQuadratic(p0, p1, p2)); + toBeDeleted.push_back(quadArray.back()); + } + TPointD p0, p1, p2; + p0 = TPointD((pv[nbPv - 2].x + pv[nbPv - 1].x) / 2, + (pv[nbPv - 2].y + pv[nbPv - 1].y) / 2); + p1 = TPointD(pv[nbPv - 1].x, pv[nbPv - 1].y); + p2 = TPointD((pv[0].x + pv[1].x) / 2, (pv[0].y + pv[1].y) / 2); + quadArray.push_back(new TQuadratic(p0, p1, p2)); + toBeDeleted.push_back(quadArray.back()); + } else { + for (int i = 0; i < (nbPv - 1); i++) { + TPointD p0, p1, p2; + p0 = TPointD(pv[i].x, pv[i].y); + p2 = TPointD(pv[i + 1].x, pv[i + 1].y); + p1 = TPointD((p0.x + p2.x) * 0.5, (p0.y + p2.y) * 0.5); + quadArray.push_back(new TQuadratic(p0, p1, p2)); + toBeDeleted.push_back(quadArray.back()); + } + TPointD p0, p1, p2; + p0 = TPointD(pv[nbPv - 1].x, pv[nbPv - 1].y); + p2 = TPointD(pv[0].x, pv[0].y); + p1 = TPointD((p0.x + p2.x) * 0.5, (p0.y + p2.y) * 0.5); + quadArray.push_back(new TQuadratic(p0, p1, p2)); + toBeDeleted.push_back(quadArray.back()); + } } -void SFlashUtils::drawRegionOutline(TFlash &flash, const bool isRounded) const -{ - if (!m_r) - return; - - std::vector> quads; - std::vector toBeDeleted; - std::vector quadArray; - PointVector2QuadsArray(*(m_ro.m_exterior.begin()), quadArray, toBeDeleted, isRounded); - quads.push_back(quadArray); - - TRegionOutline::Boundary::const_iterator iinter = m_ro.m_interior.begin(); - TRegionOutline::Boundary::const_iterator iinter_end = m_ro.m_interior.end(); - for (; iinter != iinter_end; iinter++) { - PointVector2QuadsArray(*iinter, quadArray, toBeDeleted, isRounded); - quads.push_back(quadArray); - } - - flash.drawPolygon(quads); - clearPointerContainer(toBeDeleted); +void SFlashUtils::drawRegionOutline(TFlash &flash, const bool isRounded) const { + if (!m_r) return; + + std::vector> quads; + std::vector toBeDeleted; + std::vector quadArray; + PointVector2QuadsArray(*(m_ro.m_exterior.begin()), quadArray, toBeDeleted, + isRounded); + quads.push_back(quadArray); + + TRegionOutline::Boundary::const_iterator iinter = m_ro.m_interior.begin(); + TRegionOutline::Boundary::const_iterator iinter_end = m_ro.m_interior.end(); + for (; iinter != iinter_end; iinter++) { + PointVector2QuadsArray(*iinter, quadArray, toBeDeleted, isRounded); + quads.push_back(quadArray); + } + + flash.drawPolygon(quads); + clearPointerContainer(toBeDeleted); } -int SFlashUtils::nbDiffVerts(const std::vector &pv) const -{ - std::vector lpv; - bool isMissing[4] = {true, true, true, true}; - if (pv.size() == 0) - return 0; - lpv.push_back(pv[0]); - isMissing[0] = false; - for (int i = 1; i < (int)pv.size(); i++) { - bool isDiff = true; - for (int j = 0; j < (int)lpv.size() && isDiff; j++) - isDiff = lpv[j] == pv[i] ? false : isDiff; - if (isDiff) { - lpv.push_back(pv[i]); - isMissing[i] = false; - } - } - return lpv.size(); +int SFlashUtils::nbDiffVerts(const std::vector &pv) const { + std::vector lpv; + bool isMissing[4] = {true, true, true, true}; + if (pv.size() == 0) return 0; + lpv.push_back(pv[0]); + isMissing[0] = false; + for (int i = 1; i < (int)pv.size(); i++) { + bool isDiff = true; + for (int j = 0; j < (int)lpv.size() && isDiff; j++) + isDiff = lpv[j] == pv[i] ? false : isDiff; + if (isDiff) { + lpv.push_back(pv[i]); + isMissing[i] = false; + } + } + return lpv.size(); } -void SFlashUtils::Triangle2Quad(std::vector &p) const -{ - TPointD e; - int i, j; - i = j = -1; - if (p[0] == p[1]) { - i = 0; - j = 1; - e = p[2] - p[3]; - } else if (p[0] == p[2]) { - - } else if (p[0] == p[3]) { - i = 0; - j = 3; - e = p[2] - p[1]; - } else if (p[1] == p[2]) { - i = 1; - j = 2; - e = p[3] - p[0]; - } else if (p[1] == p[3]) { - } else if (p[2] == p[3]) { - i = 2; - j = 3; - e = p[0] - p[1]; - } - e = normalize(e); - p[j] = p[i] + e * 0.001; +void SFlashUtils::Triangle2Quad(std::vector &p) const { + TPointD e; + int i, j; + i = j = -1; + if (p[0] == p[1]) { + i = 0; + j = 1; + e = p[2] - p[3]; + } else if (p[0] == p[2]) { + } else if (p[0] == p[3]) { + i = 0; + j = 3; + e = p[2] - p[1]; + } else if (p[1] == p[2]) { + i = 1; + j = 2; + e = p[3] - p[0]; + } else if (p[1] == p[3]) { + } else if (p[2] == p[3]) { + i = 2; + j = 3; + e = p[0] - p[1]; + } + e = normalize(e); + p[j] = p[i] + e * 0.001; } -void SFlashUtils::drawGradedPolyline(TFlash &flash, - std::vector &pvv, - const TPixel32 &c1, - const TPixel32 &c2) const -{ - std::vector pv; - pv = pvv; - int nbDV = nbDiffVerts(pv); - if (nbDV < 3 || nbDV > 4) - return; - if (nbDV == 3) - Triangle2Quad(pv); - - // Direction Of polyline - TPointD u = pv[0] - pv[1]; - TPointD up = (pv[0] + pv[1]) * 0.5; - u = normalize(u); - u = rotate90(u); - TPointD up1 = up + u; - TPointD up2 = up - u; - double d1 = (tdistance(up1, pv[2]) + tdistance(up1, pv[3])) * 0.5; - double d2 = (tdistance(up2, pv[2]) + tdistance(up2, pv[3])) * 0.5; - - std::vector lpv; - if (d1 > d2) { - lpv = pv; - } else { - lpv.push_back(pv[1]); - lpv.push_back(pv[0]); - lpv.push_back(pv[3]); - lpv.push_back(pv[2]); - } - - // Transformation of gradient square - const double flashGrad = 16384.0; // size of gradient square - flash.setGradientFill(true, c1, c2, 0); - TPointD p0((lpv[0] + lpv[3]) * 0.5); - TPointD p1((lpv[1] + lpv[2]) * 0.5); - double lv = (tdistance(p0, p1)); - double lh = 0.5 * (tdistance(lpv[0], lpv[3]) + tdistance(lpv[1], lpv[2])); - TPointD center = 0.25 * lpv[0] + 0.25 * lpv[1] + 0.25 * lpv[2] + 0.25 * lpv[3]; - TPointD e(p0 - p1); - - double angle = rad2degree(atan(e)); - angle = angle <= 0 ? 270 + angle : angle - 90; - TRotation rM(angle); - TTranslation tM(center.x, center.y); - TScale sM(lh / (flashGrad), lv / (flashGrad)); - - flash.setFillStyleMatrix(tM * sM * rM); - flash.drawPolyline(pv); +void SFlashUtils::drawGradedPolyline(TFlash &flash, std::vector &pvv, + const TPixel32 &c1, + const TPixel32 &c2) const { + std::vector pv; + pv = pvv; + int nbDV = nbDiffVerts(pv); + if (nbDV < 3 || nbDV > 4) return; + if (nbDV == 3) Triangle2Quad(pv); + + // Direction Of polyline + TPointD u = pv[0] - pv[1]; + TPointD up = (pv[0] + pv[1]) * 0.5; + u = normalize(u); + u = rotate90(u); + TPointD up1 = up + u; + TPointD up2 = up - u; + double d1 = (tdistance(up1, pv[2]) + tdistance(up1, pv[3])) * 0.5; + double d2 = (tdistance(up2, pv[2]) + tdistance(up2, pv[3])) * 0.5; + + std::vector lpv; + if (d1 > d2) { + lpv = pv; + } else { + lpv.push_back(pv[1]); + lpv.push_back(pv[0]); + lpv.push_back(pv[3]); + lpv.push_back(pv[2]); + } + + // Transformation of gradient square + const double flashGrad = 16384.0; // size of gradient square + flash.setGradientFill(true, c1, c2, 0); + TPointD p0((lpv[0] + lpv[3]) * 0.5); + TPointD p1((lpv[1] + lpv[2]) * 0.5); + double lv = (tdistance(p0, p1)); + double lh = 0.5 * (tdistance(lpv[0], lpv[3]) + tdistance(lpv[1], lpv[2])); + TPointD center = + 0.25 * lpv[0] + 0.25 * lpv[1] + 0.25 * lpv[2] + 0.25 * lpv[3]; + TPointD e(p0 - p1); + + double angle = rad2degree(atan(e)); + angle = angle <= 0 ? 270 + angle : angle - 90; + TRotation rM(angle); + TTranslation tM(center.x, center.y); + TScale sM(lh / (flashGrad), lv / (flashGrad)); + + flash.setFillStyleMatrix(tM * sM * rM); + flash.drawPolyline(pv); } //------------------------------------------------------------ //------------------------------------------------------------ -void SFlashUtils::drawGradedRegion(TFlash &flash, - std::vector &pvv, - const TPixel32 &c1, - const TPixel32 &c2, const TRegion &r) const -{ - std::vector pv; - pv = pvv; - int nbDV = nbDiffVerts(pv); - if (nbDV < 3 || nbDV > 4) - return; - if (nbDV == 3) - Triangle2Quad(pv); - - // Direction Of polyline - TPointD u = pv[0] - pv[1]; - TPointD up = (pv[0] + pv[1]) * 0.5; - u = normalize(u); - u = rotate90(u); - TPointD up1 = up + u; - TPointD up2 = up - u; - double d1 = (tdistance(up1, pv[2]) + tdistance(up1, pv[3])) * 0.5; - double d2 = (tdistance(up2, pv[2]) + tdistance(up2, pv[3])) * 0.5; - - std::vector lpv; - if (d1 > d2) { - lpv = pv; - } else { - lpv.push_back(pv[1]); - lpv.push_back(pv[0]); - lpv.push_back(pv[3]); - lpv.push_back(pv[2]); - } - - // Transformation of gradient square - const double flashGrad = 16384.0; // size of gradient square - flash.setGradientFill(true, c1, c2, 0); - TPointD p0((lpv[0] + lpv[3]) * 0.5); - TPointD p1((lpv[1] + lpv[2]) * 0.5); - double lv = (tdistance(p0, p1)); - double lh = 0.5 * (tdistance(lpv[0], lpv[3]) + tdistance(lpv[1], lpv[2])); - TPointD center = 0.25 * lpv[0] + 0.25 * lpv[1] + 0.25 * lpv[2] + 0.25 * lpv[3]; - TPointD e(p0 - p1); - - double angle = rad2degree(atan(e)); - angle = angle <= 0 ? 270 + angle : angle - 90; - TRotation rM(angle); - TTranslation tM(center.x, center.y); - TScale sM(lh / (flashGrad), lv / (flashGrad)); - - flash.setFillStyleMatrix(tM * sM * rM); - flash.drawRegion(r); +void SFlashUtils::drawGradedRegion(TFlash &flash, std::vector &pvv, + const TPixel32 &c1, const TPixel32 &c2, + const TRegion &r) const { + std::vector pv; + pv = pvv; + int nbDV = nbDiffVerts(pv); + if (nbDV < 3 || nbDV > 4) return; + if (nbDV == 3) Triangle2Quad(pv); + + // Direction Of polyline + TPointD u = pv[0] - pv[1]; + TPointD up = (pv[0] + pv[1]) * 0.5; + u = normalize(u); + u = rotate90(u); + TPointD up1 = up + u; + TPointD up2 = up - u; + double d1 = (tdistance(up1, pv[2]) + tdistance(up1, pv[3])) * 0.5; + double d2 = (tdistance(up2, pv[2]) + tdistance(up2, pv[3])) * 0.5; + + std::vector lpv; + if (d1 > d2) { + lpv = pv; + } else { + lpv.push_back(pv[1]); + lpv.push_back(pv[0]); + lpv.push_back(pv[3]); + lpv.push_back(pv[2]); + } + + // Transformation of gradient square + const double flashGrad = 16384.0; // size of gradient square + flash.setGradientFill(true, c1, c2, 0); + TPointD p0((lpv[0] + lpv[3]) * 0.5); + TPointD p1((lpv[1] + lpv[2]) * 0.5); + double lv = (tdistance(p0, p1)); + double lh = 0.5 * (tdistance(lpv[0], lpv[3]) + tdistance(lpv[1], lpv[2])); + TPointD center = + 0.25 * lpv[0] + 0.25 * lpv[1] + 0.25 * lpv[2] + 0.25 * lpv[3]; + TPointD e(p0 - p1); + + double angle = rad2degree(atan(e)); + angle = angle <= 0 ? 270 + angle : angle - 90; + TRotation rM(angle); + TTranslation tM(center.x, center.y); + TScale sM(lh / (flashGrad), lv / (flashGrad)); + + flash.setFillStyleMatrix(tM * sM * rM); + flash.drawRegion(r); } diff --git a/toonz/sources/colorfx/colorfxutils.h b/toonz/sources/colorfx/colorfxutils.h index cf73217..3683a00 100644 --- a/toonz/sources/colorfx/colorfxutils.h +++ b/toonz/sources/colorfx/colorfxutils.h @@ -12,55 +12,50 @@ class TRegion; class TFlash; -class RubberDeform -{ - std::vector *m_pPolyOri; - std::vector m_polyLoc; +class RubberDeform { + std::vector *m_pPolyOri; + std::vector m_polyLoc; - void deformStep(); - double avgLength(); - void refinePoly(const double rf = -1.0); - void getBBox(TRectD &bbox); + void deformStep(); + double avgLength(); + void refinePoly(const double rf = -1.0); + void getBBox(TRectD &bbox); public: - RubberDeform(); - RubberDeform(std::vector *pPolyOri, const double rf = -1.0); - void copyLoc2Ori() { *m_pPolyOri = m_polyLoc; }; - void copyOri2Loc() { m_polyLoc = *m_pPolyOri; }; + RubberDeform(); + RubberDeform(std::vector *pPolyOri, const double rf = -1.0); + void copyLoc2Ori() { *m_pPolyOri = m_polyLoc; }; + void copyOri2Loc() { m_polyLoc = *m_pPolyOri; }; - virtual ~RubberDeform(); - void deform(const double n); + virtual ~RubberDeform(); + void deform(const double n); }; -class SFlashUtils -{ - void computeOutline(const TRegion *region, TRegionOutline::PointVector &polyline) const; - void PointVector2QuadsArray(const std::vector &pv, - std::vector &quadArray, - std::vector &toBeDeleted, - const bool isRounded) const; - int nbDiffVerts(const std::vector &pv) const; - void Triangle2Quad(std::vector &p) const; +class SFlashUtils { + void computeOutline(const TRegion *region, + TRegionOutline::PointVector &polyline) const; + void PointVector2QuadsArray(const std::vector &pv, + std::vector &quadArray, + std::vector &toBeDeleted, + const bool isRounded) const; + int nbDiffVerts(const std::vector &pv) const; + void Triangle2Quad(std::vector &p) const; public: - const TRegion *m_r; - TRegionOutline m_ro; - - SFlashUtils(){}; - SFlashUtils(const TRegion *r) : m_r(r){}; - virtual ~SFlashUtils(){}; - - void computeRegionOutline(); - void drawRegionOutline(TFlash &flash, const bool isRounded = true) const; - void drawGradedPolyline(TFlash &flash, - std::vector &pv, - const TPixel32 &c1, - const TPixel32 &c2) const; - void drawGradedRegion(TFlash &flash, - std::vector &pv, - const TPixel32 &c1, - const TPixel32 &c2, - const TRegion &r) const; + const TRegion *m_r; + TRegionOutline m_ro; + + SFlashUtils(){}; + SFlashUtils(const TRegion *r) : m_r(r){}; + virtual ~SFlashUtils(){}; + + void computeRegionOutline(); + void drawRegionOutline(TFlash &flash, const bool isRounded = true) const; + void drawGradedPolyline(TFlash &flash, std::vector &pv, + const TPixel32 &c1, const TPixel32 &c2) const; + void drawGradedRegion(TFlash &flash, std::vector &pv, + const TPixel32 &c1, const TPixel32 &c2, + const TRegion &r) const; }; #endif diff --git a/toonz/sources/colorfx/rasterstyles.cpp b/toonz/sources/colorfx/rasterstyles.cpp index d28e2ac..3e17a17 100644 --- a/toonz/sources/colorfx/rasterstyles.cpp +++ b/toonz/sources/colorfx/rasterstyles.cpp @@ -13,227 +13,209 @@ // TAirbrushRasterStyle implementation //************************************************************************************* -void TAirbrushRasterStyle::loadData(TInputStreamInterface &is) -{ - is >> m_blur; -} +void TAirbrushRasterStyle::loadData(TInputStreamInterface &is) { is >> m_blur; } //----------------------------------------------------------------------------- -void TAirbrushRasterStyle::saveData(TOutputStreamInterface &os) const -{ - os << m_blur; +void TAirbrushRasterStyle::saveData(TOutputStreamInterface &os) const { + os << m_blur; } //----------------------------------------------------------------------------- -bool TAirbrushRasterStyle::compute(const Params ¶ms) const -{ - if (m_blur > 0.0) - TRop::blur(params.m_r, params.m_r, m_blur, 0, 0, true); +bool TAirbrushRasterStyle::compute(const Params ¶ms) const { + if (m_blur > 0.0) TRop::blur(params.m_r, params.m_r, m_blur, 0, 0, true); - return true; + return true; } //----------------------------------------------------------------------------- -TColorStyle *TAirbrushRasterStyle::clone() const -{ - TColorStyle *cs = new TAirbrushRasterStyle(*this); - cs->assignNames(this); - return cs; +TColorStyle *TAirbrushRasterStyle::clone() const { + TColorStyle *cs = new TAirbrushRasterStyle(*this); + cs->assignNames(this); + return cs; } //----------------------------------------------------------------------------- -void TAirbrushRasterStyle::makeIcon(const TDimension &d) -{ - TFilePath dir = TEnv::getStuffDir() + "pixmaps"; - static TRasterP normalIc; - if (normalIc == TRasterP()) - TImageReader::load(dir + "airbrush.bmp", normalIc); +void TAirbrushRasterStyle::makeIcon(const TDimension &d) { + TFilePath dir = TEnv::getStuffDir() + "pixmaps"; + static TRasterP normalIc; + if (normalIc == TRasterP()) + TImageReader::load(dir + "airbrush.bmp", normalIc); - arrangeIcon(d, normalIc); + arrangeIcon(d, normalIc); } /*---------------------------------------------------------------------------*/ void TAirbrushRasterStyle::arrangeIcon(const TDimension &d, - const TRasterP &normalIc) -{ - if (normalIc == TRasterP()) { - m_icon = TRaster32P(d); - m_icon->fill(TPixel32::Red); - return; - } - - m_icon = TRasterP(); - - if (d == TDimension(52, 52)) - m_icon = normalIc->clone(); - else { - m_icon = TRaster32P(d); - TRop::resample(m_icon, normalIc, TScale(d.lx / 52.0, d.ly / 52.0)); - } - - m_icon->lock(); - TPixel *buf = (TPixel *)m_icon->getRawData(); - TPixel color = getMainColor(); - double rd = (color.r - color.m) / 255.0; - double gd = (color.g - color.m) / 255.0; - double bd = (color.b - color.m) / 255.0; - - assert(m_icon->getWrap() == m_icon->getSize().lx); - - for (int i = 0; i < m_icon->getSize().lx * m_icon->getSize().ly; i++, buf++) { - assert(buf->r == buf->g && buf->r == buf->b); - - if (buf->r < 255) { - if (buf->r == 0) - *buf = color; - else { - int val = 255 - buf->r; - buf->r = (UCHAR)(val * rd + 255); - buf->g = (UCHAR)(val * gd + 255); - buf->b = (UCHAR)(val * bd + 255); - } - } - } - m_icon->unlock(); + const TRasterP &normalIc) { + if (normalIc == TRasterP()) { + m_icon = TRaster32P(d); + m_icon->fill(TPixel32::Red); + return; + } + + m_icon = TRasterP(); + + if (d == TDimension(52, 52)) + m_icon = normalIc->clone(); + else { + m_icon = TRaster32P(d); + TRop::resample(m_icon, normalIc, TScale(d.lx / 52.0, d.ly / 52.0)); + } + + m_icon->lock(); + TPixel *buf = (TPixel *)m_icon->getRawData(); + TPixel color = getMainColor(); + double rd = (color.r - color.m) / 255.0; + double gd = (color.g - color.m) / 255.0; + double bd = (color.b - color.m) / 255.0; + + assert(m_icon->getWrap() == m_icon->getSize().lx); + + for (int i = 0; i < m_icon->getSize().lx * m_icon->getSize().ly; i++, buf++) { + assert(buf->r == buf->g && buf->r == buf->b); + + if (buf->r < 255) { + if (buf->r == 0) + *buf = color; + else { + int val = 255 - buf->r; + buf->r = (UCHAR)(val * rd + 255); + buf->g = (UCHAR)(val * gd + 255); + buf->b = (UCHAR)(val * bd + 255); + } + } + } + m_icon->unlock(); } //************************************************************************************* // TBlendRasterStyle implementation //************************************************************************************* -TColorStyle *TBlendRasterStyle::clone() const -{ - return new TBlendRasterStyle(*this); +TColorStyle *TBlendRasterStyle::clone() const { + return new TBlendRasterStyle(*this); } //----------------------------------------------------------------------------- -bool TBlendRasterStyle::compute(const Params ¶ms) const -{ - int i, j; - TRasterGR8P r = (TRasterGR8P)params.m_r; - assert(r); - - double factor = computeFactor(params); - - if (m_blur > 0.0) - TRop::blur(params.m_r, params.m_r, m_blur, 0, 0, true); - - r->lock(); - for (i = 0; i < r->getLy(); i++) { - TPixelGR8 *bufGr = r->pixels(i); - for (j = 0; j < r->getLx(); j++, bufGr++) - if (bufGr->value > 0) { - double val = bufGr->value * factor + 0.5; - bufGr->value = (UCHAR)((val > 255) ? 255 : val); - } - } - r->unlock(); - return true; +bool TBlendRasterStyle::compute(const Params ¶ms) const { + int i, j; + TRasterGR8P r = (TRasterGR8P)params.m_r; + assert(r); + + double factor = computeFactor(params); + + if (m_blur > 0.0) TRop::blur(params.m_r, params.m_r, m_blur, 0, 0, true); + + r->lock(); + for (i = 0; i < r->getLy(); i++) { + TPixelGR8 *bufGr = r->pixels(i); + for (j = 0; j < r->getLx(); j++, bufGr++) + if (bufGr->value > 0) { + double val = bufGr->value * factor + 0.5; + bufGr->value = (UCHAR)((val > 255) ? 255 : val); + } + } + r->unlock(); + return true; } //----------------------------------------------------------------------------- -namespace -{ -bool inline doIsBorderPix(int index, TPixelCM32 *pix, TPixelGR8 *pixGr, int paint) -{ - return (pix->getPaint() != paint && (pix->isPurePaint() || pixGr->value != 0)); +namespace { +bool inline doIsBorderPix(int index, TPixelCM32 *pix, TPixelGR8 *pixGr, + int paint) { + return (pix->getPaint() != paint && + (pix->isPurePaint() || pixGr->value != 0)); } //----------------------------------------------------------------------------- -bool inline isBorderPix(int index, TPixelCM32 *pix, int wrap, TPixelGR8 *pixGr, int wrapGr, int color) -{ - return doIsBorderPix(index, pix + 1, pixGr + 1, color) || - doIsBorderPix(index, pix - 1, pixGr - 1, color) || - doIsBorderPix(index, pix + wrap, pixGr + wrapGr, color) || - doIsBorderPix(index, pix - wrap, pixGr - wrapGr, color); +bool inline isBorderPix(int index, TPixelCM32 *pix, int wrap, TPixelGR8 *pixGr, + int wrapGr, int color) { + return doIsBorderPix(index, pix + 1, pixGr + 1, color) || + doIsBorderPix(index, pix - 1, pixGr - 1, color) || + doIsBorderPix(index, pix + wrap, pixGr + wrapGr, color) || + doIsBorderPix(index, pix - wrap, pixGr - wrapGr, color); } } /*---------------------------------------------------------------------------*/ -void TBlendRasterStyle::makeIcon(const TDimension &d) -{ - TFilePath dir = TEnv::getStuffDir() + "pixmaps"; - static TRasterP normalIc; - if (normalIc == TRasterP()) - TImageReader::load(dir + "blend.bmp", normalIc); +void TBlendRasterStyle::makeIcon(const TDimension &d) { + TFilePath dir = TEnv::getStuffDir() + "pixmaps"; + static TRasterP normalIc; + if (normalIc == TRasterP()) TImageReader::load(dir + "blend.bmp", normalIc); - arrangeIcon(d, normalIc); + arrangeIcon(d, normalIc); } //----------------------------------------------------------------------------- -double TBlendRasterStyle::computeFactor(const Params ¶ms) const -{ - TRasterCM32P rCm = (TRasterCM32P)params.m_rOrig; - TRasterGR8P rGr = (TRasterGR8P)params.m_r; - TPixelGR8 *bufGr; - TPixelCM32 *bufCmap; - int i, j; - int wr = params.m_rOrig->getWrap(); - int wrGr = params.m_r->getWrap(); - int num_lines = 0; - double tot_sum = 0; - - //interactive! - //if (Factor == 0) - rGr->lock(); - rCm->lock(); - for (i = 1; i < params.m_r->getLy() - 1; i++) { - int line_sum = 0, num_points = 0; - bufGr = rGr->pixels(i) + 1; - bufCmap = rCm->pixels(i) + 1; - for (j = 1; j < rGr->getLx() - 1; j++, bufGr++, bufCmap++) { - if (bufGr->value > 0) { - int paint = bufCmap->getPaint(); - if ((bufCmap->isPurePaint() || bufGr->value != 0) && - isBorderPix(params.m_colorIndex, bufCmap, wr, bufGr, wrGr, paint)) { - line_sum += troundp(bufGr->value); - num_points++; - } - } - } - rGr->unlock(); - rCm->unlock(); - if (num_points != 0) { - tot_sum += ((float)line_sum / ((float)num_points * 255)); - num_lines++; - } - } - if (num_lines == 0) - return 0; - - return num_lines / tot_sum; +double TBlendRasterStyle::computeFactor(const Params ¶ms) const { + TRasterCM32P rCm = (TRasterCM32P)params.m_rOrig; + TRasterGR8P rGr = (TRasterGR8P)params.m_r; + TPixelGR8 *bufGr; + TPixelCM32 *bufCmap; + int i, j; + int wr = params.m_rOrig->getWrap(); + int wrGr = params.m_r->getWrap(); + int num_lines = 0; + double tot_sum = 0; + + // interactive! + // if (Factor == 0) + rGr->lock(); + rCm->lock(); + for (i = 1; i < params.m_r->getLy() - 1; i++) { + int line_sum = 0, num_points = 0; + bufGr = rGr->pixels(i) + 1; + bufCmap = rCm->pixels(i) + 1; + for (j = 1; j < rGr->getLx() - 1; j++, bufGr++, bufCmap++) { + if (bufGr->value > 0) { + int paint = bufCmap->getPaint(); + if ((bufCmap->isPurePaint() || bufGr->value != 0) && + isBorderPix(params.m_colorIndex, bufCmap, wr, bufGr, wrGr, paint)) { + line_sum += troundp(bufGr->value); + num_points++; + } + } + } + rGr->unlock(); + rCm->unlock(); + if (num_points != 0) { + tot_sum += ((float)line_sum / ((float)num_points * 255)); + num_lines++; + } + } + if (num_lines == 0) return 0; + + return num_lines / tot_sum; } //************************************************************************************* // TNoColorRasterStyle implementation //************************************************************************************* -void TNoColorRasterStyle::makeIcon(const TDimension &d) -{ - TFilePath dir = TEnv::getStuffDir() + "pixmaps"; - static TRasterP normalIc; - if (normalIc == TRasterP()) - TImageReader::load(dir + "markup.bmp", normalIc); - - if (normalIc == TRasterP()) { - m_icon = TRaster32P(d); - m_icon->fill(TPixel32::Red); - return; - } - - m_icon = TRasterP(); - if (d == TDimension(52, 52) && normalIc != TRasterP()) - m_icon = normalIc->clone(); - else { - m_icon = TRaster32P(d); - TRop::resample(m_icon, normalIc, TScale(d.lx / 52.0, d.ly / 52.0)); - } +void TNoColorRasterStyle::makeIcon(const TDimension &d) { + TFilePath dir = TEnv::getStuffDir() + "pixmaps"; + static TRasterP normalIc; + if (normalIc == TRasterP()) TImageReader::load(dir + "markup.bmp", normalIc); + + if (normalIc == TRasterP()) { + m_icon = TRaster32P(d); + m_icon->fill(TPixel32::Red); + return; + } + + m_icon = TRasterP(); + if (d == TDimension(52, 52) && normalIc != TRasterP()) + m_icon = normalIc->clone(); + else { + m_icon = TRaster32P(d); + TRop::resample(m_icon, normalIc, TScale(d.lx / 52.0, d.ly / 52.0)); + } } diff --git a/toonz/sources/colorfx/rasterstyles.h b/toonz/sources/colorfx/rasterstyles.h index 3d06185..dee3d28 100644 --- a/toonz/sources/colorfx/rasterstyles.h +++ b/toonz/sources/colorfx/rasterstyles.h @@ -18,169 +18,163 @@ class TOutputStreamInterface; //============================================================================= -class TAirbrushRasterStyle : public TColorStyle, public TRasterStyleFx -{ +class TAirbrushRasterStyle : public TColorStyle, public TRasterStyleFx { protected: - TPixel32 m_color; - double m_blur; + TPixel32 m_color; + double m_blur; public: - TAirbrushRasterStyle(const TPixel32 &color, double blur) - : m_color(color), m_blur(blur) {} + TAirbrushRasterStyle(const TPixel32 &color, double blur) + : m_color(color), m_blur(blur) {} - TColorStyle *clone() const; + TColorStyle *clone() const; public: - // n.b. per un plain color: isRasterStyle() == true, ma getRasterStyleFx() = 0 - - TStrokeProp *makeStrokeProp(const TStroke *stroke) { return 0; } - TRegionProp *makeRegionProp(const TRegion *region) { return 0; } - TRasterStyleFx *getRasterStyleFx() { return this; } - - bool isRegionStyle() const { return false; } - bool isStrokeStyle() const { return false; } - bool isRasterStyle() const { return true; } - void getEnlargement(int &borderIn, int &borderOut) const - { - borderIn = tceil(2 * m_blur); - borderOut = tceil(m_blur); - } - - bool hasMainColor() const { return true; } - TPixel32 getMainColor() const { return m_color; } - void setMainColor(const TPixel32 &color) { m_color = color; } - - int getColorParamCount() const { return 1; } - TPixel32 getColorParamValue(int index) const { return m_color; } - void setColorParamValue(int index, const TPixel32 &color) - { - m_color = color; - } - - virtual QString getDescription() const { return QCoreApplication::translate("TAirbrushRasterStyle", "Airbrush"); } - - int getParamCount() const { return 1; } - TColorStyle::ParamType getParamType(int index) const - { - assert(index == 0); - return TColorStyle::DOUBLE; - } - - QString getParamNames(int index) const - { - assert(index == 0); - return QCoreApplication::translate("TAirbrushRasterStyle", "Blur value"); - } - void getParamRange(int index, double &min, double &max) const - { - assert(index == 0); - min = 0; - max = 30; - } - double getParamValue(TColorStyle::double_tag, int index) const - { - assert(index == 0); - return m_blur; - } - void setParamValue(int index, double value) - { - assert(index == 0); - m_blur = value; - } - - void invalidateIcon(); - - //const TRaster32P &getIcon(const TDimension &d) {assert(false);return (TRaster32P)0;} - - TPixel32 getAverageColor() const { return m_color; } - - int getTagId() const { return 1150; } - - bool isInkStyle() const { return true; } - bool isPaintStyle() const { return false; } - - bool compute(const Params ¶ms) const; + // n.b. per un plain color: isRasterStyle() == true, ma getRasterStyleFx() = 0 + + TStrokeProp *makeStrokeProp(const TStroke *stroke) { return 0; } + TRegionProp *makeRegionProp(const TRegion *region) { return 0; } + TRasterStyleFx *getRasterStyleFx() { return this; } + + bool isRegionStyle() const { return false; } + bool isStrokeStyle() const { return false; } + bool isRasterStyle() const { return true; } + void getEnlargement(int &borderIn, int &borderOut) const { + borderIn = tceil(2 * m_blur); + borderOut = tceil(m_blur); + } + + bool hasMainColor() const { return true; } + TPixel32 getMainColor() const { return m_color; } + void setMainColor(const TPixel32 &color) { m_color = color; } + + int getColorParamCount() const { return 1; } + TPixel32 getColorParamValue(int index) const { return m_color; } + void setColorParamValue(int index, const TPixel32 &color) { m_color = color; } + + virtual QString getDescription() const { + return QCoreApplication::translate("TAirbrushRasterStyle", "Airbrush"); + } + + int getParamCount() const { return 1; } + TColorStyle::ParamType getParamType(int index) const { + assert(index == 0); + return TColorStyle::DOUBLE; + } + + QString getParamNames(int index) const { + assert(index == 0); + return QCoreApplication::translate("TAirbrushRasterStyle", "Blur value"); + } + void getParamRange(int index, double &min, double &max) const { + assert(index == 0); + min = 0; + max = 30; + } + double getParamValue(TColorStyle::double_tag, int index) const { + assert(index == 0); + return m_blur; + } + void setParamValue(int index, double value) { + assert(index == 0); + m_blur = value; + } + + void invalidateIcon(); + + // const TRaster32P &getIcon(const TDimension &d) {assert(false);return + // (TRaster32P)0;} + + TPixel32 getAverageColor() const { return m_color; } + + int getTagId() const { return 1150; } + + bool isInkStyle() const { return true; } + bool isPaintStyle() const { return false; } + + bool compute(const Params ¶ms) const; protected: - virtual void makeIcon(const TDimension &d); + virtual void makeIcon(const TDimension &d); - void arrangeIcon(const TDimension &d, const TRasterP &normalIc); + void arrangeIcon(const TDimension &d, const TRasterP &normalIc); - void loadData(TInputStreamInterface &); - void saveData(TOutputStreamInterface &) const; + void loadData(TInputStreamInterface &); + void saveData(TOutputStreamInterface &) const; - // per la compatibilita' con il passato - void loadData(int oldId, TInputStreamInterface &){}; + // per la compatibilita' con il passato + void loadData(int oldId, TInputStreamInterface &){}; }; //============================================================================= -class TBlendRasterStyle : public TAirbrushRasterStyle -{ +class TBlendRasterStyle : public TAirbrushRasterStyle { public: - TBlendRasterStyle(const TPixel32 &color, double blur) - : TAirbrushRasterStyle(color, blur) {} - TColorStyle *clone() const; + TBlendRasterStyle(const TPixel32 &color, double blur) + : TAirbrushRasterStyle(color, blur) {} + TColorStyle *clone() const; - int getTagId() const { return 1160; } + int getTagId() const { return 1160; } - virtual QString getDescription() const { return QCoreApplication::translate("TBlendRasterStyle", "Blend"); } + virtual QString getDescription() const { + return QCoreApplication::translate("TBlendRasterStyle", "Blend"); + } - void makeIcon(const TDimension &d); + void makeIcon(const TDimension &d); - bool compute(const TRasterStyleFx::Params ¶ms) const; + bool compute(const TRasterStyleFx::Params ¶ms) const; private: - double computeFactor(const TRasterStyleFx::Params ¶ms) const; + double computeFactor(const TRasterStyleFx::Params ¶ms) const; }; //============================================================================= -class TNoColorRasterStyle : public TColorStyle, TRasterStyleFx -{ +class TNoColorRasterStyle : public TColorStyle, TRasterStyleFx { public: - TNoColorRasterStyle() {} - TColorStyle *clone() const { return new TNoColorRasterStyle(*this); } + TNoColorRasterStyle() {} + TColorStyle *clone() const { return new TNoColorRasterStyle(*this); } - // n.b. per un plain color: isRasterStyle() == true, ma getRasterStyleFx() = 0 + // n.b. per un plain color: isRasterStyle() == true, ma getRasterStyleFx() = 0 - TStrokeProp *makeStrokeProp(const TStroke *stroke) { return 0; } - TRegionProp *makeRegionProp(const TRegion *region) { return 0; } - TRasterStyleFx *getRasterStyleFx() { return this; } + TStrokeProp *makeStrokeProp(const TStroke *stroke) { return 0; } + TRegionProp *makeRegionProp(const TRegion *region) { return 0; } + TRasterStyleFx *getRasterStyleFx() { return this; } - bool isRegionStyle() const { return false; } - bool isStrokeStyle() const { return false; } - bool isRasterStyle() const { return true; } + bool isRegionStyle() const { return false; } + bool isStrokeStyle() const { return false; } + bool isRasterStyle() const { return true; } - virtual QString getDescription() const { return QCoreApplication::translate("TNoColorRasterStyle", "Markup"); } + virtual QString getDescription() const { + return QCoreApplication::translate("TNoColorRasterStyle", "Markup"); + } - bool hasMainColor() { return false; } - //TPixel32 getMainColor() const {return m_color;} - //void setMainColor(const TPixel32 &color) {m_color = color;} + bool hasMainColor() { return false; } + // TPixel32 getMainColor() const {return m_color;} + // void setMainColor(const TPixel32 &color) {m_color = color;} - int getColorParamCount() const { return 0; } - TPixel32 getColorParamValue(int index) const - { - assert(false); - return TPixel32(); - } - void setColorParamValue(int index, const TPixel32 &color) { assert(false); } + int getColorParamCount() const { return 0; } + TPixel32 getColorParamValue(int index) const { + assert(false); + return TPixel32(); + } + void setColorParamValue(int index, const TPixel32 &color) { assert(false); } - int getTagId() const { return 1151; } + int getTagId() const { return 1151; } - bool isInkStyle() const { return true; } - bool isPaintStyle() const { return true; } + bool isInkStyle() const { return true; } + bool isPaintStyle() const { return true; } - bool compute(const Params ¶ms) const { return false; } + bool compute(const Params ¶ms) const { return false; } protected: - void makeIcon(const TDimension &d); + void makeIcon(const TDimension &d); - void loadData(TInputStreamInterface &){}; - void saveData(TOutputStreamInterface &) const {}; + void loadData(TInputStreamInterface &){}; + void saveData(TOutputStreamInterface &) const {}; - // per la compatibilita' con il passato - void loadData(int oldId, TInputStreamInterface &){}; + // per la compatibilita' con il passato + void loadData(int oldId, TInputStreamInterface &){}; }; #endif diff --git a/toonz/sources/colorfx/regionstyles.cpp b/toonz/sources/colorfx/regionstyles.cpp index 2a48b71..e4b904c 100644 --- a/toonz/sources/colorfx/regionstyles.cpp +++ b/toonz/sources/colorfx/regionstyles.cpp @@ -20,56 +20,43 @@ #include "tstencilcontrol.h" //*************************************************************************** -// Local namesapce stuff -//*************************************************************************** - -namespace -{ - -const double pi2 = TConsts::pi * 2.0; - -} // namespace - -//*************************************************************************** // MovingModifier implementation //*************************************************************************** -TOutlineStyle::RegionOutlineModifier *MovingModifier::clone() const -{ - return new MovingModifier(*this); +TOutlineStyle::RegionOutlineModifier *MovingModifier::clone() const { + return new MovingModifier(*this); } //------------------------------------------------------------ -void MovingModifier::modify(TRegionOutline &outline) const -{ - TRegionOutline::Boundary::iterator regIt = outline.m_exterior.begin(); - TRegionOutline::Boundary::iterator regItEnd = outline.m_exterior.end(); +void MovingModifier::modify(TRegionOutline &outline) const { + TRegionOutline::Boundary::iterator regIt = outline.m_exterior.begin(); + TRegionOutline::Boundary::iterator regItEnd = outline.m_exterior.end(); - TRegionOutline::PointVector::iterator pIt; - TRegionOutline::PointVector::iterator pItEnd; + TRegionOutline::PointVector::iterator pIt; + TRegionOutline::PointVector::iterator pItEnd; - for (; regIt != regItEnd; ++regIt) { - pIt = regIt->begin(); - pItEnd = regIt->end(); + for (; regIt != regItEnd; ++regIt) { + pIt = regIt->begin(); + pItEnd = regIt->end(); - for (; pIt != pItEnd; ++pIt) { - pIt->x += m_move.x; - pIt->y += m_move.y; - } - } + for (; pIt != pItEnd; ++pIt) { + pIt->x += m_move.x; + pIt->y += m_move.y; + } + } - regIt = outline.m_interior.begin(); - regItEnd = outline.m_interior.end(); - for (; regIt != regItEnd; ++regIt) { - pIt = regIt->begin(); - pItEnd = regIt->end(); + regIt = outline.m_interior.begin(); + regItEnd = outline.m_interior.end(); + for (; regIt != regItEnd; ++regIt) { + pIt = regIt->begin(); + pItEnd = regIt->end(); - for (; pIt != pItEnd; ++pIt) { - pIt->x += m_move.x; - pIt->y += m_move.y; - } - } + for (; pIt != pItEnd; ++pIt) { + pIt->x += m_move.x; + pIt->y += m_move.y; + } + } } //*************************************************************************** @@ -77,421 +64,399 @@ void MovingModifier::modify(TRegionOutline &outline) const //*************************************************************************** MovingSolidColor::MovingSolidColor(const TPixel32 &color, const TPointD &move) - : TSolidColorStyle(color) -{ - m_regionOutlineModifier = new MovingModifier(move); + : TSolidColorStyle(color) { + m_regionOutlineModifier = new MovingModifier(move); } //------------------------------------------------------------ -TColorStyle *MovingSolidColor::clone() const -{ - return new MovingSolidColor(*this); +TColorStyle *MovingSolidColor::clone() const { + return new MovingSolidColor(*this); } //------------------------------------------------------------ -void MovingSolidColor::loadData(TInputStreamInterface &is) -{ - TSolidColorStyle::loadData(is); - delete m_regionOutlineModifier; - MovingModifier *mov = new MovingModifier(TPointD()); - mov->loadData(is); - m_regionOutlineModifier = mov; +void MovingSolidColor::loadData(TInputStreamInterface &is) { + TSolidColorStyle::loadData(is); + delete m_regionOutlineModifier; + MovingModifier *mov = new MovingModifier(TPointD()); + mov->loadData(is); + m_regionOutlineModifier = mov; } //------------------------------------------------------------ -void MovingSolidColor::saveData(TOutputStreamInterface &os) const -{ - TSolidColorStyle::saveData(os); +void MovingSolidColor::saveData(TOutputStreamInterface &os) const { + TSolidColorStyle::saveData(os); - assert(m_regionOutlineModifier); - ((MovingModifier *)m_regionOutlineModifier)->saveData(os); + assert(m_regionOutlineModifier); + ((MovingModifier *)m_regionOutlineModifier)->saveData(os); } //------------------------------------------------------------ -int MovingSolidColor::getParamCount() const -{ - return 2; -} +int MovingSolidColor::getParamCount() const { return 2; } //----------------------------------------------------------------------------- -TColorStyle::ParamType MovingSolidColor::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +TColorStyle::ParamType MovingSolidColor::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -QString MovingSolidColor::getParamNames(int index) const -{ - assert(0 <= index && index < 2); +QString MovingSolidColor::getParamNames(int index) const { + assert(0 <= index && index < 2); - return index == 0 ? QCoreApplication::translate("MovingSolidColor", "Horiz Offset") : QCoreApplication::translate("MovingSolidColor", "Vert Offset"); + return index == 0 + ? QCoreApplication::translate("MovingSolidColor", "Horiz Offset") + : QCoreApplication::translate("MovingSolidColor", "Vert Offset"); } //----------------------------------------------------------------------------- -void MovingSolidColor::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 2); - min = -100.0; - max = 100.0; +void MovingSolidColor::getParamRange(int index, double &min, + double &max) const { + assert(0 <= index && index < 2); + min = -100.0; + max = 100.0; } //----------------------------------------------------------------------------- -double MovingSolidColor::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 2); +double MovingSolidColor::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 2); - if (index) - return ((MovingModifier *)m_regionOutlineModifier)->getMovePoint().y; - else - return ((MovingModifier *)m_regionOutlineModifier)->getMovePoint().x; + if (index) + return ((MovingModifier *)m_regionOutlineModifier)->getMovePoint().y; + else + return ((MovingModifier *)m_regionOutlineModifier)->getMovePoint().x; } //----------------------------------------------------------------------------- -void MovingSolidColor::setParamValue(int index, double value) -{ - assert(0 <= index && index < 2); +void MovingSolidColor::setParamValue(int index, double value) { + assert(0 <= index && index < 2); - TPointD oldMove = ((MovingModifier *)m_regionOutlineModifier)->getMovePoint(); + TPointD oldMove = ((MovingModifier *)m_regionOutlineModifier)->getMovePoint(); - if (!index) { - if (oldMove.x != value) { - delete m_regionOutlineModifier; - oldMove.x = value; - m_regionOutlineModifier = new MovingModifier(oldMove); - updateVersionNumber(); - } - } else { - if (oldMove.y != value) { - delete m_regionOutlineModifier; - oldMove.y = value; - m_regionOutlineModifier = new MovingModifier(oldMove); - updateVersionNumber(); - } - } + if (!index) { + if (oldMove.x != value) { + delete m_regionOutlineModifier; + oldMove.x = value; + m_regionOutlineModifier = new MovingModifier(oldMove); + updateVersionNumber(); + } + } else { + if (oldMove.y != value) { + delete m_regionOutlineModifier; + oldMove.y = value; + m_regionOutlineModifier = new MovingModifier(oldMove); + updateVersionNumber(); + } + } } //------------------------------------------------------------ -void MovingSolidColor::drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const -{ - TSolidColorStyle::drawRegion(cf, true, boundary); +void MovingSolidColor::drawRegion(const TColorFunction *cf, + const bool antiAliasing, + TRegionOutline &boundary) const { + TSolidColorStyle::drawRegion(cf, true, boundary); } //------------------------------------------------------------ -void MovingSolidColor::drawRegion(TFlash &flash, const TRegion *r) const -{ - SFlashUtils rdf(r); - rdf.computeRegionOutline(); - m_regionOutlineModifier->modify(rdf.m_ro); - flash.setFillColor(getMainColor()); - rdf.drawRegionOutline(flash, false); +void MovingSolidColor::drawRegion(TFlash &flash, const TRegion *r) const { + SFlashUtils rdf(r); + rdf.computeRegionOutline(); + m_regionOutlineModifier->modify(rdf.m_ro); + flash.setFillColor(getMainColor()); + rdf.drawRegionOutline(flash, false); } //*************************************************************************** // ShadowStyle implementation //*************************************************************************** -ShadowStyle::ShadowStyle(const TPixel32 &bgColor, - const TPixel32 &shadowColor, - const TPointD &shadowDirection, - double len, - double density) - : TSolidColorStyle(bgColor), m_shadowColor(shadowColor), m_shadowDirection(normalize(shadowDirection)), m_len(len), m_density(density) -{ -} +ShadowStyle::ShadowStyle(const TPixel32 &bgColor, const TPixel32 &shadowColor, + const TPointD &shadowDirection, double len, + double density) + : TSolidColorStyle(bgColor) + , m_shadowColor(shadowColor) + , m_shadowDirection(normalize(shadowDirection)) + , m_len(len) + , m_density(density) {} //------------------------------------------------------------ -TColorStyle *ShadowStyle::clone() const -{ - return new ShadowStyle(*this); -} +TColorStyle *ShadowStyle::clone() const { return new ShadowStyle(*this); } //------------------------------------------------------------ -void ShadowStyle::loadData(TInputStreamInterface &is) -{ - TSolidColorStyle::loadData(is); - is >> m_shadowDirection.x >> m_shadowDirection.y; - is >> m_density; - is >> m_shadowColor; - is >> m_len; +void ShadowStyle::loadData(TInputStreamInterface &is) { + TSolidColorStyle::loadData(is); + is >> m_shadowDirection.x >> m_shadowDirection.y; + is >> m_density; + is >> m_shadowColor; + is >> m_len; } //------------------------------------------------------------ -void ShadowStyle::saveData(TOutputStreamInterface &os) const -{ - TSolidColorStyle::saveData(os); - os << m_shadowDirection.x << m_shadowDirection.y; - os << m_density; - os << m_shadowColor; - os << m_len; +void ShadowStyle::saveData(TOutputStreamInterface &os) const { + TSolidColorStyle::saveData(os); + os << m_shadowDirection.x << m_shadowDirection.y; + os << m_density; + os << m_shadowColor; + os << m_len; } //------------------------------------------------------------ -int ShadowStyle::getParamCount() const -{ - return 3; -} +int ShadowStyle::getParamCount() const { return 3; } //----------------------------------------------------------------------------- -TColorStyle::ParamType ShadowStyle::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +TColorStyle::ParamType ShadowStyle::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -QString ShadowStyle::getParamNames(int index) const -{ - assert(0 <= index && index < 3); +QString ShadowStyle::getParamNames(int index) const { + assert(0 <= index && index < 3); - switch (index) { - case 0: - return QCoreApplication::translate("ShadowStyle", "Angle"); - case 1: - return QCoreApplication::translate("ShadowStyle", "Density"); - case 2: - return QCoreApplication::translate("ShadowStyle", "Length"); + switch (index) { + case 0: + return QCoreApplication::translate("ShadowStyle", "Angle"); + case 1: + return QCoreApplication::translate("ShadowStyle", "Density"); + case 2: + return QCoreApplication::translate("ShadowStyle", "Length"); - default: - return QString(); - } + default: + return QString(); + } - assert(0); - return QString(); + assert(0); + return QString(); } //----------------------------------------------------------------------------- -void ShadowStyle::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 3); - - switch (index) { - case 0: - min = 0.0; - max = 360.0; - break; - case 1: - min = 0.0; - max = 1.0; - break; - case 2: - min = 0.0; - max = 100.0; - break; - } +void ShadowStyle::getParamRange(int index, double &min, double &max) const { + assert(0 <= index && index < 3); + + switch (index) { + case 0: + min = 0.0; + max = 360.0; + break; + case 1: + min = 0.0; + max = 1.0; + break; + case 2: + min = 0.0; + max = 100.0; + break; + } } //----------------------------------------------------------------------------- -double ShadowStyle::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 3); +double ShadowStyle::getParamValue(TColorStyle::double_tag, int index) const { + assert(0 <= index && index < 3); - double degree; + double degree; - switch (index) { - case 0: - degree = asin(m_shadowDirection.y); - if (m_shadowDirection.x < 0) - degree = TConsts::pi - degree; - if (degree < 0) - degree += pi2; - return degree * TConsts::invOf_pi_180; + switch (index) { + case 0: + degree = asin(m_shadowDirection.y); + if (m_shadowDirection.x < 0) degree = M_PI - degree; + if (degree < 0) degree += M_2PI; + return degree * M_180_PI; - case 1: - return m_density; + case 1: + return m_density; - case 2: - return m_len; - } + case 2: + return m_len; + } - assert(0); - return 0.0; + assert(0); + return 0.0; } //----------------------------------------------------------------------------- -void ShadowStyle::setParamValue(int index, double value) -{ - assert(0 <= index && index < 3); - double degree; +void ShadowStyle::setParamValue(int index, double value) { + assert(0 <= index && index < 3); + double degree; - switch (index) { - case 0: - degree = value * TConsts::pi_180; - m_shadowDirection.x = cos(degree); - m_shadowDirection.y = sin(degree); - break; + switch (index) { + case 0: + degree = value * M_PI_180; + m_shadowDirection.x = cos(degree); + m_shadowDirection.y = sin(degree); + break; - case 1: - m_density = value; - break; + case 1: + m_density = value; + break; - case 2: - m_len = value; - break; - } + case 2: + m_len = value; + break; + } } //------------------------------------------------------------ -void ShadowStyle::drawPolyline(const TColorFunction *cf, std::vector &polyline, TPointD shadowDirection) const -{ - int i; - int stepNumber; - double distance; +void ShadowStyle::drawPolyline(const TColorFunction *cf, + std::vector &polyline, + TPointD shadowDirection) const { + int i; + int stepNumber; + double distance; - TPointD v1, v2, diff, midPoint, ratio; - double len; + TPointD v1, v2, diff, midPoint, ratio; + double len; - TPixel32 color; - if (cf) - color = (*(cf))(m_shadowColor); - else - color = m_shadowColor; + TPixel32 color; + if (cf) + color = (*(cf))(m_shadowColor); + else + color = m_shadowColor; - tglColor(color); + tglColor(color); - //glEnable(GL_BLEND); - //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - //// <-- tglEnableBlending(); + // glEnable(GL_BLEND); + // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + //// <-- tglEnableBlending(); - TRegionOutline::PointVector::iterator it; - TRegionOutline::PointVector::iterator it_b = polyline.begin(); - TRegionOutline::PointVector::iterator it_e = polyline.end(); + TRegionOutline::PointVector::iterator it; + TRegionOutline::PointVector::iterator it_b = polyline.begin(); + TRegionOutline::PointVector::iterator it_e = polyline.end(); - v1.x = polyline.back().x; - v1.y = polyline.back().y; + v1.x = polyline.back().x; + v1.y = polyline.back().y; - for (it = it_b; it != it_e; ++it) { - v2.x = it->x; - v2.y = it->y; - if (v1 == v2) - continue; + for (it = it_b; it != it_e; ++it) { + v2.x = it->x; + v2.y = it->y; + if (v1 == v2) continue; - diff = normalize(rotate90(v2 - v1)); - len = diff * shadowDirection; + diff = normalize(rotate90(v2 - v1)); + len = diff * shadowDirection; - if (len > 0) { - distance = tdistance(v1, v2) * m_density; + if (len > 0) { + distance = tdistance(v1, v2) * m_density; - ratio = (v2 - v1) * (1.0 / distance); - midPoint = v1; - stepNumber = (int)distance; + ratio = (v2 - v1) * (1.0 / distance); + midPoint = v1; + stepNumber = (int)distance; - for (i = 0; i < stepNumber; i++) { - glBegin(GL_LINE_STRIP); + for (i = 0; i < stepNumber; i++) { + glBegin(GL_LINE_STRIP); - tglColor(TPixel32(color.r, color.g, color.b, 0)); - tglVertex(midPoint); + tglColor(TPixel32(color.r, color.g, color.b, 0)); + tglVertex(midPoint); - tglColor(color); - tglVertex(midPoint + (shadowDirection * len * m_len * 0.5)); + tglColor(color); + tglVertex(midPoint + (shadowDirection * len * m_len * 0.5)); - tglColor(TPixel32(color.r, color.g, color.b, 0)); - tglVertex(midPoint + (shadowDirection * len * m_len)); + tglColor(TPixel32(color.r, color.g, color.b, 0)); + tglVertex(midPoint + (shadowDirection * len * m_len)); - midPoint += ratio; + midPoint += ratio; - glEnd(); - } - } + glEnd(); + } + } - v1 = v2; - } - //tglColor(TPixel32::White); + v1 = v2; + } + // tglColor(TPixel32::White); } //------------------------------------------------------------ void ShadowStyle::drawRegion(const TColorFunction *cf, const bool antiAliasing, - TRegionOutline ®ionOutline) const -{ - TStencilControl *stenc = TStencilControl::instance(); - - TPixel32 backgroundColor = TSolidColorStyle::getMainColor(); - if (cf) - backgroundColor = (*(cf))(backgroundColor); - - ////stenc->beginMask(); - /* - glBegin(GL_QUADS); - glVertex2d (regionOutline.m_bbox.getP00().x, regionOutline.m_bbox.getP00().y); - glVertex2d (regionOutline.m_bbox.getP01().x, regionOutline.m_bbox.getP01().y); - glVertex2d (regionOutline.m_bbox.getP11().x, regionOutline.m_bbox.getP11().y); - glVertex2d (regionOutline.m_bbox.getP10().x, regionOutline.m_bbox.getP10().y); - glEnd(); - */ - ////stenc->endMask(); - ////stenc->enableMask(TStencilControl::SHOW_INSIDE); + TRegionOutline ®ionOutline) const { + TStencilControl *stenc = TStencilControl::instance(); + + TPixel32 backgroundColor = TSolidColorStyle::getMainColor(); + if (cf) backgroundColor = (*(cf))(backgroundColor); + + ////stenc->beginMask(); + /* +glBegin(GL_QUADS); +glVertex2d (regionOutline.m_bbox.getP00().x, regionOutline.m_bbox.getP00().y); +glVertex2d (regionOutline.m_bbox.getP01().x, regionOutline.m_bbox.getP01().y); +glVertex2d (regionOutline.m_bbox.getP11().x, regionOutline.m_bbox.getP11().y); +glVertex2d (regionOutline.m_bbox.getP10().x, regionOutline.m_bbox.getP10().y); +glEnd(); +*/ + ////stenc->endMask(); + ////stenc->enableMask(TStencilControl::SHOW_INSIDE); - if (backgroundColor.m == 0) { //only to create stencil mask - TSolidColorStyle appStyle(TPixel32::White); - stenc->beginMask(); - appStyle.drawRegion(0, false, regionOutline); - } else { - stenc->beginMask(TStencilControl::DRAW_ALSO_ON_SCREEN); - TSolidColorStyle::drawRegion(cf, antiAliasing, regionOutline); - } - stenc->endMask(); - stenc->enableMask(TStencilControl::SHOW_INSIDE); + if (backgroundColor.m == 0) { // only to create stencil mask + TSolidColorStyle appStyle(TPixel32::White); + stenc->beginMask(); + appStyle.drawRegion(0, false, regionOutline); + } else { + stenc->beginMask(TStencilControl::DRAW_ALSO_ON_SCREEN); + TSolidColorStyle::drawRegion(cf, antiAliasing, regionOutline); + } + stenc->endMask(); + stenc->enableMask(TStencilControl::SHOW_INSIDE); - TRegionOutline::Boundary::iterator regions_it; - TRegionOutline::Boundary::iterator regions_it_b = regionOutline.m_exterior.begin(); - TRegionOutline::Boundary::iterator regions_it_e = regionOutline.m_exterior.end(); - for (regions_it = regions_it_b; regions_it != regions_it_e; ++regions_it) - drawPolyline(cf, *regions_it, m_shadowDirection); + TRegionOutline::Boundary::iterator regions_it; + TRegionOutline::Boundary::iterator regions_it_b = + regionOutline.m_exterior.begin(); + TRegionOutline::Boundary::iterator regions_it_e = + regionOutline.m_exterior.end(); + for (regions_it = regions_it_b; regions_it != regions_it_e; ++regions_it) + drawPolyline(cf, *regions_it, m_shadowDirection); - stenc->enableMask(TStencilControl::SHOW_OUTSIDE); + stenc->enableMask(TStencilControl::SHOW_OUTSIDE); - regions_it_b = regionOutline.m_interior.begin(); - regions_it_e = regionOutline.m_interior.end(); + regions_it_b = regionOutline.m_interior.begin(); + regions_it_e = regionOutline.m_interior.end(); - for (regions_it = regions_it_b; regions_it != regions_it_e; ++regions_it) - drawPolyline(cf, *regions_it, -m_shadowDirection); + for (regions_it = regions_it_b; regions_it != regions_it_e; ++regions_it) + drawPolyline(cf, *regions_it, -m_shadowDirection); - //tglColor(TPixel32::White); + // tglColor(TPixel32::White); - stenc->disableMask(); + stenc->disableMask(); } //------------------------------------------------------------ /* int ShadowStyle::drawPolyline(TFlash& flash, std::vector &polyline, - TPointD shadowDirection, const bool isDraw) const + TPointD +shadowDirection, const bool isDraw) const { int i; int stepNumber; double distance; - + TPointD v1,v2,diff,midPoint,ratio; double len; - + TRegionOutline::PointVector::iterator it; TRegionOutline::PointVector::iterator it_b = polyline.begin(); - TRegionOutline::PointVector::iterator it_e = polyline.end(); - - + TRegionOutline::PointVector::iterator it_e = polyline.end(); + + std::vector segmentArray; v1.x = polyline.back().x; @@ -517,19 +482,19 @@ int ShadowStyle::drawPolyline(TFlash& flash, std::vector &polyline, stepNumber= (int)distance; for(i=0; i sa; + { + std::vector sa; - TPointD p0=midPoint; - TPointD p1=midPoint+(shadowDirection*len*m_len*0.5); - TPointD p2=midPoint+(shadowDirection*len*m_len); + TPointD p0=midPoint; + TPointD p1=midPoint+(shadowDirection*len*m_len*0.5); + TPointD p2=midPoint+(shadowDirection*len*m_len); - segmentArray.push_back(TSegment(p1,p0)); - segmentArray.push_back(TSegment(p1,p2)); + segmentArray.push_back(TSegment(p1,p0)); + segmentArray.push_back(TSegment(p1,p2)); midPoint += ratio; } - + } v1=v2; @@ -537,12 +502,12 @@ int ShadowStyle::drawPolyline(TFlash& flash, std::vector &polyline, if ( isDraw && segmentArray.size()>0 ) { - flash.setLineColor(m_shadowColor); - flash.drawSegments(segmentArray, true); + flash.setLineColor(m_shadowColor); + flash.drawSegments(segmentArray, true); } if ( segmentArray.size()>0 ) - return 1; + return 1; return 0; } @@ -552,34 +517,35 @@ void ShadowStyle::drawRegion( TFlash& flash, const TRegion* r) const rdf.computeRegionOutline(); TRegionOutline::Boundary::iterator regions_it; - TRegionOutline::Boundary::iterator regions_it_b = rdf.m_ro.m_exterior->begin(); - TRegionOutline::Boundary::iterator regions_it_e = rdf.m_ro.m_exterior->end(); + TRegionOutline::Boundary::iterator regions_it_b = +rdf.m_ro.m_exterior->begin(); + TRegionOutline::Boundary::iterator regions_it_e = rdf.m_ro.m_exterior->end(); + - // In the GL version the shadow lines are not croped into the filled region. -// This is the reason why I don't calculate the number of shadow lines. +// This is the reason why I don't calculate the number of shadow lines. // int nbDraw=0; // for( regions_it = regions_it_b ; regions_it!= regions_it_e; ++regions_it) // nbDraw+=drawPolyline(flash,*regions_it, m_shadowDirection,false); // regions_it_b = rdf.m_ro.m_interior->begin(); -// regions_it_e = rdf.m_ro.m_interior->end(); +// regions_it_e = rdf.m_ro.m_interior->end(); // for( regions_it = regions_it_b ; regions_it!= regions_it_e; ++regions_it) // nbDraw+=drawPolyline(flash,*regions_it,-m_shadowDirection,false); // Only the bbox rectangle is croped. - flash.drawRegion(*r,1); + flash.drawRegion(*r,1); flash.setFillColor(getMainColor()); flash.drawRectangle(rdf.m_ro.m_bbox); regions_it_b = rdf.m_ro.m_exterior->begin(); - regions_it_e = rdf.m_ro.m_exterior->end(); + regions_it_e = rdf.m_ro.m_exterior->end(); for( regions_it = regions_it_b ; regions_it!= regions_it_e; ++regions_it) - drawPolyline(flash,*regions_it, m_shadowDirection); + drawPolyline(flash,*regions_it, m_shadowDirection); regions_it_b = rdf.m_ro.m_interior->begin(); - regions_it_e = rdf.m_ro.m_interior->end(); + regions_it_e = rdf.m_ro.m_interior->end(); for( regions_it = regions_it_b ; regions_it!= regions_it_e; ++regions_it) drawPolyline(flash,*regions_it,-m_shadowDirection); @@ -589,510 +555,482 @@ void ShadowStyle::drawRegion( TFlash& flash, const TRegion* r) const //------------------------------------------------------------ -TPixel32 ShadowStyle::getColorParamValue(int index) const -{ - return index == 0 ? m_shadowColor : TSolidColorStyle::getMainColor(); +TPixel32 ShadowStyle::getColorParamValue(int index) const { + return index == 0 ? m_shadowColor : TSolidColorStyle::getMainColor(); } //------------------------------------------------------------ -void ShadowStyle::setColorParamValue(int index, const TPixel32 &color) -{ - if (index == 0) - m_shadowColor = color; - else { - TSolidColorStyle::setMainColor(color); - } +void ShadowStyle::setColorParamValue(int index, const TPixel32 &color) { + if (index == 0) + m_shadowColor = color; + else { + TSolidColorStyle::setMainColor(color); + } } //------------------------------------------------------------ -void ShadowStyle::makeIcon(const TDimension &d) -{ - double oldVal = getParamValue(TColorStyle::double_tag(), 1); - setParamValue(1, oldVal * 0.25); - TColorStyle::makeIcon(d); - setParamValue(1, oldVal); +void ShadowStyle::makeIcon(const TDimension &d) { + double oldVal = getParamValue(TColorStyle::double_tag(), 1); + setParamValue(1, oldVal * 0.25); + TColorStyle::makeIcon(d); + setParamValue(1, oldVal); } //*************************************************************************** // ShadowStyle2 implementation //*************************************************************************** -ShadowStyle2::ShadowStyle2(const TPixel32 &bgColor, - const TPixel32 &shadowColor, - const TPointD &shadowDirection, - double shadowLength) - : TSolidColorStyle(bgColor), m_shadowColor(shadowColor), m_shadowLength(shadowLength), m_shadowDirection(normalize(shadowDirection)) -{ -} +ShadowStyle2::ShadowStyle2(const TPixel32 &bgColor, const TPixel32 &shadowColor, + const TPointD &shadowDirection, double shadowLength) + : TSolidColorStyle(bgColor) + , m_shadowColor(shadowColor) + , m_shadowLength(shadowLength) + , m_shadowDirection(normalize(shadowDirection)) {} //------------------------------------------------------------ -TColorStyle *ShadowStyle2::clone() const -{ - return new ShadowStyle2(*this); -} +TColorStyle *ShadowStyle2::clone() const { return new ShadowStyle2(*this); } //------------------------------------------------------------ -void ShadowStyle2::loadData(TInputStreamInterface &is) -{ - TSolidColorStyle::loadData(is); - is >> m_shadowDirection.x >> m_shadowDirection.y; - is >> m_shadowLength; - is >> m_shadowColor; +void ShadowStyle2::loadData(TInputStreamInterface &is) { + TSolidColorStyle::loadData(is); + is >> m_shadowDirection.x >> m_shadowDirection.y; + is >> m_shadowLength; + is >> m_shadowColor; } //------------------------------------------------------------ -void ShadowStyle2::saveData(TOutputStreamInterface &os) const -{ - TSolidColorStyle::saveData(os); - os << m_shadowDirection.x << m_shadowDirection.y; - os << m_shadowLength; - os << m_shadowColor; +void ShadowStyle2::saveData(TOutputStreamInterface &os) const { + TSolidColorStyle::saveData(os); + os << m_shadowDirection.x << m_shadowDirection.y; + os << m_shadowLength; + os << m_shadowColor; } //------------------------------------------------------------ -int ShadowStyle2::getParamCount() const -{ - return 2; -} +int ShadowStyle2::getParamCount() const { return 2; } //----------------------------------------------------------------------------- -TColorStyle::ParamType ShadowStyle2::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +TColorStyle::ParamType ShadowStyle2::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -QString ShadowStyle2::getParamNames(int index) const -{ - assert(0 <= index && index < 2); +QString ShadowStyle2::getParamNames(int index) const { + assert(0 <= index && index < 2); - return index == 0 ? QCoreApplication::translate("ShadowStyle2", "Angle") : QCoreApplication::translate("ShadowStyle2", "Size"); + return index == 0 ? QCoreApplication::translate("ShadowStyle2", "Angle") + : QCoreApplication::translate("ShadowStyle2", "Size"); } //----------------------------------------------------------------------------- -void ShadowStyle2::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 2); - if (index == 0) { - min = 0.0; - max = 360.0; - } else { - min = 0.0; - max = 500.0; - } +void ShadowStyle2::getParamRange(int index, double &min, double &max) const { + assert(0 <= index && index < 2); + if (index == 0) { + min = 0.0; + max = 360.0; + } else { + min = 0.0; + max = 500.0; + } } //----------------------------------------------------------------------------- -double ShadowStyle2::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 2); +double ShadowStyle2::getParamValue(TColorStyle::double_tag, int index) const { + assert(0 <= index && index < 2); - if (index == 1) - return m_shadowLength; + if (index == 1) return m_shadowLength; - double degree = asin(m_shadowDirection.y); - if (m_shadowDirection.x < 0) - degree = TConsts::pi - degree; + double degree = asin(m_shadowDirection.y); + if (m_shadowDirection.x < 0) degree = M_PI - degree; - if (degree < 0) - degree += pi2; + if (degree < 0) degree += M_2PI; - return degree * TConsts::invOf_pi_180; + return degree * M_180_PI; } //----------------------------------------------------------------------------- -int nbDiffVerts(const std::vector &pv) -{ - std::vector lpv; - bool isMissing[4] = {true, true, true, true}; - if (pv.size() == 0) - return 0; - lpv.push_back(pv[0]); - isMissing[0] = false; - for (int i = 1; i < (int)pv.size(); i++) { - bool isDiff = true; - for (int j = 0; j < (int)lpv.size() && isDiff; j++) - isDiff = lpv[j] == pv[i] ? false : isDiff; - if (isDiff) { - lpv.push_back(pv[i]); - isMissing[i] = false; - } - } - return lpv.size(); -} - -void ShadowStyle2::setParamValue(int index, double value) -{ - assert(0 <= index && index < 2); +int nbDiffVerts(const std::vector &pv) { + std::vector lpv; + bool isMissing[4] = {true, true, true, true}; + if (pv.size() == 0) return 0; + lpv.push_back(pv[0]); + isMissing[0] = false; + for (int i = 1; i < (int)pv.size(); i++) { + bool isDiff = true; + for (int j = 0; j < (int)lpv.size() && isDiff; j++) + isDiff = lpv[j] == pv[i] ? false : isDiff; + if (isDiff) { + lpv.push_back(pv[i]); + isMissing[i] = false; + } + } + return lpv.size(); +} + +void ShadowStyle2::setParamValue(int index, double value) { + assert(0 <= index && index < 2); - if (index == 1) { - m_shadowLength = value; - } else { - double degree = value * TConsts::pi_180; - m_shadowDirection.x = cos(degree); - m_shadowDirection.y = sin(degree); - } + if (index == 1) { + m_shadowLength = value; + } else { + double degree = value * M_PI_180; + m_shadowDirection.x = cos(degree); + m_shadowDirection.y = sin(degree); + } } //------------------------------------------------------------ -namespace -{ +namespace { -void drawShadowLine(TPixel32 shadowColor, TPixel32 color, TPointD v1, TPointD v2, TPointD diff1, TPointD diff2) -{ - v1 = v1 + diff1; - v2 = v2 + diff2; - diff1 = -diff1; - diff2 = -diff2; +void drawShadowLine(TPixel32 shadowColor, TPixel32 color, TPointD v1, + TPointD v2, TPointD diff1, TPointD diff2) { + v1 = v1 + diff1; + v2 = v2 + diff2; + diff1 = -diff1; + diff2 = -diff2; - double r1, r2; - double t = 0.0; + double r1, r2; + double t = 0.0; - glBegin(GL_QUAD_STRIP); + glBegin(GL_QUAD_STRIP); - for (; t <= 1; t += 0.1) { - r1 = t * t * t; - r2 = 1 - r1; + for (; t <= 1; t += 0.1) { + r1 = t * t * t; + r2 = 1 - r1; - TPixel32 c((int)(color.r * r2 + shadowColor.r * r1), - (int)(color.g * r2 + shadowColor.g * r1), - (int)(color.b * r2 + shadowColor.b * r1), - (int)(color.m * r2 + shadowColor.m * r1)); - tglColor(c); - tglVertex(v1 + t * diff1); - tglVertex(v2 + t * diff2); - } + TPixel32 c((int)(color.r * r2 + shadowColor.r * r1), + (int)(color.g * r2 + shadowColor.g * r1), + (int)(color.b * r2 + shadowColor.b * r1), + (int)(color.m * r2 + shadowColor.m * r1)); + tglColor(c); + tglVertex(v1 + t * diff1); + tglVertex(v2 + t * diff2); + } - glEnd(); + glEnd(); } int drawShadowLine(TFlash &flash, TPixel32 shadowColor, TPixel32 color, - TPointD v1, TPointD v2, TPointD diff1, TPointD diff2, - const bool isDraw = true) -{ - int nbDraw = 0; - - v1 = v1 + diff1; - v2 = v2 + diff2; - diff1 = -diff1; - diff2 = -diff2; - - TPointD vv1, vv2, ovv1, ovv2; - TPixel32 oc; - double r1, r2; - double t = 0.0; - bool isFirst = true; - flash.setThickness(0.0); - SFlashUtils sfu; - for (; t <= 1; t += 0.1) { - if (isFirst) { - r1 = t * t * t; - r2 = 1 - r1; - oc = TPixel32((int)(color.r * r2 + shadowColor.r * r1), - (int)(color.g * r2 + shadowColor.g * r1), - (int)(color.b * r2 + shadowColor.b * r1), - (int)(color.m * r2 + shadowColor.m * r1)); - ovv1 = v1 + t * diff1; - ovv2 = v2 + t * diff2; - isFirst = false; - } else { - r1 = t * t * t; - r2 = 1 - r1; - TPixel32 c((int)(color.r * r2 + shadowColor.r * r1), - (int)(color.g * r2 + shadowColor.g * r1), - (int)(color.b * r2 + shadowColor.b * r1), - (int)(color.m * r2 + shadowColor.m * r1)); - vv1 = (v1 + t * diff1); - vv2 = (v2 + t * diff2); - - std::vector pv; - pv.push_back(ovv1); - pv.push_back(ovv2); - pv.push_back(vv2); - pv.push_back(vv1); - - int nbDV = nbDiffVerts(pv); - if (nbDV >= 3 && nbDV <= 4) - nbDraw++; - - if (isDraw) - sfu.drawGradedPolyline(flash, pv, oc, c); - - oc = c; - ovv1 = vv1; - ovv2 = vv2; - } - } - return nbDraw; -} -} - -//------------------------------------------------------------ - -void ShadowStyle2::drawPolyline(const TColorFunction *cf, const std::vector &polyline, TPointD shadowDirection) const -{ - if (polyline.empty()) - return; - TPointD v0, v1, diff; - double len1, len2; - - TPixel32 color, shadowColor; - - if (cf) - color = (*(cf))(TSolidColorStyle::getMainColor()); - else - color = TSolidColorStyle::getMainColor(); - - if (cf) - shadowColor = (*(cf))(m_shadowColor); - else - shadowColor = m_shadowColor; - - tglColor(shadowColor); - - //glEnable(GL_BLEND); - //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - //// <-- tglEnableBlending(); - TRegionOutline::PointVector::const_iterator it; - TRegionOutline::PointVector::const_iterator it_b = polyline.begin(); - TRegionOutline::PointVector::const_iterator it_e = polyline.end(); - - int size = polyline.size(); - std::vector lens(size); - v0.x = polyline.back().x; - v0.y = polyline.back().y; - int count = 0; - for (it = it_b; it != it_e; ++it) { - v1.x = it->x; - v1.y = it->y; - if (v1 != v0) { - diff = normalize(rotate90(v1 - v0)); - len1 = diff * shadowDirection; - if (len1 < 0) - len1 = 0; - lens[count++] = len1; - } else - lens[count++] = 0; - - v0 = v1; - } - - double firstVal = lens.front(); - for (count = 0; count != size - 1; count++) { - lens[count] = (lens[count] + lens[count + 1]) * 0.5; - } - lens[size - 1] = (lens[size - 1] + firstVal) * 0.5; - - for (count = 0; count != size - 1; count++) { - v0.x = polyline[count].x; - v0.y = polyline[count].y; - v1.x = polyline[count + 1].x; - v1.y = polyline[count + 1].y; - len1 = lens[count]; - len2 = lens[count + 1]; - - if (v0 != v1 && len1 >= 0 && len2 >= 0 && (len1 + len2) > 0) - drawShadowLine(shadowColor, color, v0, v1, shadowDirection * len1 * m_shadowLength, shadowDirection * len2 * m_shadowLength); - } - v0.x = polyline[count].x; - v0.y = polyline[count].y; - v1.x = polyline.front().x; - v1.y = polyline.front().y; - len1 = lens[count]; - len2 = lens[0]; - if (v0 != v1 && len1 >= 0 && len2 >= 0 && (len1 + len2) > 0) - drawShadowLine(shadowColor, color, v0, v1, shadowDirection * len1 * m_shadowLength, shadowDirection * len2 * m_shadowLength); - - //tglColor(TPixel32::White); -} - -//------------------------------------------------------------ - -TPixel32 ShadowStyle2::getColorParamValue(int index) const -{ - return index == 0 ? m_shadowColor : TSolidColorStyle::getMainColor(); + TPointD v1, TPointD v2, TPointD diff1, TPointD diff2, + const bool isDraw = true) { + int nbDraw = 0; + + v1 = v1 + diff1; + v2 = v2 + diff2; + diff1 = -diff1; + diff2 = -diff2; + + TPointD vv1, vv2, ovv1, ovv2; + TPixel32 oc; + double r1, r2; + double t = 0.0; + bool isFirst = true; + flash.setThickness(0.0); + SFlashUtils sfu; + for (; t <= 1; t += 0.1) { + if (isFirst) { + r1 = t * t * t; + r2 = 1 - r1; + oc = TPixel32((int)(color.r * r2 + shadowColor.r * r1), + (int)(color.g * r2 + shadowColor.g * r1), + (int)(color.b * r2 + shadowColor.b * r1), + (int)(color.m * r2 + shadowColor.m * r1)); + ovv1 = v1 + t * diff1; + ovv2 = v2 + t * diff2; + isFirst = false; + } else { + r1 = t * t * t; + r2 = 1 - r1; + TPixel32 c((int)(color.r * r2 + shadowColor.r * r1), + (int)(color.g * r2 + shadowColor.g * r1), + (int)(color.b * r2 + shadowColor.b * r1), + (int)(color.m * r2 + shadowColor.m * r1)); + vv1 = (v1 + t * diff1); + vv2 = (v2 + t * diff2); + + std::vector pv; + pv.push_back(ovv1); + pv.push_back(ovv2); + pv.push_back(vv2); + pv.push_back(vv1); + + int nbDV = nbDiffVerts(pv); + if (nbDV >= 3 && nbDV <= 4) nbDraw++; + + if (isDraw) sfu.drawGradedPolyline(flash, pv, oc, c); + + oc = c; + ovv1 = vv1; + ovv2 = vv2; + } + } + return nbDraw; +} } //------------------------------------------------------------ -void ShadowStyle2::setColorParamValue(int index, const TPixel32 &color) -{ - if (index == 0) - m_shadowColor = color; - else { - TSolidColorStyle::setMainColor(color); - } +void ShadowStyle2::drawPolyline(const TColorFunction *cf, + const std::vector &polyline, + TPointD shadowDirection) const { + if (polyline.empty()) return; + TPointD v0, v1, diff; + double len1, len2; + + TPixel32 color, shadowColor; + + if (cf) + color = (*(cf))(TSolidColorStyle::getMainColor()); + else + color = TSolidColorStyle::getMainColor(); + + if (cf) + shadowColor = (*(cf))(m_shadowColor); + else + shadowColor = m_shadowColor; + + tglColor(shadowColor); + + // glEnable(GL_BLEND); + // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + //// <-- tglEnableBlending(); + TRegionOutline::PointVector::const_iterator it; + TRegionOutline::PointVector::const_iterator it_b = polyline.begin(); + TRegionOutline::PointVector::const_iterator it_e = polyline.end(); + + int size = polyline.size(); + std::vector lens(size); + v0.x = polyline.back().x; + v0.y = polyline.back().y; + int count = 0; + for (it = it_b; it != it_e; ++it) { + v1.x = it->x; + v1.y = it->y; + if (v1 != v0) { + diff = normalize(rotate90(v1 - v0)); + len1 = diff * shadowDirection; + if (len1 < 0) len1 = 0; + lens[count++] = len1; + } else + lens[count++] = 0; + + v0 = v1; + } + + double firstVal = lens.front(); + for (count = 0; count != size - 1; count++) { + lens[count] = (lens[count] + lens[count + 1]) * 0.5; + } + lens[size - 1] = (lens[size - 1] + firstVal) * 0.5; + + for (count = 0; count != size - 1; count++) { + v0.x = polyline[count].x; + v0.y = polyline[count].y; + v1.x = polyline[count + 1].x; + v1.y = polyline[count + 1].y; + len1 = lens[count]; + len2 = lens[count + 1]; + + if (v0 != v1 && len1 >= 0 && len2 >= 0 && (len1 + len2) > 0) + drawShadowLine(shadowColor, color, v0, v1, + shadowDirection * len1 * m_shadowLength, + shadowDirection * len2 * m_shadowLength); + } + v0.x = polyline[count].x; + v0.y = polyline[count].y; + v1.x = polyline.front().x; + v1.y = polyline.front().y; + len1 = lens[count]; + len2 = lens[0]; + if (v0 != v1 && len1 >= 0 && len2 >= 0 && (len1 + len2) > 0) + drawShadowLine(shadowColor, color, v0, v1, + shadowDirection * len1 * m_shadowLength, + shadowDirection * len2 * m_shadowLength); + + // tglColor(TPixel32::White); } //------------------------------------------------------------ -void ShadowStyle2::drawRegion(const TColorFunction *cf, const bool antiAliasing, - TRegionOutline &boundary) const -{ - TStencilControl *stenc = TStencilControl::instance(); - TPixel32 backgroundColor = TSolidColorStyle::getMainColor(); - if (cf) - backgroundColor = (*(cf))(backgroundColor); +TPixel32 ShadowStyle2::getColorParamValue(int index) const { + return index == 0 ? m_shadowColor : TSolidColorStyle::getMainColor(); +} + +//------------------------------------------------------------ + +void ShadowStyle2::setColorParamValue(int index, const TPixel32 &color) { + if (index == 0) + m_shadowColor = color; + else { + TSolidColorStyle::setMainColor(color); + } +} + +//------------------------------------------------------------ - if (backgroundColor.m == 0) { //only to create stencil mask - TSolidColorStyle appStyle(TPixel32::White); - stenc->beginMask(); //does not draw on screen - appStyle.drawRegion(0, false, boundary); - } else { //create stencil mask and draw on screen - stenc->beginMask(TStencilControl::DRAW_ALSO_ON_SCREEN); - TSolidColorStyle::drawRegion(cf, antiAliasing, boundary); - } - stenc->endMask(); +void ShadowStyle2::drawRegion(const TColorFunction *cf, const bool antiAliasing, + TRegionOutline &boundary) const { + TStencilControl *stenc = TStencilControl::instance(); + TPixel32 backgroundColor = TSolidColorStyle::getMainColor(); + if (cf) backgroundColor = (*(cf))(backgroundColor); + + if (backgroundColor.m == 0) { // only to create stencil mask + TSolidColorStyle appStyle(TPixel32::White); + stenc->beginMask(); // does not draw on screen + appStyle.drawRegion(0, false, boundary); + } else { // create stencil mask and draw on screen + stenc->beginMask(TStencilControl::DRAW_ALSO_ON_SCREEN); + TSolidColorStyle::drawRegion(cf, antiAliasing, boundary); + } + stenc->endMask(); - stenc->enableMask(TStencilControl::SHOW_INSIDE); + stenc->enableMask(TStencilControl::SHOW_INSIDE); - TRegionOutline::Boundary::iterator regions_it; - TRegionOutline::Boundary::iterator regions_it_b = boundary.m_exterior.begin(); - TRegionOutline::Boundary::iterator regions_it_e = boundary.m_exterior.end(); + TRegionOutline::Boundary::iterator regions_it; + TRegionOutline::Boundary::iterator regions_it_b = boundary.m_exterior.begin(); + TRegionOutline::Boundary::iterator regions_it_e = boundary.m_exterior.end(); - for (regions_it = regions_it_b; regions_it != regions_it_e; ++regions_it) - drawPolyline(cf, *regions_it, m_shadowDirection); + for (regions_it = regions_it_b; regions_it != regions_it_e; ++regions_it) + drawPolyline(cf, *regions_it, m_shadowDirection); - //tglColor(TPixel32::White); + // tglColor(TPixel32::White); - stenc->disableMask(); + stenc->disableMask(); } //------------------------------------------------------------ int ShadowStyle2::drawPolyline(TFlash &flash, std::vector &polyline, - TPointD shadowDirection, const bool isDraw) const -{ - int nbDraw = 0; - - TPointD v0, v1, diff; - double len1, len2; - TPixel32 color, shadowColor; - color = TSolidColorStyle::getMainColor(); - shadowColor = m_shadowColor; - - TRegionOutline::PointVector::iterator it; - TRegionOutline::PointVector::iterator it_b = polyline.begin(); - TRegionOutline::PointVector::iterator it_e = polyline.end(); - - int size = polyline.size(); - std::vector lens(size); - v0.x = polyline.back().x; - v0.y = polyline.back().y; - int count = 0; - for (it = it_b; it != it_e; ++it) { - v1.x = it->x; - v1.y = it->y; - if (v1 != v0) { - diff = normalize(rotate90(v1 - v0)); - len1 = diff * shadowDirection; - if (len1 < 0) - len1 = 0; - lens[count++] = len1; - } else - lens[count++] = 0; - - v0 = v1; - } - - double firstVal = lens.front(); - for (count = 0; count != size - 1; count++) { - lens[count] = (lens[count] + lens[count + 1]) * 0.5; - } - lens[size - 1] = (lens[size - 1] + firstVal) * 0.5; - - for (count = 0; count != size - 1; count++) { - v0.x = polyline[count].x; - v0.y = polyline[count].y; - v1.x = polyline[count + 1].x; - v1.y = polyline[count + 1].y; - len1 = lens[count]; - len2 = lens[count + 1]; - - if (v0 != v1 && len1 >= 0 && len2 >= 0 && (len1 + len2) > 0) - nbDraw += drawShadowLine(flash, shadowColor, color, v0, v1, shadowDirection * len1 * m_shadowLength, - shadowDirection * len2 * m_shadowLength, isDraw); - } - v0.x = polyline[count].x; - v0.y = polyline[count].y; - v1.x = polyline.front().x; - v1.y = polyline.front().y; - len1 = lens[count]; - len2 = lens[0]; - if (v0 != v1 && len1 >= 0 && len2 >= 0 && (len1 + len2) > 0) - nbDraw += drawShadowLine(flash, shadowColor, color, v0, v1, shadowDirection * len1 * m_shadowLength, - shadowDirection * len2 * m_shadowLength, isDraw); - - return nbDraw; -} - -//------------------------------------------------------------ - -void ShadowStyle2::drawRegion(TFlash &flash, const TRegion *r) const -{ - SFlashUtils rdf(r); - rdf.computeRegionOutline(); + TPointD shadowDirection, + const bool isDraw) const { + int nbDraw = 0; + + TPointD v0, v1, diff; + double len1, len2; + TPixel32 color, shadowColor; + color = TSolidColorStyle::getMainColor(); + shadowColor = m_shadowColor; + + TRegionOutline::PointVector::iterator it; + TRegionOutline::PointVector::iterator it_b = polyline.begin(); + TRegionOutline::PointVector::iterator it_e = polyline.end(); + + int size = polyline.size(); + std::vector lens(size); + v0.x = polyline.back().x; + v0.y = polyline.back().y; + int count = 0; + for (it = it_b; it != it_e; ++it) { + v1.x = it->x; + v1.y = it->y; + if (v1 != v0) { + diff = normalize(rotate90(v1 - v0)); + len1 = diff * shadowDirection; + if (len1 < 0) len1 = 0; + lens[count++] = len1; + } else + lens[count++] = 0; + + v0 = v1; + } + + double firstVal = lens.front(); + for (count = 0; count != size - 1; count++) { + lens[count] = (lens[count] + lens[count + 1]) * 0.5; + } + lens[size - 1] = (lens[size - 1] + firstVal) * 0.5; + + for (count = 0; count != size - 1; count++) { + v0.x = polyline[count].x; + v0.y = polyline[count].y; + v1.x = polyline[count + 1].x; + v1.y = polyline[count + 1].y; + len1 = lens[count]; + len2 = lens[count + 1]; + + if (v0 != v1 && len1 >= 0 && len2 >= 0 && (len1 + len2) > 0) + nbDraw += drawShadowLine(flash, shadowColor, color, v0, v1, + shadowDirection * len1 * m_shadowLength, + shadowDirection * len2 * m_shadowLength, isDraw); + } + v0.x = polyline[count].x; + v0.y = polyline[count].y; + v1.x = polyline.front().x; + v1.y = polyline.front().y; + len1 = lens[count]; + len2 = lens[0]; + if (v0 != v1 && len1 >= 0 && len2 >= 0 && (len1 + len2) > 0) + nbDraw += drawShadowLine(flash, shadowColor, color, v0, v1, + shadowDirection * len1 * m_shadowLength, + shadowDirection * len2 * m_shadowLength, isDraw); + + return nbDraw; +} + +//------------------------------------------------------------ + +void ShadowStyle2::drawRegion(TFlash &flash, const TRegion *r) const { + SFlashUtils rdf(r); + rdf.computeRegionOutline(); - TRegionOutline::Boundary::iterator regions_it; - TRegionOutline::Boundary::iterator regions_it_b = rdf.m_ro.m_exterior.begin(); - TRegionOutline::Boundary::iterator regions_it_e = rdf.m_ro.m_exterior.end(); + TRegionOutline::Boundary::iterator regions_it; + TRegionOutline::Boundary::iterator regions_it_b = rdf.m_ro.m_exterior.begin(); + TRegionOutline::Boundary::iterator regions_it_e = rdf.m_ro.m_exterior.end(); - int nbDraw = 0; - for (regions_it = regions_it_b; regions_it != regions_it_e; ++regions_it) - nbDraw += drawPolyline(flash, *regions_it, m_shadowDirection, false); + int nbDraw = 0; + for (regions_it = regions_it_b; regions_it != regions_it_e; ++regions_it) + nbDraw += drawPolyline(flash, *regions_it, m_shadowDirection, false); - flash.drawRegion(*r, nbDraw + 1); - flash.setFillColor(getMainColor()); - flash.drawRectangle(rdf.m_ro.m_bbox); + flash.drawRegion(*r, nbDraw + 1); + flash.setFillColor(getMainColor()); + flash.drawRectangle(rdf.m_ro.m_bbox); - for (regions_it = regions_it_b; regions_it != regions_it_e; ++regions_it) - drawPolyline(flash, *regions_it, m_shadowDirection); + for (regions_it = regions_it_b; regions_it != regions_it_e; ++regions_it) + drawPolyline(flash, *regions_it, m_shadowDirection); } //*************************************************************************** // RubberModifier implementation //*************************************************************************** -TOutlineStyle::RegionOutlineModifier *RubberModifier::clone() const -{ - return new RubberModifier(*this); +TOutlineStyle::RegionOutlineModifier *RubberModifier::clone() const { + return new RubberModifier(*this); } //------------------------------------------------------------ -void RubberModifier::modify(TRegionOutline &outline) const -{ - double deformSize = 40.0 + (100 - m_deform) * 0.60; +void RubberModifier::modify(TRegionOutline &outline) const { + double deformSize = 40.0 + (100 - m_deform) * 0.60; - TRegionOutline::Boundary::iterator regions_it; - TRegionOutline::Boundary::iterator regions_it_b = outline.m_exterior.begin(); - TRegionOutline::Boundary::iterator regions_it_e = outline.m_exterior.end(); + TRegionOutline::Boundary::iterator regions_it; + TRegionOutline::Boundary::iterator regions_it_b = outline.m_exterior.begin(); + TRegionOutline::Boundary::iterator regions_it_e = outline.m_exterior.end(); - for (regions_it = regions_it_b; regions_it != regions_it_e; ++regions_it) { - RubberDeform rd(®ions_it[0]); - rd.deform(deformSize); - } + for (regions_it = regions_it_b; regions_it != regions_it_e; ++regions_it) { + RubberDeform rd(®ions_it[0]); + rd.deform(deformSize); + } - regions_it_b = outline.m_interior.begin(); - regions_it_e = outline.m_interior.end(); + regions_it_b = outline.m_interior.begin(); + regions_it_e = outline.m_interior.end(); - for (regions_it = regions_it_b; regions_it != regions_it_e; ++regions_it) { - RubberDeform rd(®ions_it[0]); - rd.deform(deformSize); - } + for (regions_it = regions_it_b; regions_it != regions_it_e; ++regions_it) { + RubberDeform rd(®ions_it[0]); + rd.deform(deformSize); + } } //*************************************************************************** @@ -1100,1385 +1038,1326 @@ void RubberModifier::modify(TRegionOutline &outline) const //*************************************************************************** TRubberFillStyle::TRubberFillStyle(const TPixel32 &color, double deform) - : TSolidColorStyle(color) -{ - m_regionOutlineModifier = new RubberModifier(deform); + : TSolidColorStyle(color) { + m_regionOutlineModifier = new RubberModifier(deform); } //------------------------------------------------------------ -TColorStyle *TRubberFillStyle::clone() const -{ - return new TRubberFillStyle(*this); +TColorStyle *TRubberFillStyle::clone() const { + return new TRubberFillStyle(*this); } //------------------------------------------------------------ -void TRubberFillStyle::makeIcon(const TDimension &d) -{ - // Saves the values of member variables and sets the right icon values +void TRubberFillStyle::makeIcon(const TDimension &d) { + // Saves the values of member variables and sets the right icon values - RubberModifier *prm = (RubberModifier *)(m_regionOutlineModifier); - double LDeform = prm->getDeform(); - prm->setDeform(LDeform); + RubberModifier *prm = (RubberModifier *)(m_regionOutlineModifier); + double LDeform = prm->getDeform(); + prm->setDeform(LDeform); - TColorStyle::makeIcon(d); + TColorStyle::makeIcon(d); - // Loads the original values - prm->setDeform(LDeform); + // Loads the original values + prm->setDeform(LDeform); } //------------------------------------------------------------ -int TRubberFillStyle::getParamCount() const -{ - return 1; -} +int TRubberFillStyle::getParamCount() const { return 1; } //----------------------------------------------------------------------------- -TColorStyle::ParamType TRubberFillStyle::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +TColorStyle::ParamType TRubberFillStyle::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -QString TRubberFillStyle::getParamNames(int index) const -{ - assert(0 <= index && index < 1); +QString TRubberFillStyle::getParamNames(int index) const { + assert(0 <= index && index < 1); - return QCoreApplication::translate("TRubberFillStyle", "Intensity"); + return QCoreApplication::translate("TRubberFillStyle", "Intensity"); } //----------------------------------------------------------------------------- -void TRubberFillStyle::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 1); - min = 0.; - max = 100.0; +void TRubberFillStyle::getParamRange(int index, double &min, + double &max) const { + assert(0 <= index && index < 1); + min = 0.; + max = 100.0; } //----------------------------------------------------------------------------- -double TRubberFillStyle::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 1); - return ((RubberModifier *)m_regionOutlineModifier)->getDeform(); +double TRubberFillStyle::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 1); + return ((RubberModifier *)m_regionOutlineModifier)->getDeform(); } //----------------------------------------------------------------------------- -void TRubberFillStyle::setParamValue(int index, double value) -{ - assert(0 <= index && index < 1); +void TRubberFillStyle::setParamValue(int index, double value) { + assert(0 <= index && index < 1); - double oldDeform = ((RubberModifier *)m_regionOutlineModifier)->getDeform(); + double oldDeform = ((RubberModifier *)m_regionOutlineModifier)->getDeform(); - if (oldDeform != value) { - delete m_regionOutlineModifier; - m_regionOutlineModifier = new RubberModifier(value); - updateVersionNumber(); - } + if (oldDeform != value) { + delete m_regionOutlineModifier; + m_regionOutlineModifier = new RubberModifier(value); + updateVersionNumber(); + } } //------------------------------------------------------------ -void TRubberFillStyle::loadData(TInputStreamInterface &is) -{ - TSolidColorStyle::loadData(is); - delete m_regionOutlineModifier; - RubberModifier *rub = new RubberModifier(0.0); - rub->loadData(is); - m_regionOutlineModifier = rub; +void TRubberFillStyle::loadData(TInputStreamInterface &is) { + TSolidColorStyle::loadData(is); + delete m_regionOutlineModifier; + RubberModifier *rub = new RubberModifier(0.0); + rub->loadData(is); + m_regionOutlineModifier = rub; } //------------------------------------------------------------ -void TRubberFillStyle::saveData(TOutputStreamInterface &os) const -{ - TSolidColorStyle::saveData(os); +void TRubberFillStyle::saveData(TOutputStreamInterface &os) const { + TSolidColorStyle::saveData(os); - assert(m_regionOutlineModifier); - ((RubberModifier *)m_regionOutlineModifier)->saveData(os); + assert(m_regionOutlineModifier); + ((RubberModifier *)m_regionOutlineModifier)->saveData(os); } //------------------------------------------------------------ -void TRubberFillStyle::drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const -{ - TSolidColorStyle::drawRegion(cf, true, boundary); +void TRubberFillStyle::drawRegion(const TColorFunction *cf, + const bool antiAliasing, + TRegionOutline &boundary) const { + TSolidColorStyle::drawRegion(cf, true, boundary); } -void TRubberFillStyle::drawRegion(TFlash &flash, const TRegion *r) const -{ - SFlashUtils rdf(r); - rdf.computeRegionOutline(); - m_regionOutlineModifier->modify(rdf.m_ro); - flash.setFillColor(getMainColor()); - rdf.drawRegionOutline(flash); - // If Valentina prefers the angled version use this - // rdf.drawRegionOutline(flash,false); +void TRubberFillStyle::drawRegion(TFlash &flash, const TRegion *r) const { + SFlashUtils rdf(r); + rdf.computeRegionOutline(); + m_regionOutlineModifier->modify(rdf.m_ro); + flash.setFillColor(getMainColor()); + rdf.drawRegionOutline(flash); + // If Valentina prefers the angled version use this + // rdf.drawRegionOutline(flash,false); } //*************************************************************************** // TPointShadowFillStyle implementation //*************************************************************************** -TPointShadowFillStyle::TPointShadowFillStyle( - const TPixel32 &bgColor, - const TPixel32 &shadowColor, - const TPointD &shadowDirection, - double density, - double shadowSize, - double pointSize) - : TSolidColorStyle(bgColor), m_shadowColor(shadowColor), m_shadowDirection(normalize(shadowDirection)), m_shadowSize(shadowSize), m_density(density), m_pointSize(pointSize) -{ -} +TPointShadowFillStyle::TPointShadowFillStyle(const TPixel32 &bgColor, + const TPixel32 &shadowColor, + const TPointD &shadowDirection, + double density, double shadowSize, + double pointSize) + : TSolidColorStyle(bgColor) + , m_shadowColor(shadowColor) + , m_shadowDirection(normalize(shadowDirection)) + , m_shadowSize(shadowSize) + , m_density(density) + , m_pointSize(pointSize) {} //----------------------------------------------------------------------------- -TColorStyle *TPointShadowFillStyle::clone() const -{ - return new TPointShadowFillStyle(*this); +TColorStyle *TPointShadowFillStyle::clone() const { + return new TPointShadowFillStyle(*this); } //----------------------------------------------------------------------------- -int TPointShadowFillStyle::getParamCount() const -{ - return 4; -} +int TPointShadowFillStyle::getParamCount() const { return 4; } //----------------------------------------------------------------------------- -TColorStyle::ParamType TPointShadowFillStyle::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +TColorStyle::ParamType TPointShadowFillStyle::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -QString TPointShadowFillStyle::getParamNames(int index) const -{ - assert(0 <= index && index < 4); - - QString value; - switch (index) { - case 0: - value = QCoreApplication::translate("TPointShadowFillStyle", "Angle"); - break; - case 1: - value = QCoreApplication::translate("TPointShadowFillStyle", "Density"); - break; - case 2: - value = QCoreApplication::translate("TPointShadowFillStyle", "Size"); - break; - case 3: - value = QCoreApplication::translate("TPointShadowFillStyle", "Point Size"); - break; - } - - return value; +QString TPointShadowFillStyle::getParamNames(int index) const { + assert(0 <= index && index < 4); + + QString value; + switch (index) { + case 0: + value = QCoreApplication::translate("TPointShadowFillStyle", "Angle"); + break; + case 1: + value = QCoreApplication::translate("TPointShadowFillStyle", "Density"); + break; + case 2: + value = QCoreApplication::translate("TPointShadowFillStyle", "Size"); + break; + case 3: + value = QCoreApplication::translate("TPointShadowFillStyle", "Point Size"); + break; + } + + return value; } //----------------------------------------------------------------------------- -void TPointShadowFillStyle::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 4); - - switch (index) { - case 0: - min = 0.0; - max = 360.0; - break; - case 1: - min = 0.0; - max = 1.0; - break; - case 2: - min = 0.0; - max = 100.0; - break; - case 3: - min = 0.01; - max = 100.0; - break; - } +void TPointShadowFillStyle::getParamRange(int index, double &min, + double &max) const { + assert(0 <= index && index < 4); + + switch (index) { + case 0: + min = 0.0; + max = 360.0; + break; + case 1: + min = 0.0; + max = 1.0; + break; + case 2: + min = 0.0; + max = 100.0; + break; + case 3: + min = 0.01; + max = 100.0; + break; + } } //----------------------------------------------------------------------------- -double TPointShadowFillStyle::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 4); +double TPointShadowFillStyle::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 4); - double degree = 0.0; + double degree = 0.0; - switch (index) { - case 0: - degree = asin(m_shadowDirection.y); - if (m_shadowDirection.x < 0) - degree = TConsts::pi - degree; - if (degree < 0) - degree += pi2; - return degree * TConsts::invOf_pi_180; + switch (index) { + case 0: + degree = asin(m_shadowDirection.y); + if (m_shadowDirection.x < 0) degree = M_PI - degree; + if (degree < 0) degree += M_2PI; + return degree * M_180_PI; - case 1: - return m_density; + case 1: + return m_density; - case 2: - return m_shadowSize; + case 2: + return m_shadowSize; - case 3: - return m_pointSize; - } + case 3: + return m_pointSize; + } - //never - return 0; + // never + return 0; } //----------------------------------------------------------------------------- -void TPointShadowFillStyle::setParamValue(int index, double value) -{ - assert(0 <= index && index < 4); +void TPointShadowFillStyle::setParamValue(int index, double value) { + assert(0 <= index && index < 4); - double degree = 0.0; + double degree = 0.0; - switch (index) { - case 0: - degree = value * TConsts::pi_180; - m_shadowDirection.x = cos(degree); - m_shadowDirection.y = sin(degree); + switch (index) { + case 0: + degree = value * M_PI_180; + m_shadowDirection.x = cos(degree); + m_shadowDirection.y = sin(degree); - break; + break; - case 1: - m_density = value; - break; + case 1: + m_density = value; + break; - case 2: - m_shadowSize = value; - break; + case 2: + m_shadowSize = value; + break; - case 3: - m_pointSize = value; - break; - } + case 3: + m_pointSize = value; + break; + } } //------------------------------------------------------------ -void TPointShadowFillStyle::loadData(TInputStreamInterface &is) -{ - TSolidColorStyle::loadData(is); - is >> m_shadowDirection.x >> m_shadowDirection.y; - is >> m_density; - is >> m_shadowSize; - is >> m_pointSize; - is >> m_shadowColor; +void TPointShadowFillStyle::loadData(TInputStreamInterface &is) { + TSolidColorStyle::loadData(is); + is >> m_shadowDirection.x >> m_shadowDirection.y; + is >> m_density; + is >> m_shadowSize; + is >> m_pointSize; + is >> m_shadowColor; } //------------------------------------------------------------ -void TPointShadowFillStyle::saveData(TOutputStreamInterface &os) const -{ - TSolidColorStyle::saveData(os); - os << m_shadowDirection.x << m_shadowDirection.y; - os << m_density; - os << m_shadowSize; - os << m_pointSize; - os << m_shadowColor; +void TPointShadowFillStyle::saveData(TOutputStreamInterface &os) const { + TSolidColorStyle::saveData(os); + os << m_shadowDirection.x << m_shadowDirection.y; + os << m_density; + os << m_shadowSize; + os << m_pointSize; + os << m_shadowColor; } //------------------------------------------------------------ -TPixel32 TPointShadowFillStyle::getColorParamValue(int index) const -{ - return index == 0 ? m_shadowColor : TSolidColorStyle::getMainColor(); +TPixel32 TPointShadowFillStyle::getColorParamValue(int index) const { + return index == 0 ? m_shadowColor : TSolidColorStyle::getMainColor(); } //------------------------------------------------------------ -void TPointShadowFillStyle::setColorParamValue(int index, const TPixel32 &color) -{ - if (index == 0) - m_shadowColor = color; - else { - TSolidColorStyle::setMainColor(color); - } +void TPointShadowFillStyle::setColorParamValue(int index, + const TPixel32 &color) { + if (index == 0) + m_shadowColor = color; + else { + TSolidColorStyle::setMainColor(color); + } } //------------------------------------------------------------ -double TPointShadowFillStyle::triangleArea(const TPointD &a, const TPointD &b, const TPointD &c) const -{ - double ab = tdistance(a, b); - double ac = tdistance(a, c); - double bc = tdistance(b, c); - double s = (ab + bc + ac) / 2.0; - return sqrt(s * (s - ab) * (s - ac) * (s - bc)); +double TPointShadowFillStyle::triangleArea(const TPointD &a, const TPointD &b, + const TPointD &c) const { + double ab = tdistance(a, b); + double ac = tdistance(a, c); + double bc = tdistance(b, c); + double s = (ab + bc + ac) / 2.0; + return sqrt(s * (s - ab) * (s - ac) * (s - bc)); } //------------------------------------------------------------ -void TPointShadowFillStyle::shadowOnEdge_parallel(const TPointD &p0, const TPointD &p1, - const TPointD &p2, TRandom &rnd) const -{ +void TPointShadowFillStyle::shadowOnEdge_parallel(const TPointD &p0, + const TPointD &p1, + const TPointD &p2, + TRandom &rnd) const { + if (p0 == p1 || p1 == p2) return; - if (p0 == p1 || p1 == p2) - return; - - TPointD diff = normalize(rotate90(p1 - p0)); - double len1 = diff * m_shadowDirection; - - diff = normalize(rotate90(p2 - p1)); - double len2 = diff * m_shadowDirection; - - if (len1 >= 0 && len2 >= 0 && (len1 + len2) > 0) { - TPointD la = p1 + m_shadowDirection * len1 * m_shadowSize; - TPointD lb = p2 + m_shadowDirection * len2 * m_shadowSize; - double t = triangleArea(p1, p2, lb) + triangleArea(p2, lb, la); - int nb = (int)(m_density * t); - for (int i = 0; i < nb; i++) { - double q = rnd.getUInt(1001) / 1000.0; - double r = rnd.getUInt(1001) / 1000.0; - r = r * r; - TPointD u = p1 + (p2 - p1) * q; - u = u + r * (len1 * (1.0 - q) + len2 * q) * m_shadowDirection * m_shadowSize; - tglColor(TPixel32(m_shadowColor.r, - m_shadowColor.g, - m_shadowColor.b, - (int)((1.0 - r) * (double)m_shadowColor.m))); - tglVertex(u); - } - } -} - -//------------------------------------------------------------ - -int TPointShadowFillStyle::shadowOnEdge_parallel(TFlash &flash, - const TPointD &p0, const TPointD &p1, - const TPointD &p2, TRandom &rnd, - const double radius, - const bool isDraw) const -{ - int nbDraw = 0; - - if (p0 == p1 || p1 == p2) - return 0; - - TPointD diff = normalize(rotate90(p1 - p0)); - double len1 = diff * m_shadowDirection; - len1 = std::max(0.0, len1); - - diff = normalize(rotate90(p2 - p1)); - double len2 = diff * m_shadowDirection; - len2 = std::max(0.0, len2); - - if ((len1 + len2) > 0) { - TPointD la = p1 + m_shadowDirection * len1 * m_shadowSize; - TPointD lb = p2 + m_shadowDirection * len2 * m_shadowSize; - double t = triangleArea(p1, p2, lb) + triangleArea(p2, lb, la); - int nb = (int)(m_density * t); - for (int i = 0; i < nb; i++) { - double q = rnd.getUInt(1001) / 1000.0; - double r = rnd.getUInt(1001) / 1000.0; - r = r * r; - TPointD u = p1 + (p2 - p1) * q; - u = u + r * (len1 * (1.0 - q) + len2 * q) * m_shadowDirection * m_shadowSize; - nbDraw++; - if (isDraw) { - flash.setFillColor(TPixel32(m_shadowColor.r, m_shadowColor.g, m_shadowColor.b, (int)((1.0 - r) * 255))); - flash.drawEllipse(u, radius, radius); - //flash.drawDot(u,radius); - } - } - } - return nbDraw; -} - -//------------------------------------------------------------ - -void TPointShadowFillStyle::deleteSameVerts(TRegionOutline::Boundary::iterator &rit, - std::vector &pv) const -{ - pv.clear(); - if (rit->size() <= 0) - return; - TRegionOutline::PointVector::iterator it_beg = rit->begin(); - TRegionOutline::PointVector::iterator it_end = rit->end(); - TRegionOutline::PointVector::iterator it = it_beg; - pv.push_back(*it); - it++; - for (; it != it_end; it++) { - if (tdistance(*it, pv.back()) > TConsts::epsilon) { - pv.push_back(*it); - } - } + TPointD diff = normalize(rotate90(p1 - p0)); + double len1 = diff * m_shadowDirection; + + diff = normalize(rotate90(p2 - p1)); + double len2 = diff * m_shadowDirection; - if (pv.size() > 2) { - if (tdistance(*(pv.begin()), pv.back()) <= TConsts::epsilon) - pv.pop_back(); - } + if (len1 >= 0 && len2 >= 0 && (len1 + len2) > 0) { + TPointD la = p1 + m_shadowDirection * len1 * m_shadowSize; + TPointD lb = p2 + m_shadowDirection * len2 * m_shadowSize; + double t = triangleArea(p1, p2, lb) + triangleArea(p2, lb, la); + int nb = (int)(m_density * t); + for (int i = 0; i < nb; i++) { + double q = rnd.getUInt(1001) / 1000.0; + double r = rnd.getUInt(1001) / 1000.0; + r = r * r; + TPointD u = p1 + (p2 - p1) * q; + u = u + + r * (len1 * (1.0 - q) + len2 * q) * m_shadowDirection * m_shadowSize; + tglColor(TPixel32(m_shadowColor.r, m_shadowColor.g, m_shadowColor.b, + (int)((1.0 - r) * (double)m_shadowColor.m))); + tglVertex(u); + } + } } //------------------------------------------------------------ -void TPointShadowFillStyle::drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const -{ +int TPointShadowFillStyle::shadowOnEdge_parallel( + TFlash &flash, const TPointD &p0, const TPointD &p1, const TPointD &p2, + TRandom &rnd, const double radius, const bool isDraw) const { + int nbDraw = 0; + + if (p0 == p1 || p1 == p2) return 0; + + TPointD diff = normalize(rotate90(p1 - p0)); + double len1 = diff * m_shadowDirection; + len1 = std::max(0.0, len1); + + diff = normalize(rotate90(p2 - p1)); + double len2 = diff * m_shadowDirection; + len2 = std::max(0.0, len2); + + if ((len1 + len2) > 0) { + TPointD la = p1 + m_shadowDirection * len1 * m_shadowSize; + TPointD lb = p2 + m_shadowDirection * len2 * m_shadowSize; + double t = triangleArea(p1, p2, lb) + triangleArea(p2, lb, la); + int nb = (int)(m_density * t); + for (int i = 0; i < nb; i++) { + double q = rnd.getUInt(1001) / 1000.0; + double r = rnd.getUInt(1001) / 1000.0; + r = r * r; + TPointD u = p1 + (p2 - p1) * q; + u = u + + r * (len1 * (1.0 - q) + len2 * q) * m_shadowDirection * m_shadowSize; + nbDraw++; + if (isDraw) { + flash.setFillColor(TPixel32(m_shadowColor.r, m_shadowColor.g, + m_shadowColor.b, (int)((1.0 - r) * 255))); + flash.drawEllipse(u, radius, radius); + // flash.drawDot(u,radius); + } + } + } + return nbDraw; +} - TStencilControl *stenc = TStencilControl::instance(); - TPixel32 backgroundColor = TSolidColorStyle::getMainColor(); - if (cf) - backgroundColor = (*(cf))(backgroundColor); - - if (backgroundColor.m == 0) { //only to create stencil mask - TSolidColorStyle appStyle(TPixel32::White); - stenc->beginMask(); //does not draw on screen - appStyle.drawRegion(0, false, boundary); - } else { //create stencil mask and draw on screen - stenc->beginMask(TStencilControl::DRAW_ALSO_ON_SCREEN); - TSolidColorStyle::drawRegion(cf, antiAliasing, boundary); - } - stenc->endMask(); - stenc->enableMask(TStencilControl::SHOW_INSIDE); - - GLfloat pointSizeSave; - glGetFloatv(GL_POINT_SIZE, &pointSizeSave); - GLfloat sizes[2]; - glGetFloatv(GL_POINT_SIZE_RANGE, sizes); - //glEnable(GL_BLEND); - //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - //glEnable(GL_POINT_SMOOTH); - //glPointSize((float)(sizes[0]+(sizes[1]-sizes[0])*m_pointSize*0.01)); - tglEnablePointSmooth((float)(sizes[0] + (sizes[1] - sizes[0]) * m_pointSize * 0.01)); - - TRegionOutline::Boundary::iterator regions_it; - TRegionOutline::Boundary::iterator regions_it_b = boundary.m_exterior.begin(); - TRegionOutline::Boundary::iterator regions_it_e = boundary.m_exterior.end(); - - TPixel32 color; - if (cf) - color = (*(cf))(m_shadowColor); - else - color = m_shadowColor; - - TRandom rnd; - - for (regions_it = regions_it_b; regions_it != regions_it_e; ++regions_it) { - std::vector pv; - deleteSameVerts(regions_it, pv); - if (pv.size() < 3) - continue; - std::vector::iterator it_beg = pv.begin(); - std::vector::iterator it_end = pv.end(); - std::vector::iterator it_last = it_end - 1; - std::vector::iterator it0, it1, it2; - glBegin(GL_POINTS); - for (it1 = it_beg; it1 != it_end; it1++) { - it0 = it1 == it_beg ? it_last : it1 - 1; - it2 = it1 == it_last ? it_beg : it1 + 1; - - shadowOnEdge_parallel(TPointD(it0->x, it0->y), TPointD(it1->x, it1->y), - TPointD(it2->x, it2->y), rnd); - } - glEnd(); - } - - glPointSize(pointSizeSave); - stenc->disableMask(); -} - -//------------------------------------------------------------ - -void TPointShadowFillStyle::drawRegion(TFlash &flash, const TRegion *r) const -{ - SFlashUtils rdf(r); - rdf.computeRegionOutline(); - - TRegionOutline::Boundary::iterator regions_it; - TRegionOutline::Boundary::iterator regions_it_b = rdf.m_ro.m_exterior.begin(); - TRegionOutline::Boundary::iterator regions_it_e = rdf.m_ro.m_exterior.end(); - - TPixel32 color = m_shadowColor; - TRandom rnd; - rnd.reset(); - - double sizes[2] = {0.15, 10.0}; - double radius = (sizes[0] + (sizes[1] - sizes[0]) * m_pointSize * 0.01); - - int nbDraw = 0; - for (regions_it = regions_it_b; regions_it != regions_it_e; ++regions_it) { - std::vector pv; - deleteSameVerts(regions_it, pv); - if (pv.size() < 3) - continue; - std::vector::iterator it_beg = pv.begin(); - std::vector::iterator it_end = pv.end(); - std::vector::iterator it_last = it_end - 1; - std::vector::iterator it0, it1, it2; - for (it1 = it_beg; it1 != it_end; it1++) { - it0 = it1 == it_beg ? it_last : it1 - 1; - it2 = it1 == it_last ? it_beg : it1 + 1; - nbDraw += shadowOnEdge_parallel(flash, TPointD(it0->x, it0->y), TPointD(it1->x, it1->y), - TPointD(it2->x, it2->y), rnd, radius, false); - } - } - - rnd.reset(); - flash.drawRegion(*r, nbDraw + 1); // +1 bbox - flash.setFillColor(getMainColor()); - flash.drawRectangle(rdf.m_ro.m_bbox); - - flash.setThickness(0.0); - for (regions_it = regions_it_b; regions_it != regions_it_e; ++regions_it) { - std::vector pv; - deleteSameVerts(regions_it, pv); - if (pv.size() < 3) - continue; - std::vector::iterator it_beg = pv.begin(); - std::vector::iterator it_end = pv.end(); - std::vector::iterator it_last = it_end - 1; - std::vector::iterator it0, it1, it2; - for (it1 = it_beg; it1 != it_end; it1++) { - it0 = it1 == it_beg ? it_last : it1 - 1; - it2 = it1 == it_last ? it_beg : it1 + 1; - shadowOnEdge_parallel(flash, TPointD(it0->x, it0->y), TPointD(it1->x, it1->y), - TPointD(it2->x, it2->y), rnd, radius, true); - } - } +//------------------------------------------------------------ + +void TPointShadowFillStyle::deleteSameVerts( + TRegionOutline::Boundary::iterator &rit, std::vector &pv) const { + pv.clear(); + if (rit->size() <= 0) return; + TRegionOutline::PointVector::iterator it_beg = rit->begin(); + TRegionOutline::PointVector::iterator it_end = rit->end(); + TRegionOutline::PointVector::iterator it = it_beg; + pv.push_back(*it); + it++; + for (; it != it_end; it++) { + if (tdistance(*it, pv.back()) > TConsts::epsilon) { + pv.push_back(*it); + } + } + + if (pv.size() > 2) { + if (tdistance(*(pv.begin()), pv.back()) <= TConsts::epsilon) pv.pop_back(); + } +} + +//------------------------------------------------------------ + +void TPointShadowFillStyle::drawRegion(const TColorFunction *cf, + const bool antiAliasing, + TRegionOutline &boundary) const { + TStencilControl *stenc = TStencilControl::instance(); + TPixel32 backgroundColor = TSolidColorStyle::getMainColor(); + if (cf) backgroundColor = (*(cf))(backgroundColor); + + if (backgroundColor.m == 0) { // only to create stencil mask + TSolidColorStyle appStyle(TPixel32::White); + stenc->beginMask(); // does not draw on screen + appStyle.drawRegion(0, false, boundary); + } else { // create stencil mask and draw on screen + stenc->beginMask(TStencilControl::DRAW_ALSO_ON_SCREEN); + TSolidColorStyle::drawRegion(cf, antiAliasing, boundary); + } + stenc->endMask(); + stenc->enableMask(TStencilControl::SHOW_INSIDE); + + GLfloat pointSizeSave; + glGetFloatv(GL_POINT_SIZE, &pointSizeSave); + GLfloat sizes[2]; + glGetFloatv(GL_POINT_SIZE_RANGE, sizes); + // glEnable(GL_BLEND); + // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + // glEnable(GL_POINT_SMOOTH); + // glPointSize((float)(sizes[0]+(sizes[1]-sizes[0])*m_pointSize*0.01)); + tglEnablePointSmooth( + (float)(sizes[0] + (sizes[1] - sizes[0]) * m_pointSize * 0.01)); + + TRegionOutline::Boundary::iterator regions_it; + TRegionOutline::Boundary::iterator regions_it_b = boundary.m_exterior.begin(); + TRegionOutline::Boundary::iterator regions_it_e = boundary.m_exterior.end(); + + TPixel32 color; + if (cf) + color = (*(cf))(m_shadowColor); + else + color = m_shadowColor; + + TRandom rnd; + + for (regions_it = regions_it_b; regions_it != regions_it_e; ++regions_it) { + std::vector pv; + deleteSameVerts(regions_it, pv); + if (pv.size() < 3) continue; + std::vector::iterator it_beg = pv.begin(); + std::vector::iterator it_end = pv.end(); + std::vector::iterator it_last = it_end - 1; + std::vector::iterator it0, it1, it2; + glBegin(GL_POINTS); + for (it1 = it_beg; it1 != it_end; it1++) { + it0 = it1 == it_beg ? it_last : it1 - 1; + it2 = it1 == it_last ? it_beg : it1 + 1; + + shadowOnEdge_parallel(TPointD(it0->x, it0->y), TPointD(it1->x, it1->y), + TPointD(it2->x, it2->y), rnd); + } + glEnd(); + } + + glPointSize(pointSizeSave); + stenc->disableMask(); +} + +//------------------------------------------------------------ + +void TPointShadowFillStyle::drawRegion(TFlash &flash, const TRegion *r) const { + SFlashUtils rdf(r); + rdf.computeRegionOutline(); + + TRegionOutline::Boundary::iterator regions_it; + TRegionOutline::Boundary::iterator regions_it_b = rdf.m_ro.m_exterior.begin(); + TRegionOutline::Boundary::iterator regions_it_e = rdf.m_ro.m_exterior.end(); + + TPixel32 color = m_shadowColor; + TRandom rnd; + rnd.reset(); + + double sizes[2] = {0.15, 10.0}; + double radius = (sizes[0] + (sizes[1] - sizes[0]) * m_pointSize * 0.01); + + int nbDraw = 0; + for (regions_it = regions_it_b; regions_it != regions_it_e; ++regions_it) { + std::vector pv; + deleteSameVerts(regions_it, pv); + if (pv.size() < 3) continue; + std::vector::iterator it_beg = pv.begin(); + std::vector::iterator it_end = pv.end(); + std::vector::iterator it_last = it_end - 1; + std::vector::iterator it0, it1, it2; + for (it1 = it_beg; it1 != it_end; it1++) { + it0 = it1 == it_beg ? it_last : it1 - 1; + it2 = it1 == it_last ? it_beg : it1 + 1; + nbDraw += shadowOnEdge_parallel( + flash, TPointD(it0->x, it0->y), TPointD(it1->x, it1->y), + TPointD(it2->x, it2->y), rnd, radius, false); + } + } + + rnd.reset(); + flash.drawRegion(*r, nbDraw + 1); // +1 bbox + flash.setFillColor(getMainColor()); + flash.drawRectangle(rdf.m_ro.m_bbox); + + flash.setThickness(0.0); + for (regions_it = regions_it_b; regions_it != regions_it_e; ++regions_it) { + std::vector pv; + deleteSameVerts(regions_it, pv); + if (pv.size() < 3) continue; + std::vector::iterator it_beg = pv.begin(); + std::vector::iterator it_end = pv.end(); + std::vector::iterator it_last = it_end - 1; + std::vector::iterator it0, it1, it2; + for (it1 = it_beg; it1 != it_end; it1++) { + it0 = it1 == it_beg ? it_last : it1 - 1; + it2 = it1 == it_last ? it_beg : it1 + 1; + shadowOnEdge_parallel(flash, TPointD(it0->x, it0->y), + TPointD(it1->x, it1->y), TPointD(it2->x, it2->y), + rnd, radius, true); + } + } } //*************************************************************************** // TDottedFillStyle implementation //*************************************************************************** -TDottedFillStyle::TDottedFillStyle( - const TPixel32 &bgColor, - const TPixel32 &pointColor, - const double dotSize, - const double dotDist, - const bool isShifted) - : TSolidColorStyle(bgColor), m_pointColor(pointColor), m_dotSize(dotSize), m_dotDist(dotDist), m_isShifted(isShifted) -{ -} +TDottedFillStyle::TDottedFillStyle(const TPixel32 &bgColor, + const TPixel32 &pointColor, + const double dotSize, const double dotDist, + const bool isShifted) + : TSolidColorStyle(bgColor) + , m_pointColor(pointColor) + , m_dotSize(dotSize) + , m_dotDist(dotDist) + , m_isShifted(isShifted) {} //------------------------------------------------------------ TDottedFillStyle::TDottedFillStyle(const TPixel32 &color) - : TSolidColorStyle(TPixel32(0, 0, 200)), m_pointColor(color), m_dotSize(3.0), m_dotDist(15.0), m_isShifted(true) -{ -} + : TSolidColorStyle(TPixel32(0, 0, 200)) + , m_pointColor(color) + , m_dotSize(3.0) + , m_dotDist(15.0) + , m_isShifted(true) {} //------------------------------------------------------------ -TColorStyle *TDottedFillStyle::clone() const -{ - return new TDottedFillStyle(*this); +TColorStyle *TDottedFillStyle::clone() const { + return new TDottedFillStyle(*this); } //------------------------------------------------------------ -int TDottedFillStyle::getParamCount() const -{ - return 2; -} +int TDottedFillStyle::getParamCount() const { return 2; } //----------------------------------------------------------------------------- -TColorStyle::ParamType TDottedFillStyle::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +TColorStyle::ParamType TDottedFillStyle::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -QString TDottedFillStyle::getParamNames(int index) const -{ - assert(0 <= index && index < 2); +QString TDottedFillStyle::getParamNames(int index) const { + assert(0 <= index && index < 2); - return index == 0 ? QCoreApplication::translate("TDottedFillStyle", "Dot Size") : QCoreApplication::translate("TDottedFillStyle", "Dot Distance"); + return index == 0 + ? QCoreApplication::translate("TDottedFillStyle", "Dot Size") + : QCoreApplication::translate("TDottedFillStyle", "Dot Distance"); } //----------------------------------------------------------------------------- -void TDottedFillStyle::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 2); - if (index == 0) { - min = 0.001; - max = 30.0; - } else { - min = 2.0; - max = 100.0; - } +void TDottedFillStyle::getParamRange(int index, double &min, + double &max) const { + assert(0 <= index && index < 2); + if (index == 0) { + min = 0.001; + max = 30.0; + } else { + min = 2.0; + max = 100.0; + } } //----------------------------------------------------------------------------- -double TDottedFillStyle::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 2); +double TDottedFillStyle::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 2); - if (!index) - return m_dotSize; - else - return m_dotDist; + if (!index) + return m_dotSize; + else + return m_dotDist; } //----------------------------------------------------------------------------- -void TDottedFillStyle::setParamValue(int index, double value) -{ - assert(0 <= index && index < 2); +void TDottedFillStyle::setParamValue(int index, double value) { + assert(0 <= index && index < 2); - if (!index) { - m_dotSize = value; - } else { - m_dotDist = value; - } + if (!index) { + m_dotSize = value; + } else { + m_dotDist = value; + } } //------------------------------------------------------------ -void TDottedFillStyle::loadData(TInputStreamInterface &is) -{ - TSolidColorStyle::loadData(is); - is >> m_dotSize; - is >> m_dotDist; - is >> m_pointColor; +void TDottedFillStyle::loadData(TInputStreamInterface &is) { + TSolidColorStyle::loadData(is); + is >> m_dotSize; + is >> m_dotDist; + is >> m_pointColor; } //------------------------------------------------------------ -void TDottedFillStyle::saveData(TOutputStreamInterface &os) const -{ - TSolidColorStyle::saveData(os); - os << m_dotSize; - os << m_dotDist; - os << m_pointColor; +void TDottedFillStyle::saveData(TOutputStreamInterface &os) const { + TSolidColorStyle::saveData(os); + os << m_dotSize; + os << m_dotDist; + os << m_pointColor; } //------------------------------------------------------------ -TPixel32 TDottedFillStyle::getColorParamValue(int index) const -{ - return index == 0 ? m_pointColor : TSolidColorStyle::getMainColor(); +TPixel32 TDottedFillStyle::getColorParamValue(int index) const { + return index == 0 ? m_pointColor : TSolidColorStyle::getMainColor(); } //------------------------------------------------------------ -void TDottedFillStyle::setColorParamValue(int index, const TPixel32 &color) -{ - if (index == 0) - m_pointColor = color; - else { - TSolidColorStyle::setMainColor(color); - } +void TDottedFillStyle::setColorParamValue(int index, const TPixel32 &color) { + if (index == 0) + m_pointColor = color; + else { + TSolidColorStyle::setMainColor(color); + } } //------------------------------------------------------------ -void TDottedFillStyle::drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const -{ - double LDotDist = std::max(m_dotDist, 0.1); - //double LDotSize=m_dotSize; - bool LIsShifted = m_isShifted; - const bool isTransparent = m_pointColor.m < 255; - - TStencilControl *stenc = TStencilControl::instance(); - TPixel32 backgroundColor = TSolidColorStyle::getMainColor(); - if (cf) - backgroundColor = (*(cf))(backgroundColor); - - if (backgroundColor.m == 0) { //only to create stencil mask - TSolidColorStyle appStyle(TPixel32::White); - stenc->beginMask(); //does not draw on screen - appStyle.drawRegion(0, false, boundary); - } else { //create stencil mask and draw on screen - stenc->beginMask(TStencilControl::DRAW_ALSO_ON_SCREEN); - TSolidColorStyle::drawRegion(cf, antiAliasing, boundary); - } - stenc->endMask(); +void TDottedFillStyle::drawRegion(const TColorFunction *cf, + const bool antiAliasing, + TRegionOutline &boundary) const { + double LDotDist = std::max(m_dotDist, 0.1); + // double LDotSize=m_dotSize; + bool LIsShifted = m_isShifted; + const bool isTransparent = m_pointColor.m < 255; - stenc->enableMask(TStencilControl::SHOW_INSIDE); + TStencilControl *stenc = TStencilControl::instance(); + TPixel32 backgroundColor = TSolidColorStyle::getMainColor(); + if (cf) backgroundColor = (*(cf))(backgroundColor); - if (isTransparent) { - //glEnable(GL_BLEND); - //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - //// <-- tglEnableBlending(); - } + if (backgroundColor.m == 0) { // only to create stencil mask + TSolidColorStyle appStyle(TPixel32::White); + stenc->beginMask(); // does not draw on screen + appStyle.drawRegion(0, false, boundary); + } else { // create stencil mask and draw on screen + stenc->beginMask(TStencilControl::DRAW_ALSO_ON_SCREEN); + TSolidColorStyle::drawRegion(cf, antiAliasing, boundary); + } + stenc->endMask(); - TPixel32 color; - if (cf) - color = (*(cf))(m_pointColor); - else - color = m_pointColor; + stenc->enableMask(TStencilControl::SHOW_INSIDE); - tglColor(color); + if (isTransparent) { + // glEnable(GL_BLEND); + // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + //// <-- tglEnableBlending(); + } - int i = 0; - for (double y = boundary.m_bbox.y0; y <= boundary.m_bbox.y1; y += LDotDist, ++i) { - double x = LIsShifted && (i % 2) == 1 ? boundary.m_bbox.x0 + LDotDist / 2.0 : boundary.m_bbox.x0; - for (; x <= boundary.m_bbox.x1; x += LDotDist) - tglDrawDisk(TPointD(x, y), m_dotSize); - // tglDrawCircle(TPointD(x,y),m_dotSize); - } + TPixel32 color; + if (cf) + color = (*(cf))(m_pointColor); + else + color = m_pointColor; + + tglColor(color); + + int i = 0; + for (double y = boundary.m_bbox.y0; y <= boundary.m_bbox.y1; + y += LDotDist, ++i) { + double x = LIsShifted && (i % 2) == 1 ? boundary.m_bbox.x0 + LDotDist / 2.0 + : boundary.m_bbox.x0; + for (; x <= boundary.m_bbox.x1; x += LDotDist) + tglDrawDisk(TPointD(x, y), m_dotSize); + // tglDrawCircle(TPointD(x,y),m_dotSize); + } - if (isTransparent) { - //tglColor(TPixel32::White); - //glDisable(GL_BLEND); - } + if (isTransparent) { + // tglColor(TPixel32::White); + // glDisable(GL_BLEND); + } - stenc->disableMask(); + stenc->disableMask(); } //------------------------------------------------------------ int TDottedFillStyle::nbClip(const double LDotDist, const bool LIsShifted, - const TRectD &bbox) const -{ - int nbClipLayers = 1; // the bbox rectangle - int i = 0; - for (double y = bbox.y0; y <= bbox.y1; y += LDotDist, ++i) { - double x = LIsShifted && (i % 2) == 1 ? bbox.x0 + LDotDist / 2.0 : bbox.x0; - for (; x <= bbox.x1; x += LDotDist) - nbClipLayers++; - } - return nbClipLayers; + const TRectD &bbox) const { + int nbClipLayers = 1; // the bbox rectangle + int i = 0; + for (double y = bbox.y0; y <= bbox.y1; y += LDotDist, ++i) { + double x = LIsShifted && (i % 2) == 1 ? bbox.x0 + LDotDist / 2.0 : bbox.x0; + for (; x <= bbox.x1; x += LDotDist) nbClipLayers++; + } + return nbClipLayers; } //------------------------------------------------------------ -void TDottedFillStyle::drawRegion(TFlash &flash, const TRegion *r) const -{ - double LDotDist = std::max(m_dotDist, 0.1); - double LDotSize = m_dotSize; - bool LIsShifted = m_isShifted; - TRectD bbox(r->getBBox()); - - flash.setFillColor(TPixel::Black); - flash.drawRegion(*r, true); - int nClip = nbClip(LDotDist, LIsShifted, bbox); +void TDottedFillStyle::drawRegion(TFlash &flash, const TRegion *r) const { + double LDotDist = std::max(m_dotDist, 0.1); + double LDotSize = m_dotSize; + bool LIsShifted = m_isShifted; + TRectD bbox(r->getBBox()); - flash.drawRegion(*r, nClip); + flash.setFillColor(TPixel::Black); + flash.drawRegion(*r, true); + int nClip = nbClip(LDotDist, LIsShifted, bbox); - flash.setFillColor(getMainColor()); - flash.drawRectangle(bbox); - flash.setFillColor(m_pointColor); + flash.drawRegion(*r, nClip); - int i = 0; - for (double y = bbox.y0; y <= bbox.y1; y += LDotDist, ++i) { - double x = LIsShifted && (i % 2) == 1 ? bbox.x0 + LDotDist / 2.0 : bbox.x0; - for (; x <= bbox.x1; x += LDotDist) - flash.drawEllipse(TPointD(x, y), LDotSize, LDotSize); - } + flash.setFillColor(getMainColor()); + flash.drawRectangle(bbox); + flash.setFillColor(m_pointColor); + + int i = 0; + for (double y = bbox.y0; y <= bbox.y1; y += LDotDist, ++i) { + double x = LIsShifted && (i % 2) == 1 ? bbox.x0 + LDotDist / 2.0 : bbox.x0; + for (; x <= bbox.x1; x += LDotDist) + flash.drawEllipse(TPointD(x, y), LDotSize, LDotSize); + } } //*************************************************************************** // TCheckedFillStyle implementation //*************************************************************************** -TCheckedFillStyle::TCheckedFillStyle( - const TPixel32 &bgColor, const TPixel32 &pointColor, - const double HDist, const double HAngle, - const double VDist, const double VAngle, const double Thickness) - : TSolidColorStyle(bgColor), m_pointColor(pointColor), m_HDist(HDist), m_HAngle(HAngle), m_VDist(VDist), m_VAngle(VAngle), m_Thickness(Thickness) -{ -} +TCheckedFillStyle::TCheckedFillStyle(const TPixel32 &bgColor, + const TPixel32 &pointColor, + const double HDist, const double HAngle, + const double VDist, const double VAngle, + const double Thickness) + : TSolidColorStyle(bgColor) + , m_pointColor(pointColor) + , m_HDist(HDist) + , m_HAngle(HAngle) + , m_VDist(VDist) + , m_VAngle(VAngle) + , m_Thickness(Thickness) {} //------------------------------------------------------------ TCheckedFillStyle::TCheckedFillStyle(const TPixel32 &color) - : TSolidColorStyle(TPixel32::Transparent), m_pointColor(color), m_HDist(15.0), m_HAngle(0.0), m_VDist(15.0), m_VAngle(0.0), m_Thickness(6.0) -{ -} + : TSolidColorStyle(TPixel32::Transparent) + , m_pointColor(color) + , m_HDist(15.0) + , m_HAngle(0.0) + , m_VDist(15.0) + , m_VAngle(0.0) + , m_Thickness(6.0) {} //------------------------------------------------------------ -TColorStyle *TCheckedFillStyle::clone() const -{ - return new TCheckedFillStyle(*this); +TColorStyle *TCheckedFillStyle::clone() const { + return new TCheckedFillStyle(*this); } //------------------------------------------------------------ -int TCheckedFillStyle::getParamCount() const -{ - return 5; -} +int TCheckedFillStyle::getParamCount() const { return 5; } //----------------------------------------------------------------------------- -TColorStyle::ParamType TCheckedFillStyle::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +TColorStyle::ParamType TCheckedFillStyle::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -QString TCheckedFillStyle::getParamNames(int index) const -{ - assert(0 <= index && index < 5); - - QString value; - switch (index) { - case 0: - value = QCoreApplication::translate("TCheckedFillStyle", "Horiz Dist"); - break; - case 1: - value = QCoreApplication::translate("TCheckedFillStyle", "Horiz Angle"); - break; - case 2: - value = QCoreApplication::translate("TCheckedFillStyle", "Vert Dist"); - break; - case 3: - value = QCoreApplication::translate("TCheckedFillStyle", "Vert Angle"); - break; - case 4: - value = QCoreApplication::translate("TCheckedFillStyle", "Thickness"); - break; - } - - return value; +QString TCheckedFillStyle::getParamNames(int index) const { + assert(0 <= index && index < 5); + + QString value; + switch (index) { + case 0: + value = QCoreApplication::translate("TCheckedFillStyle", "Horiz Dist"); + break; + case 1: + value = QCoreApplication::translate("TCheckedFillStyle", "Horiz Angle"); + break; + case 2: + value = QCoreApplication::translate("TCheckedFillStyle", "Vert Dist"); + break; + case 3: + value = QCoreApplication::translate("TCheckedFillStyle", "Vert Angle"); + break; + case 4: + value = QCoreApplication::translate("TCheckedFillStyle", "Thickness"); + break; + } + + return value; } //----------------------------------------------------------------------------- -void TCheckedFillStyle::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 5); - switch (index) { - case 0: - min = 1.0; - max = 100.0; - break; - case 1: - min = -45.0; - max = 45.0; - break; - case 2: - min = 1.0; - max = 100.0; - break; - case 3: - min = -45.0; - max = 45.0; - break; - case 4: - min = 0.5; - max = 100.0; - break; - } +void TCheckedFillStyle::getParamRange(int index, double &min, + double &max) const { + assert(0 <= index && index < 5); + switch (index) { + case 0: + min = 1.0; + max = 100.0; + break; + case 1: + min = -45.0; + max = 45.0; + break; + case 2: + min = 1.0; + max = 100.0; + break; + case 3: + min = -45.0; + max = 45.0; + break; + case 4: + min = 0.5; + max = 100.0; + break; + } } //----------------------------------------------------------------------------- -double TCheckedFillStyle::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 5); - - switch (index) { - case 0: - return m_HDist; - case 1: - return m_HAngle; - case 2: - return m_VDist; - case 3: - return m_VAngle; - case 4: - return m_Thickness; - } - return 0.0; +double TCheckedFillStyle::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 5); + + switch (index) { + case 0: + return m_HDist; + case 1: + return m_HAngle; + case 2: + return m_VDist; + case 3: + return m_VAngle; + case 4: + return m_Thickness; + } + return 0.0; } //----------------------------------------------------------------------------- -void TCheckedFillStyle::setParamValue(int index, double value) -{ - assert(0 <= index && index < 5); - - switch (index) { - case 0: - m_HDist = value; - break; - case 1: - m_HAngle = value; - break; - case 2: - m_VDist = value; - break; - case 3: - m_VAngle = value; - break; - case 4: - m_Thickness = value; - break; - } -} - -//------------------------------------------------------------ - -void TCheckedFillStyle::loadData(TInputStreamInterface &is) -{ - TSolidColorStyle::loadData(is); - is >> m_HDist; - is >> m_HAngle; - is >> m_VDist; - is >> m_VAngle; - is >> m_Thickness; - is >> m_pointColor; +void TCheckedFillStyle::setParamValue(int index, double value) { + assert(0 <= index && index < 5); + + switch (index) { + case 0: + m_HDist = value; + break; + case 1: + m_HAngle = value; + break; + case 2: + m_VDist = value; + break; + case 3: + m_VAngle = value; + break; + case 4: + m_Thickness = value; + break; + } } //------------------------------------------------------------ -void TCheckedFillStyle::saveData(TOutputStreamInterface &os) const -{ - TSolidColorStyle::saveData(os); - os << m_HDist; - os << m_HAngle; - os << m_VDist; - os << m_VAngle; - os << m_Thickness; - os << m_pointColor; +void TCheckedFillStyle::loadData(TInputStreamInterface &is) { + TSolidColorStyle::loadData(is); + is >> m_HDist; + is >> m_HAngle; + is >> m_VDist; + is >> m_VAngle; + is >> m_Thickness; + is >> m_pointColor; +} + +//------------------------------------------------------------ + +void TCheckedFillStyle::saveData(TOutputStreamInterface &os) const { + TSolidColorStyle::saveData(os); + os << m_HDist; + os << m_HAngle; + os << m_VDist; + os << m_VAngle; + os << m_Thickness; + os << m_pointColor; } //------------------------------------------------------------ void TCheckedFillStyle::getHThickline(const TPointD &lc, const double lx, - TPointD &p0, TPointD &p1, - TPointD &p2, TPointD &p3) const -{ - double l = m_Thickness / cos(degree2rad(m_HAngle)); - l *= 0.5; - p0 = TPointD(lc.x, lc.y - l); - p1 = TPointD(lc.x, lc.y + l); - double y = lc.y + lx * tan(degree2rad(m_HAngle)); - p2 = TPointD(lc.x + lx, y + l); - p3 = TPointD(lc.x + lx, y - l); + TPointD &p0, TPointD &p1, TPointD &p2, + TPointD &p3) const { + double l = m_Thickness / cos(degree2rad(m_HAngle)); + l *= 0.5; + p0 = TPointD(lc.x, lc.y - l); + p1 = TPointD(lc.x, lc.y + l); + double y = lc.y + lx * tan(degree2rad(m_HAngle)); + p2 = TPointD(lc.x + lx, y + l); + p3 = TPointD(lc.x + lx, y - l); } //------------------------------------------------------------ void TCheckedFillStyle::getVThickline(const TPointD &lc, const double ly, - TPointD &p0, TPointD &p1, - TPointD &p2, TPointD &p3) const -{ - double l = m_Thickness / cos(degree2rad(-m_VAngle)); - l *= 0.5; - p0 = TPointD(lc.x - l, lc.y); - p1 = TPointD(lc.x + l, lc.y); - double x = lc.x + ly * tan(degree2rad(-m_VAngle)); - p2 = TPointD(x + l, lc.y + ly); - p3 = TPointD(x - l, lc.y + ly); + TPointD &p0, TPointD &p1, TPointD &p2, + TPointD &p3) const { + double l = m_Thickness / cos(degree2rad(-m_VAngle)); + l *= 0.5; + p0 = TPointD(lc.x - l, lc.y); + p1 = TPointD(lc.x + l, lc.y); + double x = lc.x + ly * tan(degree2rad(-m_VAngle)); + p2 = TPointD(x + l, lc.y + ly); + p3 = TPointD(x - l, lc.y + ly); } //------------------------------------------------------------ -TPixel32 TCheckedFillStyle::getColorParamValue(int index) const -{ - return index == 0 ? m_pointColor : TSolidColorStyle::getMainColor(); +TPixel32 TCheckedFillStyle::getColorParamValue(int index) const { + return index == 0 ? m_pointColor : TSolidColorStyle::getMainColor(); } //------------------------------------------------------------ -void TCheckedFillStyle::setColorParamValue(int index, const TPixel32 &color) -{ - if (index == 0) - m_pointColor = color; - else { - TSolidColorStyle::setMainColor(color); - } +void TCheckedFillStyle::setColorParamValue(int index, const TPixel32 &color) { + if (index == 0) + m_pointColor = color; + else { + TSolidColorStyle::setMainColor(color); + } } //------------------------------------------------------------ -void TCheckedFillStyle::drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const -{ - TStencilControl *stenc = TStencilControl::instance(); - TPixel32 backgroundColor = TSolidColorStyle::getMainColor(); - if (cf) - backgroundColor = (*(cf))(backgroundColor); - - if (backgroundColor.m == 0) { //only to create stencil mask - TSolidColorStyle appStyle(TPixel32::White); - stenc->beginMask(); //does not draw on screen - appStyle.drawRegion(0, false, boundary); - } else { //create stencil mask and draw on screen - stenc->beginMask(TStencilControl::DRAW_ALSO_ON_SCREEN); - TSolidColorStyle::drawRegion(cf, antiAliasing, boundary); - } - stenc->endMask(); - stenc->enableMask(TStencilControl::SHOW_INSIDE); - - const bool isTransparent = m_pointColor.m < 255; - if (isTransparent) { - //glEnable(GL_BLEND); - //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - //// <-- tglEnableBlending(); - } - - glBegin(GL_QUADS); - TPixel32 color; - if (cf) - color = (*(cf))(m_pointColor); - else - color = m_pointColor; - - tglColor(color); - - // Horizontal Lines - double lx = boundary.m_bbox.x1 - boundary.m_bbox.x0; - double ly = boundary.m_bbox.y1 - boundary.m_bbox.y0; - double beg = boundary.m_bbox.y0; - double end = boundary.m_bbox.y1; - beg = m_HAngle <= 0 ? beg : beg - lx * tan(degree2rad(m_HAngle)); - end = m_HAngle >= 0 ? end : end - lx * tan(degree2rad(m_HAngle)); - double dist = m_HDist / cos(degree2rad(m_HAngle)); - for (double y = beg; y <= end; y += dist) { - TPointD p0, p1, p2, p3; - getHThickline(TPointD(boundary.m_bbox.x0, y), lx, p0, p1, p2, p3); - tglVertex(p0); - tglVertex(p1); - tglVertex(p2); - tglVertex(p3); - } - - // Vertical Lines - beg = boundary.m_bbox.x0; - end = boundary.m_bbox.x1; - beg = (-m_VAngle) <= 0 ? beg : beg - ly * tan(degree2rad(-m_VAngle)); - end = (-m_VAngle) >= 0 ? end : end - ly * tan(degree2rad(-m_VAngle)); - dist = m_VDist / cos(degree2rad(-m_VAngle)); - for (double x = beg; x <= end; x += dist) { - TPointD p0, p1, p2, p3; - getVThickline(TPointD(x, boundary.m_bbox.y0), ly, p0, p1, p2, p3); - tglVertex(p0); - tglVertex(p1); - tglVertex(p2); - tglVertex(p3); - } - - glEnd(); - - if (isTransparent) { - //tglColor(TPixel32::White); - //glDisable(GL_BLEND); - } - - stenc->disableMask(); -} - -//------------------------------------------------------------ - -int TCheckedFillStyle::nbClip(const TRectD &bbox) const -{ - int nbClip = 1; // the bbox rectangle +void TCheckedFillStyle::drawRegion(const TColorFunction *cf, + const bool antiAliasing, + TRegionOutline &boundary) const { + TStencilControl *stenc = TStencilControl::instance(); + TPixel32 backgroundColor = TSolidColorStyle::getMainColor(); + if (cf) backgroundColor = (*(cf))(backgroundColor); + + if (backgroundColor.m == 0) { // only to create stencil mask + TSolidColorStyle appStyle(TPixel32::White); + stenc->beginMask(); // does not draw on screen + appStyle.drawRegion(0, false, boundary); + } else { // create stencil mask and draw on screen + stenc->beginMask(TStencilControl::DRAW_ALSO_ON_SCREEN); + TSolidColorStyle::drawRegion(cf, antiAliasing, boundary); + } + stenc->endMask(); + stenc->enableMask(TStencilControl::SHOW_INSIDE); + + const bool isTransparent = m_pointColor.m < 255; + if (isTransparent) { + // glEnable(GL_BLEND); + // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + //// <-- tglEnableBlending(); + } + + glBegin(GL_QUADS); + TPixel32 color; + if (cf) + color = (*(cf))(m_pointColor); + else + color = m_pointColor; + + tglColor(color); + + // Horizontal Lines + double lx = boundary.m_bbox.x1 - boundary.m_bbox.x0; + double ly = boundary.m_bbox.y1 - boundary.m_bbox.y0; + double beg = boundary.m_bbox.y0; + double end = boundary.m_bbox.y1; + beg = m_HAngle <= 0 ? beg : beg - lx * tan(degree2rad(m_HAngle)); + end = m_HAngle >= 0 ? end : end - lx * tan(degree2rad(m_HAngle)); + double dist = m_HDist / cos(degree2rad(m_HAngle)); + for (double y = beg; y <= end; y += dist) { + TPointD p0, p1, p2, p3; + getHThickline(TPointD(boundary.m_bbox.x0, y), lx, p0, p1, p2, p3); + tglVertex(p0); + tglVertex(p1); + tglVertex(p2); + tglVertex(p3); + } + + // Vertical Lines + beg = boundary.m_bbox.x0; + end = boundary.m_bbox.x1; + beg = (-m_VAngle) <= 0 ? beg : beg - ly * tan(degree2rad(-m_VAngle)); + end = (-m_VAngle) >= 0 ? end : end - ly * tan(degree2rad(-m_VAngle)); + dist = m_VDist / cos(degree2rad(-m_VAngle)); + for (double x = beg; x <= end; x += dist) { + TPointD p0, p1, p2, p3; + getVThickline(TPointD(x, boundary.m_bbox.y0), ly, p0, p1, p2, p3); + tglVertex(p0); + tglVertex(p1); + tglVertex(p2); + tglVertex(p3); + } + + glEnd(); + + if (isTransparent) { + // tglColor(TPixel32::White); + // glDisable(GL_BLEND); + } + + stenc->disableMask(); +} + +//------------------------------------------------------------ - double lx = bbox.x1 - bbox.x0; - double ly = bbox.y1 - bbox.y0; - double beg = bbox.y0; - double end = bbox.y1; - beg = m_HAngle <= 0 ? beg : beg - lx * tan(degree2rad(m_HAngle)); - end = m_HAngle >= 0 ? end : end - lx * tan(degree2rad(m_HAngle)); - double dist = m_HDist / cos(degree2rad(m_HAngle)); - for (double y = beg; y <= end; y += dist) - nbClip++; +int TCheckedFillStyle::nbClip(const TRectD &bbox) const { + int nbClip = 1; // the bbox rectangle - // Vertical lines - beg = bbox.x0; - end = bbox.x1; - beg = (-m_VAngle) <= 0 ? beg : beg - ly * tan(degree2rad(-m_VAngle)); - end = (-m_VAngle) >= 0 ? end : end - ly * tan(degree2rad(-m_VAngle)); - dist = m_VDist / cos(degree2rad(-m_VAngle)); - for (double x = beg; x <= end; x += dist) - nbClip++; - return nbClip; + double lx = bbox.x1 - bbox.x0; + double ly = bbox.y1 - bbox.y0; + double beg = bbox.y0; + double end = bbox.y1; + beg = m_HAngle <= 0 ? beg : beg - lx * tan(degree2rad(m_HAngle)); + end = m_HAngle >= 0 ? end : end - lx * tan(degree2rad(m_HAngle)); + double dist = m_HDist / cos(degree2rad(m_HAngle)); + for (double y = beg; y <= end; y += dist) nbClip++; + + // Vertical lines + beg = bbox.x0; + end = bbox.x1; + beg = (-m_VAngle) <= 0 ? beg : beg - ly * tan(degree2rad(-m_VAngle)); + end = (-m_VAngle) >= 0 ? end : end - ly * tan(degree2rad(-m_VAngle)); + dist = m_VDist / cos(degree2rad(-m_VAngle)); + for (double x = beg; x <= end; x += dist) nbClip++; + return nbClip; } //------------------------------------------------------------ -void TCheckedFillStyle::drawRegion(TFlash &flash, const TRegion *r) const -{ - TRectD bbox(r->getBBox()); - - // flash.drawRegion(*r,true); - flash.drawRegion(*r, nbClip(bbox)); - - flash.setFillColor(getMainColor()); - flash.drawRectangle(bbox); - - flash.setFillColor(m_pointColor); - // Horizontal Lines - double lx = bbox.x1 - bbox.x0; - double ly = bbox.y1 - bbox.y0; - double beg = bbox.y0; - double end = bbox.y1; - beg = m_HAngle <= 0 ? beg : beg - lx * tan(degree2rad(m_HAngle)); - end = m_HAngle >= 0 ? end : end - lx * tan(degree2rad(m_HAngle)); - double dist = m_HDist / cos(degree2rad(m_HAngle)); - for (double y = beg; y <= end; y += dist) { - TPointD p0, p1, p2, p3; - getHThickline(TPointD(bbox.x0, y), lx, p0, p1, p2, p3); - std::vector v; - v.push_back(p0); - v.push_back(p1); - v.push_back(p2); - v.push_back(p3); - flash.drawPolyline(v); - } - - // Vertical lines - beg = bbox.x0; - end = bbox.x1; - beg = (-m_VAngle) <= 0 ? beg : beg - ly * tan(degree2rad(-m_VAngle)); - end = (-m_VAngle) >= 0 ? end : end - ly * tan(degree2rad(-m_VAngle)); - dist = m_VDist / cos(degree2rad(-m_VAngle)); - for (double x = beg; x <= end; x += dist) { - TPointD p0, p1, p2, p3; - getVThickline(TPointD(x, bbox.y0), ly, p0, p1, p2, p3); - std::vector v; - v.push_back(p0); - v.push_back(p1); - v.push_back(p2); - v.push_back(p3); - flash.drawPolyline(v); - } +void TCheckedFillStyle::drawRegion(TFlash &flash, const TRegion *r) const { + TRectD bbox(r->getBBox()); + + // flash.drawRegion(*r,true); + flash.drawRegion(*r, nbClip(bbox)); + + flash.setFillColor(getMainColor()); + flash.drawRectangle(bbox); + + flash.setFillColor(m_pointColor); + // Horizontal Lines + double lx = bbox.x1 - bbox.x0; + double ly = bbox.y1 - bbox.y0; + double beg = bbox.y0; + double end = bbox.y1; + beg = m_HAngle <= 0 ? beg : beg - lx * tan(degree2rad(m_HAngle)); + end = m_HAngle >= 0 ? end : end - lx * tan(degree2rad(m_HAngle)); + double dist = m_HDist / cos(degree2rad(m_HAngle)); + for (double y = beg; y <= end; y += dist) { + TPointD p0, p1, p2, p3; + getHThickline(TPointD(bbox.x0, y), lx, p0, p1, p2, p3); + std::vector v; + v.push_back(p0); + v.push_back(p1); + v.push_back(p2); + v.push_back(p3); + flash.drawPolyline(v); + } + + // Vertical lines + beg = bbox.x0; + end = bbox.x1; + beg = (-m_VAngle) <= 0 ? beg : beg - ly * tan(degree2rad(-m_VAngle)); + end = (-m_VAngle) >= 0 ? end : end - ly * tan(degree2rad(-m_VAngle)); + dist = m_VDist / cos(degree2rad(-m_VAngle)); + for (double x = beg; x <= end; x += dist) { + TPointD p0, p1, p2, p3; + getVThickline(TPointD(x, bbox.y0), ly, p0, p1, p2, p3); + std::vector v; + v.push_back(p0); + v.push_back(p1); + v.push_back(p2); + v.push_back(p3); + flash.drawPolyline(v); + } } //*************************************************************************** // ArtisticModifier implementation //*************************************************************************** -void ArtisticModifier::modify(TRegionOutline &outline) const -{ +void ArtisticModifier::modify(TRegionOutline &outline) const { + TRegionOutline::Boundary::iterator regIt = outline.m_exterior.begin(); + TRegionOutline::Boundary::iterator regItEnd = outline.m_exterior.end(); + + TRegionOutline::PointVector::iterator pIt; + TRegionOutline::PointVector::iterator pItEnd; + TRandom rnd; + double counter = 0; + double maxcounter = 0; + for (; regIt != regItEnd; ++regIt) { + pIt = regIt->begin(); + pItEnd = regIt->end(); + + for (; pIt != pItEnd; ++pIt) { + if (counter >= maxcounter) { + double tmp = (201 - m_period) * (rnd.getFloat() + 1); + maxcounter = tmp * tmp; + counter = 0; + } + if (pIt != regIt->begin()) { + double distance = (pIt->x - (pIt - 1)->x) * (pIt->x - (pIt - 1)->x) + + (pIt->y - (pIt - 1)->y) * (pIt->y - (pIt - 1)->y); + counter += distance; + } + double wave = 1; + if (maxcounter) wave = sin(M_2PI * counter / maxcounter); - TRegionOutline::Boundary::iterator regIt = outline.m_exterior.begin(); - TRegionOutline::Boundary::iterator regItEnd = outline.m_exterior.end(); - - TRegionOutline::PointVector::iterator pIt; - TRegionOutline::PointVector::iterator pItEnd; - TRandom rnd; - double counter = 0; - double maxcounter = 0; - for (; regIt != regItEnd; ++regIt) { - pIt = regIt->begin(); - pItEnd = regIt->end(); - - for (; pIt != pItEnd; ++pIt) { - if (counter >= maxcounter) { - double tmp = (201 - m_period) * (rnd.getFloat() + 1); - maxcounter = tmp * tmp; - counter = 0; - } - if (pIt != regIt->begin()) { - double distance = (pIt->x - (pIt - 1)->x) * (pIt->x - (pIt - 1)->x) + (pIt->y - (pIt - 1)->y) * (pIt->y - (pIt - 1)->y); - counter += distance; - } - double wave = 1; - if (maxcounter) - wave = sin(pi2 * counter / maxcounter); - - pIt->x += m_move.x * wave; - pIt->y += m_move.y * wave; - } - } - - regIt = outline.m_interior.begin(); - regItEnd = outline.m_interior.end(); - for (; regIt != regItEnd; ++regIt) { - pIt = regIt->begin(); - pItEnd = regIt->end(); - - for (; pIt != pItEnd; ++pIt) { - pIt->x += (0.5 - rnd.getFloat()) * m_move.x; - pIt->y += (0.5 - rnd.getFloat()) * m_move.y; - } - } -} - -//------------------------------------------------------------ - -TOutlineStyle::RegionOutlineModifier *ArtisticModifier::clone() const -{ - return new ArtisticModifier(*this); + pIt->x += m_move.x * wave; + pIt->y += m_move.y * wave; + } + } + + regIt = outline.m_interior.begin(); + regItEnd = outline.m_interior.end(); + for (; regIt != regItEnd; ++regIt) { + pIt = regIt->begin(); + pItEnd = regIt->end(); + + for (; pIt != pItEnd; ++pIt) { + pIt->x += (0.5 - rnd.getFloat()) * m_move.x; + pIt->y += (0.5 - rnd.getFloat()) * m_move.y; + } + } +} + +//------------------------------------------------------------ + +TOutlineStyle::RegionOutlineModifier *ArtisticModifier::clone() const { + return new ArtisticModifier(*this); } //*************************************************************************** // ArtisticSolidColor implementation //*************************************************************************** -ArtisticSolidColor::ArtisticSolidColor( - const TPixel32 &color, const TPointD &move, double period) - : TSolidColorStyle(color) -{ - m_regionOutlineModifier = new ArtisticModifier(move, period); +ArtisticSolidColor::ArtisticSolidColor(const TPixel32 &color, + const TPointD &move, double period) + : TSolidColorStyle(color) { + m_regionOutlineModifier = new ArtisticModifier(move, period); } //------------------------------------------------------------ -TColorStyle *ArtisticSolidColor::clone() const -{ - return new ArtisticSolidColor(*this); +TColorStyle *ArtisticSolidColor::clone() const { + return new ArtisticSolidColor(*this); } //------------------------------------------------------------ -void ArtisticSolidColor::loadData(TInputStreamInterface &is) -{ - TSolidColorStyle::loadData(is); - delete m_regionOutlineModifier; - ArtisticModifier *mov = new ArtisticModifier(TPointD(), double()); - mov->loadData(is); - m_regionOutlineModifier = mov; +void ArtisticSolidColor::loadData(TInputStreamInterface &is) { + TSolidColorStyle::loadData(is); + delete m_regionOutlineModifier; + ArtisticModifier *mov = new ArtisticModifier(TPointD(), double()); + mov->loadData(is); + m_regionOutlineModifier = mov; } //------------------------------------------------------------ -void ArtisticSolidColor::saveData(TOutputStreamInterface &os) const -{ - TSolidColorStyle::saveData(os); +void ArtisticSolidColor::saveData(TOutputStreamInterface &os) const { + TSolidColorStyle::saveData(os); - assert(m_regionOutlineModifier); - ((ArtisticModifier *)m_regionOutlineModifier)->saveData(os); + assert(m_regionOutlineModifier); + ((ArtisticModifier *)m_regionOutlineModifier)->saveData(os); } //------------------------------------------------------------ -int ArtisticSolidColor::getParamCount() const -{ - return 3; -} +int ArtisticSolidColor::getParamCount() const { return 3; } //----------------------------------------------------------------------------- -TColorStyle::ParamType ArtisticSolidColor::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +TColorStyle::ParamType ArtisticSolidColor::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -QString ArtisticSolidColor::getParamNames(int index) const -{ - assert(0 <= index && index < 3); - QString value; - switch (index) { - case 0: - value = QCoreApplication::translate("ArtisticSolidColor", "Horiz Offset"); - break; - case 1: - value = QCoreApplication::translate("ArtisticSolidColor", "Vert Offset"); - break; - case 2: - value = QCoreApplication::translate("ArtisticSolidColor", "Noise"); - break; - } - return value; +QString ArtisticSolidColor::getParamNames(int index) const { + assert(0 <= index && index < 3); + QString value; + switch (index) { + case 0: + value = QCoreApplication::translate("ArtisticSolidColor", "Horiz Offset"); + break; + case 1: + value = QCoreApplication::translate("ArtisticSolidColor", "Vert Offset"); + break; + case 2: + value = QCoreApplication::translate("ArtisticSolidColor", "Noise"); + break; + } + return value; } //----------------------------------------------------------------------------- -void ArtisticSolidColor::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 3); - switch (index) { - case 0: - min = 0.0; - max = 20.0; - break; - case 1: - min = 0.0; - max = 20.0; - break; - case 2: - min = 0.0; - max = 200.0; - break; - } +void ArtisticSolidColor::getParamRange(int index, double &min, + double &max) const { + assert(0 <= index && index < 3); + switch (index) { + case 0: + min = 0.0; + max = 20.0; + break; + case 1: + min = 0.0; + max = 20.0; + break; + case 2: + min = 0.0; + max = 200.0; + break; + } } //----------------------------------------------------------------------------- -double ArtisticSolidColor::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 3); - double value; - switch (index) { - case 0: - value = ((ArtisticModifier *)m_regionOutlineModifier)->getMovePoint().x; - break; - case 1: - value = ((ArtisticModifier *)m_regionOutlineModifier)->getMovePoint().y; - break; - case 2: - value = ((ArtisticModifier *)m_regionOutlineModifier)->getPeriod(); - break; - } - return value; +double ArtisticSolidColor::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 3); + double value; + switch (index) { + case 0: + value = ((ArtisticModifier *)m_regionOutlineModifier)->getMovePoint().x; + break; + case 1: + value = ((ArtisticModifier *)m_regionOutlineModifier)->getMovePoint().y; + break; + case 2: + value = ((ArtisticModifier *)m_regionOutlineModifier)->getPeriod(); + break; + } + return value; } //----------------------------------------------------------------------------- -void ArtisticSolidColor::setParamValue(int index, double value) -{ - assert(0 <= index && index < 3); - - TPointD oldMove = ((ArtisticModifier *)m_regionOutlineModifier)->getMovePoint(); - double oldPeriod = ((ArtisticModifier *)m_regionOutlineModifier)->getPeriod(); - - switch (index) { - case 0: - if (oldMove.x != value) { - delete m_regionOutlineModifier; - oldMove.x = value; - m_regionOutlineModifier = new ArtisticModifier(oldMove, oldPeriod); - updateVersionNumber(); - } - break; - case 1: - if (oldMove.y != value) { - delete m_regionOutlineModifier; - oldMove.y = value; - m_regionOutlineModifier = new ArtisticModifier(oldMove, oldPeriod); - updateVersionNumber(); - } - break; - case 2: - if (oldPeriod != value) { - delete m_regionOutlineModifier; - oldPeriod = value; - m_regionOutlineModifier = new ArtisticModifier(oldMove, oldPeriod); - updateVersionNumber(); - } - break; - } -} - -//------------------------------------------------------------ - -void ArtisticSolidColor::drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const -{ - TSolidColorStyle::drawRegion(cf, true, boundary); +void ArtisticSolidColor::setParamValue(int index, double value) { + assert(0 <= index && index < 3); + + TPointD oldMove = + ((ArtisticModifier *)m_regionOutlineModifier)->getMovePoint(); + double oldPeriod = ((ArtisticModifier *)m_regionOutlineModifier)->getPeriod(); + + switch (index) { + case 0: + if (oldMove.x != value) { + delete m_regionOutlineModifier; + oldMove.x = value; + m_regionOutlineModifier = new ArtisticModifier(oldMove, oldPeriod); + updateVersionNumber(); + } + break; + case 1: + if (oldMove.y != value) { + delete m_regionOutlineModifier; + oldMove.y = value; + m_regionOutlineModifier = new ArtisticModifier(oldMove, oldPeriod); + updateVersionNumber(); + } + break; + case 2: + if (oldPeriod != value) { + delete m_regionOutlineModifier; + oldPeriod = value; + m_regionOutlineModifier = new ArtisticModifier(oldMove, oldPeriod); + updateVersionNumber(); + } + break; + } } //------------------------------------------------------------ -void ArtisticSolidColor::drawRegion(TFlash &flash, const TRegion *r) const -{ - SFlashUtils rdf(r); - rdf.computeRegionOutline(); - m_regionOutlineModifier->modify(rdf.m_ro); - flash.setFillColor(getMainColor()); - rdf.drawRegionOutline(flash, false); +void ArtisticSolidColor::drawRegion(const TColorFunction *cf, + const bool antiAliasing, + TRegionOutline &boundary) const { + TSolidColorStyle::drawRegion(cf, true, boundary); +} + +//------------------------------------------------------------ + +void ArtisticSolidColor::drawRegion(TFlash &flash, const TRegion *r) const { + SFlashUtils rdf(r); + rdf.computeRegionOutline(); + m_regionOutlineModifier->modify(rdf.m_ro); + flash.setFillColor(getMainColor()); + rdf.drawRegionOutline(flash, false); } //*************************************************************************** @@ -2486,1274 +2365,1231 @@ void ArtisticSolidColor::drawRegion(TFlash &flash, const TRegion *r) const //*************************************************************************** TChalkFillStyle::TChalkFillStyle(const TPixel32 &color0, const TPixel32 &color1, - const double density, const double size) - : TSolidColorStyle(color1), m_color0(color0), m_density(density), m_size(size) -{ -} + const double density, const double size) + : TSolidColorStyle(color1) + , m_color0(color0) + , m_density(density) + , m_size(size) {} //------------------------------------------------------------ TChalkFillStyle::TChalkFillStyle(const TPixel32 &color0, const TPixel32 &color1) - : TSolidColorStyle(color0), m_color0(color1), m_density(25.0), m_size(1.0) -{ -} + : TSolidColorStyle(color0) + , m_color0(color1) + , m_density(25.0) + , m_size(1.0) {} //------------------------------------------------------------ -TColorStyle *TChalkFillStyle::clone() const -{ - return new TChalkFillStyle(*this); +TColorStyle *TChalkFillStyle::clone() const { + return new TChalkFillStyle(*this); } //------------------------------------------------------------ -int TChalkFillStyle::getParamCount() const -{ - return 2; -} +int TChalkFillStyle::getParamCount() const { return 2; } //----------------------------------------------------------------------------- -TColorStyle::ParamType TChalkFillStyle::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +TColorStyle::ParamType TChalkFillStyle::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -QString TChalkFillStyle::getParamNames(int index) const -{ - assert(0 <= index && index < 2); - QString value; - switch (index) { - case 0: - value = QCoreApplication::translate("TChalkFillStyle", "Density"); - break; - case 1: - value = QCoreApplication::translate("TChalkFillStyle", "Dot Size"); - break; - } +QString TChalkFillStyle::getParamNames(int index) const { + assert(0 <= index && index < 2); + QString value; + switch (index) { + case 0: + value = QCoreApplication::translate("TChalkFillStyle", "Density"); + break; + case 1: + value = QCoreApplication::translate("TChalkFillStyle", "Dot Size"); + break; + } - return value; + return value; } //----------------------------------------------------------------------------- -void TChalkFillStyle::loadData(int ids, TInputStreamInterface &is) -{ - if (ids != 1133) - throw TException("Chalk Fill style: unknown obsolete format"); - TSolidColorStyle::loadData(is); - is >> m_color0 >> m_density >> m_size; - m_density = m_density / 1000; - if (m_density > 100) - m_density = 100; +void TChalkFillStyle::loadData(int ids, TInputStreamInterface &is) { + if (ids != 1133) + throw TException("Chalk Fill style: unknown obsolete format"); + TSolidColorStyle::loadData(is); + is >> m_color0 >> m_density >> m_size; + m_density = m_density / 1000; + if (m_density > 100) m_density = 100; } //----------------------------------------------------------------------------- -void TChalkFillStyle::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 2); - switch (index) { - case 0: - min = 0; - max = 100.0; - break; - case 1: - min = 0.0; - max = 10.0; - break; - } +void TChalkFillStyle::getParamRange(int index, double &min, double &max) const { + assert(0 <= index && index < 2); + switch (index) { + case 0: + min = 0; + max = 100.0; + break; + case 1: + min = 0.0; + max = 10.0; + break; + } } //----------------------------------------------------------------------------- -double TChalkFillStyle::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 2); - double value; - switch (index) { - case 0: - value = m_density; - break; - case 1: - value = m_size; - break; - } - return value; +double TChalkFillStyle::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 2); + double value; + switch (index) { + case 0: + value = m_density; + break; + case 1: + value = m_size; + break; + } + return value; } //----------------------------------------------------------------------------- -void TChalkFillStyle::setParamValue(int index, double value) -{ - assert(0 <= index && index < 2); +void TChalkFillStyle::setParamValue(int index, double value) { + assert(0 <= index && index < 2); - switch (index) { - case 0: - m_density = value; - break; - case 1: - m_size = value; - break; - } + switch (index) { + case 0: + m_density = value; + break; + case 1: + m_size = value; + break; + } } //------------------------------------------------------------ -void TChalkFillStyle::loadData(TInputStreamInterface &is) -{ - TSolidColorStyle::loadData(is); - is >> m_color0; - is >> m_density; - is >> m_size; +void TChalkFillStyle::loadData(TInputStreamInterface &is) { + TSolidColorStyle::loadData(is); + is >> m_color0; + is >> m_density; + is >> m_size; } //------------------------------------------------------------ -void TChalkFillStyle::saveData(TOutputStreamInterface &os) const -{ - TSolidColorStyle::saveData(os); - os << m_color0; - os << m_density; - os << m_size; +void TChalkFillStyle::saveData(TOutputStreamInterface &os) const { + TSolidColorStyle::saveData(os); + os << m_color0; + os << m_density; + os << m_size; } //------------------------------------------------------------ -TPixel32 TChalkFillStyle::getColorParamValue(int index) const -{ - return index == 0 ? m_color0 : TSolidColorStyle::getMainColor(); +TPixel32 TChalkFillStyle::getColorParamValue(int index) const { + return index == 0 ? m_color0 : TSolidColorStyle::getMainColor(); } //------------------------------------------------------------ -void TChalkFillStyle::setColorParamValue(int index, const TPixel32 &color) -{ - if (index == 0) - m_color0 = color; - else { - TSolidColorStyle::setMainColor(color); - } +void TChalkFillStyle::setColorParamValue(int index, const TPixel32 &color) { + if (index == 0) + m_color0 = color; + else { + TSolidColorStyle::setMainColor(color); + } } //------------------------------------------------------------ -void TChalkFillStyle::drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const -{ - //const bool isTransparent=m_color0.m<255; - - //TRegionOutline::Boundary& exter=*(boundary.m_exterior); - //TRegionOutline::Boundary& inter=*(boundary.m_interior); - - TPixel32 color0; - if (cf) - color0 = (*(cf))(m_color0); - else - color0 = m_color0; - - TStencilControl *stenc = TStencilControl::instance(); - TPixel32 backgroundColor = TSolidColorStyle::getMainColor(); - if (cf) - backgroundColor = (*(cf))(backgroundColor); - - if (backgroundColor.m == 0) { //only to create stencil mask - TSolidColorStyle appStyle(TPixel32::White); - stenc->beginMask(); //does not draw on screen - appStyle.drawRegion(0, false, boundary); - } else { //create stencil mask and draw on screen - stenc->beginMask(TStencilControl::DRAW_ALSO_ON_SCREEN); - TSolidColorStyle::drawRegion(cf, antiAliasing, boundary); - } - stenc->endMask(); - stenc->enableMask(TStencilControl::SHOW_INSIDE); - - int chalkId = glGenLists(1); - glNewList(chalkId, GL_COMPILE); - glBegin(GL_QUADS); - glVertex2d(m_size, m_size); - glVertex2d(-m_size, m_size); - glVertex2d(-m_size, -m_size); - glVertex2d(m_size, -m_size); - glEnd(); - glEndList(); - TRandom rnd; - - double lx = boundary.m_bbox.x1 - boundary.m_bbox.x0; - double ly = boundary.m_bbox.y1 - boundary.m_bbox.y0; - - // cioe' imposta una densita' tale, per cui in una regione che ha bbox 200x200 - // inserisce esattamente m_density punti - int pointNumber = (int)(m_density * ((lx * ly) * 0.02)); - - for (int i = 0; i < pointNumber; i++) { - TPixel32 tmpcolor = color0; - double shiftx = boundary.m_bbox.x0 + rnd.getFloat() * lx; - double shifty = boundary.m_bbox.y0 + rnd.getFloat() * ly; - tmpcolor.m = (UCHAR)(tmpcolor.m * rnd.getFloat()); - tglColor(tmpcolor); - glPushMatrix(); - glTranslated(shiftx, shifty, 0.0); - glCallList(chalkId); - glPopMatrix(); - } - - //glEnd(); e questo che era??? - - glDeleteLists(chalkId, 1); - - stenc->disableMask(); -} - -//------------------------------------------------------------ - -void TChalkFillStyle::drawRegion(TFlash &flash, const TRegion *r) const -{ +void TChalkFillStyle::drawRegion(const TColorFunction *cf, + const bool antiAliasing, + TRegionOutline &boundary) const { + // const bool isTransparent=m_color0.m<255; + + // TRegionOutline::Boundary& exter=*(boundary.m_exterior); + // TRegionOutline::Boundary& inter=*(boundary.m_interior); + + TPixel32 color0; + if (cf) + color0 = (*(cf))(m_color0); + else + color0 = m_color0; + + TStencilControl *stenc = TStencilControl::instance(); + TPixel32 backgroundColor = TSolidColorStyle::getMainColor(); + if (cf) backgroundColor = (*(cf))(backgroundColor); + + if (backgroundColor.m == 0) { // only to create stencil mask + TSolidColorStyle appStyle(TPixel32::White); + stenc->beginMask(); // does not draw on screen + appStyle.drawRegion(0, false, boundary); + } else { // create stencil mask and draw on screen + stenc->beginMask(TStencilControl::DRAW_ALSO_ON_SCREEN); + TSolidColorStyle::drawRegion(cf, antiAliasing, boundary); + } + stenc->endMask(); + stenc->enableMask(TStencilControl::SHOW_INSIDE); + + int chalkId = glGenLists(1); + glNewList(chalkId, GL_COMPILE); + glBegin(GL_QUADS); + glVertex2d(m_size, m_size); + glVertex2d(-m_size, m_size); + glVertex2d(-m_size, -m_size); + glVertex2d(m_size, -m_size); + glEnd(); + glEndList(); + TRandom rnd; - TPixel32 bgColor = TSolidColorStyle::getMainColor(); + double lx = boundary.m_bbox.x1 - boundary.m_bbox.x0; + double ly = boundary.m_bbox.y1 - boundary.m_bbox.y0; - double minDensity; - double maxDensity; + // cioe' imposta una densita' tale, per cui in una regione che ha bbox 200x200 + // inserisce esattamente m_density punti + int pointNumber = (int)(m_density * ((lx * ly) * 0.02)); + + for (int i = 0; i < pointNumber; i++) { + TPixel32 tmpcolor = color0; + double shiftx = boundary.m_bbox.x0 + rnd.getFloat() * lx; + double shifty = boundary.m_bbox.y0 + rnd.getFloat() * ly; + tmpcolor.m = (UCHAR)(tmpcolor.m * rnd.getFloat()); + tglColor(tmpcolor); + glPushMatrix(); + glTranslated(shiftx, shifty, 0.0); + glCallList(chalkId); + glPopMatrix(); + } - getParamRange(0, minDensity, maxDensity); + // glEnd(); e questo che era??? - double r1 = (m_density - minDensity) / (maxDensity - minDensity); - double r2 = 1.0 - r1; + glDeleteLists(chalkId, 1); - TPixel32 color((int)(bgColor.r * r2 + m_color0.r * r1), - (int)(bgColor.g * r2 + m_color0.g * r1), - (int)(bgColor.b * r2 + m_color0.b * r1), - (int)(bgColor.m * r2 + m_color0.m * r1)); + stenc->disableMask(); +} - flash.setFillColor(color); - flash.drawRegion(*r); +//------------------------------------------------------------ - /* - SFlashUtils rdf(r); - rdf.computeRegionOutline(); +void TChalkFillStyle::drawRegion(TFlash &flash, const TRegion *r) const { + TPixel32 bgColor = TSolidColorStyle::getMainColor(); - TRandom rnd; + double minDensity; + double maxDensity; - const bool isTransparent=m_color0.m<255; + getParamRange(0, minDensity, maxDensity); - TRegionOutline::Boundary& exter=*(rdf.m_ro.m_exterior); - TRegionOutline::Boundary& inter=*(rdf.m_ro.m_interior); + double r1 = (m_density - minDensity) / (maxDensity - minDensity); + double r2 = 1.0 - r1; - TPixel32 color0=m_color0; - - double lx=rdf.m_ro.m_bbox.x1-rdf.m_ro.m_bbox.x0; - double ly=rdf.m_ro.m_bbox.y1-rdf.m_ro.m_bbox.y0; + TPixel32 color((int)(bgColor.r * r2 + m_color0.r * r1), + (int)(bgColor.g * r2 + m_color0.g * r1), + (int)(bgColor.b * r2 + m_color0.b * r1), + (int)(bgColor.m * r2 + m_color0.m * r1)); - // cioe' imposta una densita' tale, per cui in una regione che ha bbox 200x200 - // inserisce esattamente m_density punti - int pointNumber= (int)(m_density*((lx*ly)*0.000025)); + flash.setFillColor(color); + flash.drawRegion(*r); - flash.drawRegion(*r,pointNumber+1); // -1 i don't know why + /* + SFlashUtils rdf(r); + rdf.computeRegionOutline(); - flash.setFillColor(getMainColor()); - flash.drawRectangle(TRectD(TPointD(rdf.m_ro.m_bbox.x0,rdf.m_ro.m_bbox.y0), - TPointD(rdf.m_ro.m_bbox.x1,rdf.m_ro.m_bbox.y1))); - - flash.setThickness(0.0); - for( int i=0;i< pointNumber; i++ ) { - TPixel32 tmpcolor=color0; - double shiftx=rdf.m_ro.m_bbox.x0+rnd.getFloat()*lx; - double shifty=rdf.m_ro.m_bbox.y0+rnd.getFloat()*ly; - tmpcolor.m=(UCHAR)(tmpcolor.m*rnd.getFloat()); - flash.setFillColor(tmpcolor); - flash.pushMatrix(); - TTranslation tM(shiftx, shifty); - flash.multMatrix(tM); - flash.drawRectangle(TRectD(TPointD(-1,-1),TPointD(1,1))); - flash.popMatrix(); - } - */ +TRandom rnd; + +const bool isTransparent=m_color0.m<255; + + TRegionOutline::Boundary& exter=*(rdf.m_ro.m_exterior); + TRegionOutline::Boundary& inter=*(rdf.m_ro.m_interior); + +TPixel32 color0=m_color0; + + double lx=rdf.m_ro.m_bbox.x1-rdf.m_ro.m_bbox.x0; + double ly=rdf.m_ro.m_bbox.y1-rdf.m_ro.m_bbox.y0; + +// cioe' imposta una densita' tale, per cui in una regione che ha bbox 200x200 +// inserisce esattamente m_density punti +int pointNumber= (int)(m_density*((lx*ly)*0.000025)); + +flash.drawRegion(*r,pointNumber+1); // -1 i don't know why + +flash.setFillColor(getMainColor()); +flash.drawRectangle(TRectD(TPointD(rdf.m_ro.m_bbox.x0,rdf.m_ro.m_bbox.y0), + TPointD(rdf.m_ro.m_bbox.x1,rdf.m_ro.m_bbox.y1))); + +flash.setThickness(0.0); +for( int i=0;i< pointNumber; i++ ) { + TPixel32 tmpcolor=color0; + double shiftx=rdf.m_ro.m_bbox.x0+rnd.getFloat()*lx; + double shifty=rdf.m_ro.m_bbox.y0+rnd.getFloat()*ly; + tmpcolor.m=(UCHAR)(tmpcolor.m*rnd.getFloat()); + flash.setFillColor(tmpcolor); + flash.pushMatrix(); + TTranslation tM(shiftx, shifty); + flash.multMatrix(tM); + flash.drawRectangle(TRectD(TPointD(-1,-1),TPointD(1,1))); + flash.popMatrix(); + } +*/ } //*************************************************************************** // TChessFillStyle implementation //*************************************************************************** -TChessFillStyle::TChessFillStyle(const TPixel32 &bgColor, const TPixel32 &pointColor, - const double HDist, const double VDist, const double Angle) - : TSolidColorStyle(bgColor), m_pointColor(pointColor), m_HDist(HDist), m_VDist(VDist), m_Angle(Angle) -{ -} +TChessFillStyle::TChessFillStyle(const TPixel32 &bgColor, + const TPixel32 &pointColor, const double HDist, + const double VDist, const double Angle) + : TSolidColorStyle(bgColor) + , m_pointColor(pointColor) + , m_HDist(HDist) + , m_VDist(VDist) + , m_Angle(Angle) {} //------------------------------------------------------------ TChessFillStyle::TChessFillStyle(const TPixel32 &color) - : TSolidColorStyle(TPixel32::White), m_pointColor(color), m_HDist(10.0), m_VDist(10.0), m_Angle(0.0) -{ -} + : TSolidColorStyle(TPixel32::White) + , m_pointColor(color) + , m_HDist(10.0) + , m_VDist(10.0) + , m_Angle(0.0) {} //------------------------------------------------------------ -TColorStyle *TChessFillStyle::clone() const -{ - return new TChessFillStyle(*this); +TColorStyle *TChessFillStyle::clone() const { + return new TChessFillStyle(*this); } //------------------------------------------------------------ -int TChessFillStyle::getParamCount() const -{ - return 3; -} +int TChessFillStyle::getParamCount() const { return 3; } //----------------------------------------------------------------------------- -TColorStyle::ParamType TChessFillStyle::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +TColorStyle::ParamType TChessFillStyle::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -QString TChessFillStyle::getParamNames(int index) const -{ - assert(0 <= index && index < 3); - - QString value; - switch (index) { - case 0: - value = QCoreApplication::translate("TChessFillStyle", "Horiz Size"); - break; - case 1: - value = QCoreApplication::translate("TChessFillStyle", "Vert Size"); - break; - case 2: - value = QCoreApplication::translate("TChessFillStyle", "Angle"); - break; - } +QString TChessFillStyle::getParamNames(int index) const { + assert(0 <= index && index < 3); + + QString value; + switch (index) { + case 0: + value = QCoreApplication::translate("TChessFillStyle", "Horiz Size"); + break; + case 1: + value = QCoreApplication::translate("TChessFillStyle", "Vert Size"); + break; + case 2: + value = QCoreApplication::translate("TChessFillStyle", "Angle"); + break; + } - return value; + return value; } //----------------------------------------------------------------------------- -void TChessFillStyle::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 3); - switch (index) { - case 0: - min = 1.0; - max = 100.0; - break; - case 1: - min = 1.0; - max = 100.0; - break; - case 2: - min = -45.0; - max = 45.0; - break; - } +void TChessFillStyle::getParamRange(int index, double &min, double &max) const { + assert(0 <= index && index < 3); + switch (index) { + case 0: + min = 1.0; + max = 100.0; + break; + case 1: + min = 1.0; + max = 100.0; + break; + case 2: + min = -45.0; + max = 45.0; + break; + } } //----------------------------------------------------------------------------- -double TChessFillStyle::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 3); - - switch (index) { - case 0: - return m_HDist; - case 1: - return m_VDist; - case 2: - return m_Angle; - } - return 0.0; +double TChessFillStyle::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 3); + + switch (index) { + case 0: + return m_HDist; + case 1: + return m_VDist; + case 2: + return m_Angle; + } + return 0.0; } //----------------------------------------------------------------------------- -void TChessFillStyle::setParamValue(int index, double value) -{ - assert(0 <= index && index < 3); +void TChessFillStyle::setParamValue(int index, double value) { + assert(0 <= index && index < 3); + + switch (index) { + case 0: + m_HDist = value; + break; + case 1: + m_VDist = value; + break; + case 2: + m_Angle = value; + break; + } +} + +//------------------------------------------------------------ - switch (index) { - case 0: - m_HDist = value; - break; - case 1: - m_VDist = value; - break; - case 2: - m_Angle = value; - break; - } +void TChessFillStyle::loadData(TInputStreamInterface &is) { + TSolidColorStyle::loadData(is); + is >> m_HDist; + is >> m_VDist; + is >> m_Angle; + is >> m_pointColor; } //------------------------------------------------------------ -void TChessFillStyle::loadData(TInputStreamInterface &is) -{ - TSolidColorStyle::loadData(is); - is >> m_HDist; - is >> m_VDist; - is >> m_Angle; - is >> m_pointColor; +void TChessFillStyle::saveData(TOutputStreamInterface &os) const { + TSolidColorStyle::saveData(os); + os << m_HDist; + os << m_VDist; + os << m_Angle; + os << m_pointColor; } //------------------------------------------------------------ -void TChessFillStyle::saveData(TOutputStreamInterface &os) const -{ - TSolidColorStyle::saveData(os); - os << m_HDist; - os << m_VDist; - os << m_Angle; - os << m_pointColor; +TPixel32 TChessFillStyle::getColorParamValue(int index) const { + return index == 0 ? m_pointColor : TSolidColorStyle::getMainColor(); } //------------------------------------------------------------ -TPixel32 TChessFillStyle::getColorParamValue(int index) const -{ - return index == 0 ? m_pointColor : TSolidColorStyle::getMainColor(); +void TChessFillStyle::setColorParamValue(int index, const TPixel32 &color) { + if (index == 0) + m_pointColor = color; + else { + TSolidColorStyle::setMainColor(color); + } } //------------------------------------------------------------ -void TChessFillStyle::setColorParamValue(int index, const TPixel32 &color) -{ - if (index == 0) - m_pointColor = color; - else { - TSolidColorStyle::setMainColor(color); - } +void TChessFillStyle::makeGrid(TRectD &bbox, TRotation &rotM, + std::vector &grid, int &nbClip) const { + double lx = bbox.x1 - bbox.x0; + double ly = bbox.y1 - bbox.y0; + TPointD center = + TPointD((bbox.x1 + bbox.x0) * 0.5, (bbox.y1 + bbox.y0) * 0.5); + double l = (lx + ly) / 1.3; + double l2 = l / 2; + + bool isFirst = true; + for (double y = -l2; y < (l2 + m_VDist); y += m_VDist) { + double x = isFirst ? -l2 : -l2 + m_HDist; + isFirst = !isFirst; + for (; x < (l2 + m_HDist); x += 2 * m_HDist) { + grid.push_back(rotM * TPointD(x, y) + center); + nbClip++; + } + } } //------------------------------------------------------------ -void TChessFillStyle::makeGrid(TRectD &bbox, TRotation &rotM, std::vector &grid, - int &nbClip) const -{ - double lx = bbox.x1 - bbox.x0; - double ly = bbox.y1 - bbox.y0; - TPointD center = TPointD((bbox.x1 + bbox.x0) * 0.5, - (bbox.y1 + bbox.y0) * 0.5); - double l = (lx + ly) / 1.3; - double l2 = l / 2; +void TChessFillStyle::drawRegion(const TColorFunction *cf, + const bool antiAliasing, + TRegionOutline &boundary) const { + // const bool isTransparent=m_pointColor.m<255; + + TStencilControl *stenc = TStencilControl::instance(); + TPixel32 backgroundColor = TSolidColorStyle::getMainColor(); + if (cf) backgroundColor = (*(cf))(backgroundColor); - bool isFirst = true; - for (double y = -l2; y < (l2 + m_VDist); y += m_VDist) { - double x = isFirst ? -l2 : -l2 + m_HDist; - isFirst = !isFirst; - for (; x < (l2 + m_HDist); x += 2 * m_HDist) { - grid.push_back(rotM * TPointD(x, y) + center); - nbClip++; - } - } + if (backgroundColor.m == 0) { // only to create stencil mask + TSolidColorStyle appStyle(TPixel32::White); + stenc->beginMask(); // does not draw on screen + appStyle.drawRegion(0, false, boundary); + } else { // create stencil mask and draw on screen + stenc->beginMask(TStencilControl::DRAW_ALSO_ON_SCREEN); + TSolidColorStyle::drawRegion(cf, antiAliasing, boundary); + } + stenc->endMask(); + + stenc->enableMask(TStencilControl::SHOW_INSIDE); + + TPixel32 color; + if (cf) + color = (*(cf))(m_pointColor); + else + color = m_pointColor; + + tglColor(color); + + TPointD vert[4]; + vert[0].x = -0.5; + vert[0].y = 0.5; + vert[1].x = -0.5; + vert[1].y = -0.5; + vert[2].x = 0.5; + vert[2].y = -0.5; + vert[3].x = 0.5; + vert[3].y = 0.5; + + TRotation rotM(m_Angle); + TScale scaleM(m_HDist, m_VDist); + for (int i = 0; i < 4; i++) vert[i] = rotM * scaleM * vert[i]; + + int chessId = glGenLists(1); + glNewList(chessId, GL_COMPILE); + glBegin(GL_QUADS); + glVertex2d(vert[0].x, vert[0].y); + glVertex2d(vert[1].x, vert[1].y); + glVertex2d(vert[2].x, vert[2].y); + glVertex2d(vert[3].x, vert[3].y); + glEnd(); + glEndList(); + + int nbClip = 1; + std::vector grid; + makeGrid(boundary.m_bbox, rotM, grid, nbClip); + + std::vector::const_iterator it = grid.begin(); + std::vector::const_iterator ite = grid.end(); + for (; it != ite; it++) { + glPushMatrix(); + glTranslated(it->x, it->y, 0.0); + glCallList(chessId); + glPopMatrix(); + } + + stenc->disableMask(); + glDeleteLists(chessId, 1); } //------------------------------------------------------------ -void TChessFillStyle::drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const -{ - // const bool isTransparent=m_pointColor.m<255; - - TStencilControl *stenc = TStencilControl::instance(); - TPixel32 backgroundColor = TSolidColorStyle::getMainColor(); - if (cf) - backgroundColor = (*(cf))(backgroundColor); - - if (backgroundColor.m == 0) { //only to create stencil mask - TSolidColorStyle appStyle(TPixel32::White); - stenc->beginMask(); //does not draw on screen - appStyle.drawRegion(0, false, boundary); - } else { //create stencil mask and draw on screen - stenc->beginMask(TStencilControl::DRAW_ALSO_ON_SCREEN); - TSolidColorStyle::drawRegion(cf, antiAliasing, boundary); - } - stenc->endMask(); - - stenc->enableMask(TStencilControl::SHOW_INSIDE); - - TPixel32 color; - if (cf) - color = (*(cf))(m_pointColor); - else - color = m_pointColor; - - tglColor(color); - - TPointD vert[4]; - vert[0].x = -0.5; - vert[0].y = 0.5; - vert[1].x = -0.5; - vert[1].y = -0.5; - vert[2].x = 0.5; - vert[2].y = -0.5; - vert[3].x = 0.5; - vert[3].y = 0.5; - - TRotation rotM(m_Angle); - TScale scaleM(m_HDist, m_VDist); - for (int i = 0; i < 4; i++) - vert[i] = rotM * scaleM * vert[i]; - - int chessId = glGenLists(1); - glNewList(chessId, GL_COMPILE); - glBegin(GL_QUADS); - glVertex2d(vert[0].x, vert[0].y); - glVertex2d(vert[1].x, vert[1].y); - glVertex2d(vert[2].x, vert[2].y); - glVertex2d(vert[3].x, vert[3].y); - glEnd(); - glEndList(); - - int nbClip = 1; - std::vector grid; - makeGrid(boundary.m_bbox, rotM, grid, nbClip); - - std::vector::const_iterator it = grid.begin(); - std::vector::const_iterator ite = grid.end(); - for (; it != ite; it++) { - glPushMatrix(); - glTranslated(it->x, it->y, 0.0); - glCallList(chessId); - glPopMatrix(); - } - - stenc->disableMask(); - glDeleteLists(chessId, 1); -} - -//------------------------------------------------------------ - -void TChessFillStyle::drawRegion(TFlash &flash, const TRegion *r) const -{ - TRectD bbox(r->getBBox()); - - TPointD vert[4]; - vert[0].x = -0.5; - vert[0].y = 0.5; - vert[1].x = -0.5; - vert[1].y = -0.5; - vert[2].x = 0.5; - vert[2].y = -0.5; - vert[3].x = 0.5; - vert[3].y = 0.5; - - TRotation rotM(m_Angle); - TScale scaleM(m_HDist, m_VDist); - for (int i = 0; i < 4; i++) - vert[i] = rotM * scaleM * vert[i]; - - int nbClip = 1; // just for the getMainColor() rectangle - std::vector grid; - makeGrid(bbox, rotM, grid, nbClip); - - // flash.drawRegion(*r,true); - flash.drawRegion(*r, nbClip); - - flash.setFillColor(getMainColor()); - flash.drawRectangle(bbox); - - flash.setFillColor(m_pointColor); - - std::vector::const_iterator it = grid.begin(); - std::vector::const_iterator ite = grid.end(); - for (; it != ite; it++) { - TTranslation trM(it->x, it->y); - std::vector lvert; - lvert.push_back(trM * vert[0]); - lvert.push_back(trM * vert[1]); - lvert.push_back(trM * vert[2]); - lvert.push_back(trM * vert[3]); - flash.drawPolyline(lvert); - } +void TChessFillStyle::drawRegion(TFlash &flash, const TRegion *r) const { + TRectD bbox(r->getBBox()); + + TPointD vert[4]; + vert[0].x = -0.5; + vert[0].y = 0.5; + vert[1].x = -0.5; + vert[1].y = -0.5; + vert[2].x = 0.5; + vert[2].y = -0.5; + vert[3].x = 0.5; + vert[3].y = 0.5; + + TRotation rotM(m_Angle); + TScale scaleM(m_HDist, m_VDist); + for (int i = 0; i < 4; i++) vert[i] = rotM * scaleM * vert[i]; + + int nbClip = 1; // just for the getMainColor() rectangle + std::vector grid; + makeGrid(bbox, rotM, grid, nbClip); + + // flash.drawRegion(*r,true); + flash.drawRegion(*r, nbClip); + + flash.setFillColor(getMainColor()); + flash.drawRectangle(bbox); + + flash.setFillColor(m_pointColor); + + std::vector::const_iterator it = grid.begin(); + std::vector::const_iterator ite = grid.end(); + for (; it != ite; it++) { + TTranslation trM(it->x, it->y); + std::vector lvert; + lvert.push_back(trM * vert[0]); + lvert.push_back(trM * vert[1]); + lvert.push_back(trM * vert[2]); + lvert.push_back(trM * vert[3]); + flash.drawPolyline(lvert); + } } //*************************************************************************** // TStripeFillStyle implementation //*************************************************************************** -TStripeFillStyle::TStripeFillStyle( - const TPixel32 &bgColor, const TPixel32 &pointColor, - const double Dist, const double Angle, const double Thickness) - : TSolidColorStyle(bgColor), m_pointColor(pointColor), m_Dist(Dist), m_Angle(Angle), m_Thickness(Thickness) -{ -} +TStripeFillStyle::TStripeFillStyle(const TPixel32 &bgColor, + const TPixel32 &pointColor, + const double Dist, const double Angle, + const double Thickness) + : TSolidColorStyle(bgColor) + , m_pointColor(pointColor) + , m_Dist(Dist) + , m_Angle(Angle) + , m_Thickness(Thickness) {} //------------------------------------------------------------ TStripeFillStyle::TStripeFillStyle(const TPixel32 &color) - : TSolidColorStyle(TPixel32::Transparent), m_pointColor(color), m_Dist(15.0), m_Angle(0.0), m_Thickness(6.0) -{ -} + : TSolidColorStyle(TPixel32::Transparent) + , m_pointColor(color) + , m_Dist(15.0) + , m_Angle(0.0) + , m_Thickness(6.0) {} //------------------------------------------------------------ -TColorStyle *TStripeFillStyle::clone() const -{ - return new TStripeFillStyle(*this); +TColorStyle *TStripeFillStyle::clone() const { + return new TStripeFillStyle(*this); } //------------------------------------------------------------ -int TStripeFillStyle::getParamCount() const -{ - return 3; -} +int TStripeFillStyle::getParamCount() const { return 3; } //----------------------------------------------------------------------------- -TColorStyle::ParamType TStripeFillStyle::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +TColorStyle::ParamType TStripeFillStyle::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -QString TStripeFillStyle::getParamNames(int index) const -{ - assert(0 <= index && index < 3); +QString TStripeFillStyle::getParamNames(int index) const { + assert(0 <= index && index < 3); + + QString value; + switch (index) { + case 0: + value = QCoreApplication::translate("TStripeFillStyle", "Distance"); + break; + case 1: + value = QCoreApplication::translate("TStripeFillStyle", "Angle"); + break; + case 2: + value = QCoreApplication::translate("TStripeFillStyle", "Thickness"); + break; + } - QString value; - switch (index) { - case 0: - value = QCoreApplication::translate("TStripeFillStyle", "Distance"); - break; - case 1: - value = QCoreApplication::translate("TStripeFillStyle", "Angle"); - break; - case 2: - value = QCoreApplication::translate("TStripeFillStyle", "Thickness"); - break; - } + return value; +} + +//----------------------------------------------------------------------------- - return value; +void TStripeFillStyle::getParamRange(int index, double &min, + double &max) const { + assert(0 <= index && index < 3); + switch (index) { + case 0: + min = 1.0; + max = 100.0; + break; + case 1: + min = -90.0; + max = 90.0; + break; + case 2: + min = 0.5; + max = 100.0; + break; + } } //----------------------------------------------------------------------------- -void TStripeFillStyle::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 3); - switch (index) { - case 0: - min = 1.0; - max = 100.0; - break; - case 1: - min = -90.0; - max = 90.0; - break; - case 2: - min = 0.5; - max = 100.0; - break; - } +double TStripeFillStyle::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 3); + + switch (index) { + case 0: + return m_Dist; + case 1: + return m_Angle; + case 2: + return m_Thickness; + } + return 0.0; } //----------------------------------------------------------------------------- -double TStripeFillStyle::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 3); +void TStripeFillStyle::setParamValue(int index, double value) { + assert(0 <= index && index < 3); + + switch (index) { + case 0: + m_Dist = value; + break; + case 1: + m_Angle = value; + break; + case 2: + m_Thickness = value; + break; + } +} + +//------------------------------------------------------------ - switch (index) { - case 0: - return m_Dist; - case 1: - return m_Angle; - case 2: - return m_Thickness; - } - return 0.0; +void TStripeFillStyle::loadData(TInputStreamInterface &is) { + TSolidColorStyle::loadData(is); + is >> m_Dist; + is >> m_Angle; + is >> m_Thickness; + is >> m_pointColor; } -//----------------------------------------------------------------------------- +//------------------------------------------------------------ -void TStripeFillStyle::setParamValue(int index, double value) -{ - assert(0 <= index && index < 3); +void TStripeFillStyle::saveData(TOutputStreamInterface &os) const { + TSolidColorStyle::saveData(os); + os << m_Dist; + os << m_Angle; + os << m_Thickness; + os << m_pointColor; +} - switch (index) { - case 0: - m_Dist = value; - break; - case 1: - m_Angle = value; - break; - case 2: - m_Thickness = value; - break; - } +void TStripeFillStyle::getThickline(const TPointD &lc, const double lx, + TPointD &p0, TPointD &p1, TPointD &p2, + TPointD &p3) const { + double l = m_Thickness / cos(degree2rad(m_Angle)); + l *= 0.5; + p0 = TPointD(lc.x, lc.y - l); + p1 = TPointD(lc.x, lc.y + l); + double y = lc.y + lx * tan(degree2rad(m_Angle)); + p2 = TPointD(lc.x + lx, y + l); + p3 = TPointD(lc.x + lx, y - l); } //------------------------------------------------------------ -void TStripeFillStyle::loadData(TInputStreamInterface &is) -{ - TSolidColorStyle::loadData(is); - is >> m_Dist; - is >> m_Angle; - is >> m_Thickness; - is >> m_pointColor; +TPixel32 TStripeFillStyle::getColorParamValue(int index) const { + return index == 0 ? m_pointColor : TSolidColorStyle::getMainColor(); +} + +//------------------------------------------------------------ +void TStripeFillStyle::setColorParamValue(int index, const TPixel32 &color) { + if (index == 0) + m_pointColor = color; + else { + TSolidColorStyle::setMainColor(color); + } +} + +//------------------------------------------------------------ + +inline void trim(TPointD &p0, TPointD &p1, double y0, double y1) { + if (p0.y < y0) { + // Trim the first extreme of the segment at y0 + double t = (y0 - p0.y) / (p1.y - p0.y); + p0.x = p0.x + t * (p1.x - p0.x); + p0.y = y0; + } else if (p0.y > y1) { + // The same, at y1 + double t = (y1 - p0.y) / (p1.y - p0.y); + p0.x = p0.x + t * (p1.x - p0.x); + p0.y = y1; + } + + // Same for p1 + if (p1.y < y0) { + double t = (y0 - p1.y) / (p0.y - p1.y); + p1.x = p1.x + t * (p0.x - p1.x); + p1.y = y0; + } else if (p1.y > y1) { + double t = (y1 - p1.y) / (p0.y - p1.y); + p1.x = p1.x + t * (p0.x - p1.x); + p1.y = y1; + } } -//------------------------------------------------------------ +//------------------------------------------------------------ + +void TStripeFillStyle::drawRegion(const TColorFunction *cf, + const bool antiAliasing, + TRegionOutline &boundary) const { + const bool isTransparent = m_pointColor.m < 255; + + TStencilControl *stenc = TStencilControl::instance(); + + TPixel32 backgroundColor = TSolidColorStyle::getMainColor(); + if (cf) backgroundColor = (*(cf))(backgroundColor); + + if (backgroundColor.m == 0) { // only to create stencil mask + TSolidColorStyle appStyle(TPixel32::White); + stenc->beginMask(); + appStyle.drawRegion(0, false, boundary); + } else { + stenc->beginMask(TStencilControl::DRAW_ALSO_ON_SCREEN); + TSolidColorStyle::drawRegion(cf, antiAliasing, boundary); + } + stenc->endMask(); + + stenc->enableMask(TStencilControl::SHOW_INSIDE); + + if (isTransparent) { + // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + // glEnable(GL_BLEND); + //// <-- tglEnableBlending(); + } + + TPixel32 color; + if (cf) + color = (*(cf))(m_pointColor); + else + color = m_pointColor; + + tglColor(color); + + // Horizontal Lines + if (fabs(m_Angle) != 90) { + double lx = boundary.m_bbox.x1 - boundary.m_bbox.x0; + // double ly=boundary.m_bbox.y1-boundary.m_bbox.y0; + double beg = boundary.m_bbox.y0; + double end = boundary.m_bbox.y1; + beg = m_Angle <= 0 ? beg : beg - lx * tan(degree2rad(m_Angle)); + end = m_Angle >= 0 ? end : end - lx * tan(degree2rad(m_Angle)); + double dist = m_Dist / cos(degree2rad(m_Angle)); + + double y; + + TStencilControl *stenc2 = TStencilControl::instance(); + stenc2->beginMask(TStencilControl::DRAW_ALSO_ON_SCREEN); + + glBegin(GL_QUADS); + for (y = beg; y <= end; y += dist) { + TPointD p0, p1, p2, p3; + getThickline(TPointD(boundary.m_bbox.x0, y), lx, p0, p1, p2, p3); + tglVertex(p0); + tglVertex(p1); + tglVertex(p2); + tglVertex(p3); + } + glEnd(); + stenc2->endMask(); + + stenc2->enableMask(TStencilControl::SHOW_OUTSIDE); + + if (m_Angle != 0) // ANTIALIASING + { + // glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + // glEnable(GL_BLEND); + // glEnable(GL_LINE_SMOOTH); + + tglEnableLineSmooth(); + + // NOTE: Trimming the fat lines is necessary outside the (-60, 60) angles + // interval + // seemingly due to a bug in MAC-Leopard's openGL implementation... + + glBegin(GL_LINES); + for (y = beg; y <= end; y += dist) { + TPointD p0, p1, p2, p3; + getThickline(TPointD(boundary.m_bbox.x0, y), lx, p0, p1, p2, p3); + trim(p1, p2, boundary.m_bbox.y0, boundary.m_bbox.y1); + tglVertex(p1); + tglVertex(p2); + + trim(p0, p3, boundary.m_bbox.y0, boundary.m_bbox.y1); + tglVertex(p0); + tglVertex(p3); + } + glEnd(); + } + stenc2->disableMask(); -void TStripeFillStyle::saveData(TOutputStreamInterface &os) const -{ - TSolidColorStyle::saveData(os); - os << m_Dist; - os << m_Angle; - os << m_Thickness; - os << m_pointColor; -} + } else { + double beg = boundary.m_bbox.x0; + double end = boundary.m_bbox.x1; + double y0 = boundary.m_bbox.y0; + double y1 = boundary.m_bbox.y1; + + glBegin(GL_QUADS); + for (double x = beg; x <= end; x += m_Dist) { + TPointD p0(x, y0); + TPointD p1(x + m_Thickness, y0); + TPointD p2(x, y1); + TPointD p3(x + m_Thickness, y1); + tglVertex(p0); + tglVertex(p1); + tglVertex(p3); + tglVertex(p2); + } + glEnd(); + } -void TStripeFillStyle::getThickline(const TPointD &lc, const double lx, - TPointD &p0, TPointD &p1, - TPointD &p2, TPointD &p3) const -{ - double l = m_Thickness / cos(degree2rad(m_Angle)); - l *= 0.5; - p0 = TPointD(lc.x, lc.y - l); - p1 = TPointD(lc.x, lc.y + l); - double y = lc.y + lx * tan(degree2rad(m_Angle)); - p2 = TPointD(lc.x + lx, y + l); - p3 = TPointD(lc.x + lx, y - l); + // tglColor(TPixel32::White); + + stenc->disableMask(); } //------------------------------------------------------------ -TPixel32 TStripeFillStyle::getColorParamValue(int index) const -{ - return index == 0 ? m_pointColor : TSolidColorStyle::getMainColor(); -} +int TStripeFillStyle::nbClip(const TRectD &bbox) const { + int nbClip = 1; // the bbox rectangle -//------------------------------------------------------------ -void TStripeFillStyle::setColorParamValue(int index, const TPixel32 &color) -{ - if (index == 0) - m_pointColor = color; - else { - TSolidColorStyle::setMainColor(color); - } + if (fabs(m_Angle) != 90) { + double lx = bbox.x1 - bbox.x0; + // double ly=bbox.y1-bbox.y0; + double beg = bbox.y0; + double end = bbox.y1; + beg = m_Angle <= 0 ? beg : beg - lx * tan(degree2rad(m_Angle)); + end = m_Angle >= 0 ? end : end - lx * tan(degree2rad(m_Angle)); + double dist = m_Dist / cos(degree2rad(m_Angle)); + for (double y = beg; y <= end; y += dist) nbClip++; + } else { + double beg = bbox.x0; + double end = bbox.x1; + // double y0=bbox.y0; + // double y1=bbox.y1; + for (double x = beg; x <= end; x += m_Dist) nbClip++; + } + + return nbClip; } //------------------------------------------------------------ -inline void trim(TPointD &p0, TPointD &p1, double y0, double y1) -{ - if (p0.y < y0) { - //Trim the first extreme of the segment at y0 - double t = (y0 - p0.y) / (p1.y - p0.y); - p0.x = p0.x + t * (p1.x - p0.x); - p0.y = y0; - } else if (p0.y > y1) { - //The same, at y1 - double t = (y1 - p0.y) / (p1.y - p0.y); - p0.x = p0.x + t * (p1.x - p0.x); - p0.y = y1; - } - - //Same for p1 - if (p1.y < y0) { - double t = (y0 - p1.y) / (p0.y - p1.y); - p1.x = p1.x + t * (p0.x - p1.x); - p1.y = y0; - } else if (p1.y > y1) { - double t = (y1 - p1.y) / (p0.y - p1.y); - p1.x = p1.x + t * (p0.x - p1.x); - p1.y = y1; - } -} - -//------------------------------------------------------------ - -void TStripeFillStyle::drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const -{ - const bool isTransparent = m_pointColor.m < 255; - - TStencilControl *stenc = TStencilControl::instance(); - - TPixel32 backgroundColor = TSolidColorStyle::getMainColor(); - if (cf) - backgroundColor = (*(cf))(backgroundColor); - - if (backgroundColor.m == 0) { //only to create stencil mask - TSolidColorStyle appStyle(TPixel32::White); - stenc->beginMask(); - appStyle.drawRegion(0, false, boundary); - } else { - stenc->beginMask(TStencilControl::DRAW_ALSO_ON_SCREEN); - TSolidColorStyle::drawRegion(cf, antiAliasing, boundary); - } - stenc->endMask(); - - stenc->enableMask(TStencilControl::SHOW_INSIDE); - - if (isTransparent) { - //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - //glEnable(GL_BLEND); - //// <-- tglEnableBlending(); - } - - TPixel32 color; - if (cf) - color = (*(cf))(m_pointColor); - else - color = m_pointColor; - - tglColor(color); - - // Horizontal Lines - if (fabs(m_Angle) != 90) { - double lx = boundary.m_bbox.x1 - boundary.m_bbox.x0; - //double ly=boundary.m_bbox.y1-boundary.m_bbox.y0; - double beg = boundary.m_bbox.y0; - double end = boundary.m_bbox.y1; - beg = m_Angle <= 0 ? beg : beg - lx * tan(degree2rad(m_Angle)); - end = m_Angle >= 0 ? end : end - lx * tan(degree2rad(m_Angle)); - double dist = m_Dist / cos(degree2rad(m_Angle)); - - double y; - - TStencilControl *stenc2 = TStencilControl::instance(); - stenc2->beginMask(TStencilControl::DRAW_ALSO_ON_SCREEN); - - glBegin(GL_QUADS); - for (y = beg; y <= end; y += dist) { - TPointD p0, p1, p2, p3; - getThickline(TPointD(boundary.m_bbox.x0, y), lx, p0, p1, p2, p3); - tglVertex(p0); - tglVertex(p1); - tglVertex(p2); - tglVertex(p3); - } - glEnd(); - stenc2->endMask(); - - stenc2->enableMask(TStencilControl::SHOW_OUTSIDE); - - if (m_Angle != 0) //ANTIALIASING - { - //glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); - //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - //glEnable(GL_BLEND); - //glEnable(GL_LINE_SMOOTH); - - tglEnableLineSmooth(); - - //NOTE: Trimming the fat lines is necessary outside the (-60, 60) angles interval - //seemingly due to a bug in MAC-Leopard's openGL implementation... - - glBegin(GL_LINES); - for (y = beg; y <= end; y += dist) { - TPointD p0, p1, p2, p3; - getThickline(TPointD(boundary.m_bbox.x0, y), lx, p0, p1, p2, p3); - trim(p1, p2, boundary.m_bbox.y0, boundary.m_bbox.y1); - tglVertex(p1); - tglVertex(p2); - - trim(p0, p3, boundary.m_bbox.y0, boundary.m_bbox.y1); - tglVertex(p0); - tglVertex(p3); - } - glEnd(); - } - stenc2->disableMask(); - - } else { - double beg = boundary.m_bbox.x0; - double end = boundary.m_bbox.x1; - double y0 = boundary.m_bbox.y0; - double y1 = boundary.m_bbox.y1; - - glBegin(GL_QUADS); - for (double x = beg; x <= end; x += m_Dist) { - TPointD p0(x, y0); - TPointD p1(x + m_Thickness, y0); - TPointD p2(x, y1); - TPointD p3(x + m_Thickness, y1); - tglVertex(p0); - tglVertex(p1); - tglVertex(p3); - tglVertex(p2); - } - glEnd(); - } - - //tglColor(TPixel32::White); - - stenc->disableMask(); -} - -//------------------------------------------------------------ - -int TStripeFillStyle::nbClip(const TRectD &bbox) const -{ - int nbClip = 1; // the bbox rectangle +void TStripeFillStyle::drawRegion(TFlash &flash, const TRegion *r) const { + TRectD bbox(r->getBBox()); - if (fabs(m_Angle) != 90) { - double lx = bbox.x1 - bbox.x0; - //double ly=bbox.y1-bbox.y0; - double beg = bbox.y0; - double end = bbox.y1; - beg = m_Angle <= 0 ? beg : beg - lx * tan(degree2rad(m_Angle)); - end = m_Angle >= 0 ? end : end - lx * tan(degree2rad(m_Angle)); - double dist = m_Dist / cos(degree2rad(m_Angle)); - for (double y = beg; y <= end; y += dist) - nbClip++; - } else { - double beg = bbox.x0; - double end = bbox.x1; - //double y0=bbox.y0; - //double y1=bbox.y1; - for (double x = beg; x <= end; x += m_Dist) - nbClip++; - } + // flash.drawRegion(*r,true); + flash.drawRegion(*r, nbClip(bbox)); // -1 i don't know why - return nbClip; + flash.setFillColor(getMainColor()); + flash.drawRectangle(bbox); + + flash.setFillColor(m_pointColor); + // Horizontal Lines + if (fabs(m_Angle) != 90) { + double lx = bbox.x1 - bbox.x0; + // double ly=bbox.y1-bbox.y0; + double beg = bbox.y0; + double end = bbox.y1; + beg = m_Angle <= 0 ? beg : beg - lx * tan(degree2rad(m_Angle)); + end = m_Angle >= 0 ? end : end - lx * tan(degree2rad(m_Angle)); + double dist = m_Dist / cos(degree2rad(m_Angle)); + for (double y = beg; y <= end; y += dist) { + TPointD p0, p1, p2, p3; + getThickline(TPointD(bbox.x0, y), lx, p0, p1, p2, p3); + std::vector v; + v.push_back(p0); + v.push_back(p1); + v.push_back(p2); + v.push_back(p3); + flash.drawPolyline(v); + } + } else { + double beg = bbox.x0; + double end = bbox.x1; + double y0 = bbox.y0; + double y1 = bbox.y1; + for (double x = beg; x <= end; x += m_Dist) { + TPointD p0(x, y0); + TPointD p1(x + m_Thickness, y0); + TPointD p2(x, y1); + TPointD p3(x + m_Thickness, y1); + std::vector v; + v.push_back(p0); + v.push_back(p1); + v.push_back(p3); + v.push_back(p2); + flash.drawPolyline(v); + } + } } //------------------------------------------------------------ -void TStripeFillStyle::drawRegion(TFlash &flash, const TRegion *r) const -{ - TRectD bbox(r->getBBox()); - - // flash.drawRegion(*r,true); - flash.drawRegion(*r, nbClip(bbox)); // -1 i don't know why - - flash.setFillColor(getMainColor()); - flash.drawRectangle(bbox); - - flash.setFillColor(m_pointColor); - // Horizontal Lines - if (fabs(m_Angle) != 90) { - double lx = bbox.x1 - bbox.x0; - //double ly=bbox.y1-bbox.y0; - double beg = bbox.y0; - double end = bbox.y1; - beg = m_Angle <= 0 ? beg : beg - lx * tan(degree2rad(m_Angle)); - end = m_Angle >= 0 ? end : end - lx * tan(degree2rad(m_Angle)); - double dist = m_Dist / cos(degree2rad(m_Angle)); - for (double y = beg; y <= end; y += dist) { - TPointD p0, p1, p2, p3; - getThickline(TPointD(bbox.x0, y), lx, p0, p1, p2, p3); - std::vector v; - v.push_back(p0); - v.push_back(p1); - v.push_back(p2); - v.push_back(p3); - flash.drawPolyline(v); - } - } else { - double beg = bbox.x0; - double end = bbox.x1; - double y0 = bbox.y0; - double y1 = bbox.y1; - for (double x = beg; x <= end; x += m_Dist) { - TPointD p0(x, y0); - TPointD p1(x + m_Thickness, y0); - TPointD p2(x, y1); - TPointD p3(x + m_Thickness, y1); - std::vector v; - v.push_back(p0); - v.push_back(p1); - v.push_back(p3); - v.push_back(p2); - flash.drawPolyline(v); - } - } -} - -//------------------------------------------------------------ - -void TStripeFillStyle::makeIcon(const TDimension &d) -{ - // Saves the values of member variables and sets the right icon values - double LDist = m_Dist; - double LAngle = m_Angle; - double LThickness = m_Thickness; +void TStripeFillStyle::makeIcon(const TDimension &d) { + // Saves the values of member variables and sets the right icon values + double LDist = m_Dist; + double LAngle = m_Angle; + double LThickness = m_Thickness; - m_Dist *= 1.33; - m_Thickness *= 1.66; + m_Dist *= 1.33; + m_Thickness *= 1.66; - TColorStyle::makeIcon(d); + TColorStyle::makeIcon(d); - m_Dist = LDist; - m_Angle = LAngle; - m_Thickness = LThickness; + m_Dist = LDist; + m_Angle = LAngle; + m_Thickness = LThickness; } //*************************************************************************** // TLinGradFillStyle implementation //*************************************************************************** -TLinGradFillStyle::TLinGradFillStyle( - const TPixel32 &bgColor, const TPixel32 &pointColor, - const double Angle, const double XPos, const double YPos, - const double Size) - : TSolidColorStyle(bgColor), m_pointColor(pointColor), m_Angle(Angle), m_XPos(XPos), m_YPos(YPos), m_Size(Size) -{ -} +TLinGradFillStyle::TLinGradFillStyle(const TPixel32 &bgColor, + const TPixel32 &pointColor, + const double Angle, const double XPos, + const double YPos, const double Size) + : TSolidColorStyle(bgColor) + , m_pointColor(pointColor) + , m_Angle(Angle) + , m_XPos(XPos) + , m_YPos(YPos) + , m_Size(Size) {} //----------------------------------------------------------------------------- TLinGradFillStyle::TLinGradFillStyle(const TPixel32 &color) - : TSolidColorStyle(TPixel32::White), m_pointColor(color), m_Angle(0.0), m_XPos(0.0), m_YPos(0.0), m_Size(100.0) -{ -} + : TSolidColorStyle(TPixel32::White) + , m_pointColor(color) + , m_Angle(0.0) + , m_XPos(0.0) + , m_YPos(0.0) + , m_Size(100.0) {} //----------------------------------------------------------------------------- -TColorStyle *TLinGradFillStyle::clone() const -{ - return new TLinGradFillStyle(*this); +TColorStyle *TLinGradFillStyle::clone() const { + return new TLinGradFillStyle(*this); } //------------------------------------------------------------ -int TLinGradFillStyle::getParamCount() const -{ - return 4; -} +int TLinGradFillStyle::getParamCount() const { return 4; } //----------------------------------------------------------------------------- -TColorStyle::ParamType TLinGradFillStyle::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +TColorStyle::ParamType TLinGradFillStyle::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -QString TLinGradFillStyle::getParamNames(int index) const -{ - assert(0 <= index && index < 4); - - QString value; - switch (index) { - case 0: - value = QCoreApplication::translate("TLinGradFillStyle", "Angle"); - break; - case 1: - value = QCoreApplication::translate("TLinGradFillStyle", "X Position"); - break; - case 2: - value = QCoreApplication::translate("TLinGradFillStyle", "Y Position"); - break; - case 3: - value = QCoreApplication::translate("TLinGradFillStyle", "Smoothness"); - break; - } - - return value; +QString TLinGradFillStyle::getParamNames(int index) const { + assert(0 <= index && index < 4); + + QString value; + switch (index) { + case 0: + value = QCoreApplication::translate("TLinGradFillStyle", "Angle"); + break; + case 1: + value = QCoreApplication::translate("TLinGradFillStyle", "X Position"); + break; + case 2: + value = QCoreApplication::translate("TLinGradFillStyle", "Y Position"); + break; + case 3: + value = QCoreApplication::translate("TLinGradFillStyle", "Smoothness"); + break; + } + + return value; } //----------------------------------------------------------------------------- -void TLinGradFillStyle::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 4); - switch (index) { - case 0: - min = -180.0; - max = 180.0; - break; - case 1: - min = -100.0; - max = 100.0; - break; - case 2: - min = -100.0; - max = 100.0; - break; - case 3: - min = 1.0; - max = 500.0; - break; - } +void TLinGradFillStyle::getParamRange(int index, double &min, + double &max) const { + assert(0 <= index && index < 4); + switch (index) { + case 0: + min = -180.0; + max = 180.0; + break; + case 1: + min = -100.0; + max = 100.0; + break; + case 2: + min = -100.0; + max = 100.0; + break; + case 3: + min = 1.0; + max = 500.0; + break; + } } //----------------------------------------------------------------------------- -double TLinGradFillStyle::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 4); - - switch (index) { - case 0: - return m_Angle; - case 1: - return m_XPos; - case 2: - return m_YPos; - case 3: - return m_Size; - } - return 0.0; +double TLinGradFillStyle::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 4); + + switch (index) { + case 0: + return m_Angle; + case 1: + return m_XPos; + case 2: + return m_YPos; + case 3: + return m_Size; + } + return 0.0; } //----------------------------------------------------------------------------- -void TLinGradFillStyle::setParamValue(int index, double value) -{ - assert(0 <= index && index < 4); - - switch (index) { - case 0: - m_Angle = value; - break; - case 1: - m_XPos = value; - break; - case 2: - m_YPos = value; - break; - case 3: - m_Size = value; - break; - } +void TLinGradFillStyle::setParamValue(int index, double value) { + assert(0 <= index && index < 4); + + switch (index) { + case 0: + m_Angle = value; + break; + case 1: + m_XPos = value; + break; + case 2: + m_YPos = value; + break; + case 3: + m_Size = value; + break; + } } //------------------------------------------------------------ -void TLinGradFillStyle::loadData(TInputStreamInterface &is) -{ - TSolidColorStyle::loadData(is); - is >> m_Angle; - is >> m_XPos; - is >> m_YPos; - is >> m_Size; - is >> m_pointColor; +void TLinGradFillStyle::loadData(TInputStreamInterface &is) { + TSolidColorStyle::loadData(is); + is >> m_Angle; + is >> m_XPos; + is >> m_YPos; + is >> m_Size; + is >> m_pointColor; } //------------------------------------------------------------ -void TLinGradFillStyle::saveData(TOutputStreamInterface &os) const -{ - TSolidColorStyle::saveData(os); - os << m_Angle; - os << m_XPos; - os << m_YPos; - os << m_Size; - os << m_pointColor; +void TLinGradFillStyle::saveData(TOutputStreamInterface &os) const { + TSolidColorStyle::saveData(os); + os << m_Angle; + os << m_XPos; + os << m_YPos; + os << m_Size; + os << m_pointColor; } //------------------------------------------------------------ -TPixel32 TLinGradFillStyle::getColorParamValue(int index) const -{ - return index == 0 ? m_pointColor : TSolidColorStyle::getMainColor(); +TPixel32 TLinGradFillStyle::getColorParamValue(int index) const { + return index == 0 ? m_pointColor : TSolidColorStyle::getMainColor(); } //------------------------------------------------------------ -void TLinGradFillStyle::setColorParamValue(int index, const TPixel32 &color) -{ - if (index == 0) - m_pointColor = color; - else { - TSolidColorStyle::setMainColor(color); - } +void TLinGradFillStyle::setColorParamValue(int index, const TPixel32 &color) { + if (index == 0) + m_pointColor = color; + else { + TSolidColorStyle::setMainColor(color); + } } //------------------------------------------------------------ -void TLinGradFillStyle::getRects(const TRectD &bbox, - std::vector &r0, - std::vector &r1, - std::vector &r2) const -{ - r0.clear(); - r1.clear(); - r2.clear(); +void TLinGradFillStyle::getRects(const TRectD &bbox, std::vector &r0, + std::vector &r1, + std::vector &r2) const { + r0.clear(); + r1.clear(); + r2.clear(); - TPointD p0, p1, p2, p3; - double lx = bbox.x1 - bbox.x0; - double ly = bbox.y1 - bbox.y0; - TPointD center((bbox.x1 + bbox.x0) / 2.0, (bbox.y1 + bbox.y0) / 2.0); - center = center + TPointD(m_XPos * 0.01 * lx * 0.5, m_YPos * 0.01 * ly * 0.5); - double l = tdistance(TPointD(bbox.x0, bbox.y0), TPointD(bbox.x1, bbox.y1)); + TPointD p0, p1, p2, p3; + double lx = bbox.x1 - bbox.x0; + double ly = bbox.y1 - bbox.y0; + TPointD center((bbox.x1 + bbox.x0) / 2.0, (bbox.y1 + bbox.y0) / 2.0); + center = center + TPointD(m_XPos * 0.01 * lx * 0.5, m_YPos * 0.01 * ly * 0.5); + double l = tdistance(TPointD(bbox.x0, bbox.y0), TPointD(bbox.x1, bbox.y1)); - r0.push_back(TPointD(-m_Size - l, l)); - r0.push_back(TPointD(-m_Size - l, -l)); - r0.push_back(TPointD(-m_Size, -l)); - r0.push_back(TPointD(-m_Size, l)); + r0.push_back(TPointD(-m_Size - l, l)); + r0.push_back(TPointD(-m_Size - l, -l)); + r0.push_back(TPointD(-m_Size, -l)); + r0.push_back(TPointD(-m_Size, l)); - r1.push_back(TPointD(-m_Size, l)); - r1.push_back(TPointD(-m_Size, -l)); - r1.push_back(TPointD(m_Size, -l)); - r1.push_back(TPointD(m_Size, l)); + r1.push_back(TPointD(-m_Size, l)); + r1.push_back(TPointD(-m_Size, -l)); + r1.push_back(TPointD(m_Size, -l)); + r1.push_back(TPointD(m_Size, l)); - r2.push_back(TPointD(m_Size, l)); - r2.push_back(TPointD(m_Size, -l)); - r2.push_back(TPointD(m_Size + l, -l)); - r2.push_back(TPointD(m_Size + l, l)); + r2.push_back(TPointD(m_Size, l)); + r2.push_back(TPointD(m_Size, -l)); + r2.push_back(TPointD(m_Size + l, -l)); + r2.push_back(TPointD(m_Size + l, l)); - TRotation rotM(m_Angle); - TTranslation traM(center); - TAffine M(traM * rotM); + TRotation rotM(m_Angle); + TTranslation traM(center); + TAffine M(traM * rotM); - for (int i = 0; i < 4; i++) { - r0[i] = M * r0[i]; - r1[i] = M * r1[i]; - r2[i] = M * r2[i]; - } + for (int i = 0; i < 4; i++) { + r0[i] = M * r0[i]; + r1[i] = M * r1[i]; + r2[i] = M * r2[i]; + } } //------------------------------------------------------------ -void TLinGradFillStyle::drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const -{ - //only to create stencil mask - TStencilControl *stenc = TStencilControl::instance(); - TSolidColorStyle appStyle(TPixel32::White); - stenc->beginMask(); //does not draw on screen - appStyle.drawRegion(0, false, boundary); - stenc->endMask(); +void TLinGradFillStyle::drawRegion(const TColorFunction *cf, + const bool antiAliasing, + TRegionOutline &boundary) const { + // only to create stencil mask + TStencilControl *stenc = TStencilControl::instance(); + TSolidColorStyle appStyle(TPixel32::White); + stenc->beginMask(); // does not draw on screen + appStyle.drawRegion(0, false, boundary); + stenc->endMask(); - //compute colors - TPixel32 color1, color2; - if (cf) { - color1 = (*(cf))(TSolidColorStyle::getMainColor()); - color2 = (*(cf))(m_pointColor); - } else { - color1 = TSolidColorStyle::getMainColor(); - color2 = m_pointColor; - } + // compute colors + TPixel32 color1, color2; + if (cf) { + color1 = (*(cf))(TSolidColorStyle::getMainColor()); + color2 = (*(cf))(m_pointColor); + } else { + color1 = TSolidColorStyle::getMainColor(); + color2 = m_pointColor; + } - //compute points - TRectD bbox(boundary.m_bbox); - std::vector r0, r1, r2; - getRects(bbox, r0, r1, r2); - assert(r0.size() == 4); - assert(r1.size() == 4); - assert(r2.size() == 4); + // compute points + TRectD bbox(boundary.m_bbox); + std::vector r0, r1, r2; + getRects(bbox, r0, r1, r2); + assert(r0.size() == 4); + assert(r1.size() == 4); + assert(r2.size() == 4); - //draw + // draw - stenc->enableMask(TStencilControl::SHOW_INSIDE); + stenc->enableMask(TStencilControl::SHOW_INSIDE); - glBegin(GL_QUADS); + glBegin(GL_QUADS); - tglColor(color2); - int i = 0; - for (; i < 4; tglVertex(r0[i++])) - ; - tglVertex(r1[0]); - tglVertex(r1[1]); + tglColor(color2); + int i = 0; + for (; i < 4; tglVertex(r0[i++])) + ; + tglVertex(r1[0]); + tglVertex(r1[1]); - tglColor(color1); - tglVertex(r1[2]); - tglVertex(r1[3]); - for (i = 0; i < 4; tglVertex(r2[i++])) - ; + tglColor(color1); + tglVertex(r1[2]); + tglVertex(r1[3]); + for (i = 0; i < 4; tglVertex(r2[i++])) + ; - glEnd(); + glEnd(); - stenc->disableMask(); + stenc->disableMask(); } //------------------------------------------------------------ @@ -3761,33 +3597,33 @@ void TLinGradFillStyle::drawRegion(const TColorFunction *cf, const bool antiAlia // It is the new version, which uses XPos, YPos, Smooth parameters. // There is a gap between the flat and graded regions. This is the reason, // why the old version (without XPos, YPos, Smooth parameters) is used. -void TLinGradFillStyle::drawRegion(TFlash &flash, const TRegion *r) const -{ - TRectD bbox(r->getBBox()); - std::vector rect; +void TLinGradFillStyle::drawRegion(TFlash &flash, const TRegion *r) const { + TRectD bbox(r->getBBox()); + std::vector rect; - TPointD center((bbox.x1 + bbox.x0) / 2.0, (bbox.y1 + bbox.y0) / 2.0); - center = center + TPointD(m_XPos * 0.01 * (bbox.x1 - bbox.x0) * 0.5, m_YPos * 0.01 * (bbox.y1 - bbox.y0) * 0.5); - double l = tdistance(TPointD(bbox.x0, bbox.y0), TPointD(bbox.x1, bbox.y1)); + TPointD center((bbox.x1 + bbox.x0) / 2.0, (bbox.y1 + bbox.y0) / 2.0); + center = center + TPointD(m_XPos * 0.01 * (bbox.x1 - bbox.x0) * 0.5, + m_YPos * 0.01 * (bbox.y1 - bbox.y0) * 0.5); + double l = tdistance(TPointD(bbox.x0, bbox.y0), TPointD(bbox.x1, bbox.y1)); - TAffine M(TTranslation(center) * TRotation(m_Angle)); + TAffine M(TTranslation(center) * TRotation(m_Angle)); - rect.push_back(M * TPointD(-m_Size, l)); - rect.push_back(M * TPointD(-m_Size, -l)); - rect.push_back(M * TPointD(m_Size, -l)); - rect.push_back(M * TPointD(m_Size, l)); + rect.push_back(M * TPointD(-m_Size, l)); + rect.push_back(M * TPointD(-m_Size, -l)); + rect.push_back(M * TPointD(m_Size, -l)); + rect.push_back(M * TPointD(m_Size, l)); - flash.setThickness(0.0); + flash.setThickness(0.0); - SFlashUtils sfu; - sfu.drawGradedRegion(flash, rect, m_pointColor, getMainColor(), *r); + SFlashUtils sfu; + sfu.drawGradedRegion(flash, rect, m_pointColor, getMainColor(), *r); } /* // --- Old version --- void TLinGradFillStyle::drawRegion(TFlash& flash, const TRegion* r) const { - flash.drawRegion(*r,1); + flash.drawRegion(*r,1); TRectD bbox(r->getBBox()); TPointD p0,p1,p2,p3; p0=TPointD(bbox.x0,bbox.y0); @@ -3796,43 +3632,43 @@ void TLinGradFillStyle::drawRegion(TFlash& flash, const TRegion* r) const p3=TPointD(bbox.x1,bbox.y1); std::vector pv; if ( fabs(m_Angle)!=90 ) { - double tga=tan(degree2rad(fabs(m_Angle))); - double lx=bbox.x1-bbox.x0; - double ly=bbox.y1-bbox.y0; - double ax=lx/(tga*tga+1); - double bx=lx-ax; - double mx=ax*tga; - double rlylx=ly/lx; - double ay=ax*rlylx; - double by=bx*rlylx; - double my=mx*rlylx; - if ( m_Angle<=0.0) { - p0=p0+TPointD(-my,by); - p1=p1+TPointD(bx,mx); - p2=p2+TPointD(-bx,-mx); - p3=p3+TPointD(my,-by); - } else { - p0=p0+TPointD(bx,-mx); - p1=p1+TPointD(-my,-by); - p2=p2+TPointD(my,by); - p3=p3+TPointD(-bx,mx); - } - pv.push_back(p0); - pv.push_back(p1); - pv.push_back(p3); - pv.push_back(p2); + double tga=tan(degree2rad(fabs(m_Angle))); + double lx=bbox.x1-bbox.x0; + double ly=bbox.y1-bbox.y0; + double ax=lx/(tga*tga+1); + double bx=lx-ax; + double mx=ax*tga; + double rlylx=ly/lx; + double ay=ax*rlylx; + double by=bx*rlylx; + double my=mx*rlylx; + if ( m_Angle<=0.0) { + p0=p0+TPointD(-my,by); + p1=p1+TPointD(bx,mx); + p2=p2+TPointD(-bx,-mx); + p3=p3+TPointD(my,-by); + } else { + p0=p0+TPointD(bx,-mx); + p1=p1+TPointD(-my,-by); + p2=p2+TPointD(my,by); + p3=p3+TPointD(-bx,mx); + } + pv.push_back(p0); + pv.push_back(p1); + pv.push_back(p3); + pv.push_back(p2); } else { - if ( m_Angle==-90 ) { - pv.push_back(p1); - pv.push_back(p3); - pv.push_back(p2); - pv.push_back(p0); - } else { - pv.push_back(p0); - pv.push_back(p2); - pv.push_back(p3); - pv.push_back(p1); - } + if ( m_Angle==-90 ) { + pv.push_back(p1); + pv.push_back(p3); + pv.push_back(p2); + pv.push_back(p0); + } else { + pv.push_back(p0); + pv.push_back(p2); + pv.push_back(p3); + pv.push_back(p1); + } } SFlashUtils sfu; sfu.drawGradedPolyline(flash,pv,m_pointColor,getMainColor()); @@ -3843,264 +3679,258 @@ void TLinGradFillStyle::drawRegion(TFlash& flash, const TRegion* r) const // TRadGradFillStyle implementation //*************************************************************************** -TRadGradFillStyle::TRadGradFillStyle( - const TPixel32 &bgColor, const TPixel32 &pointColor, - const double XPos, const double YPos, - const double Radius, const double Smooth) - : TSolidColorStyle(bgColor), m_pointColor(pointColor), m_XPos(XPos), m_YPos(YPos), m_Radius(Radius), m_Smooth(Smooth) -{ -} +TRadGradFillStyle::TRadGradFillStyle(const TPixel32 &bgColor, + const TPixel32 &pointColor, + const double XPos, const double YPos, + const double Radius, const double Smooth) + : TSolidColorStyle(bgColor) + , m_pointColor(pointColor) + , m_XPos(XPos) + , m_YPos(YPos) + , m_Radius(Radius) + , m_Smooth(Smooth) {} //----------------------------------------------------------------------------- TRadGradFillStyle::TRadGradFillStyle(const TPixel32 &color) - : TSolidColorStyle(TPixel32::White), m_pointColor(color), m_XPos(0.0), m_YPos(0.0), m_Radius(50.0), m_Smooth(50) -{ -} + : TSolidColorStyle(TPixel32::White) + , m_pointColor(color) + , m_XPos(0.0) + , m_YPos(0.0) + , m_Radius(50.0) + , m_Smooth(50) {} //----------------------------------------------------------------------------- -TColorStyle *TRadGradFillStyle::clone() const -{ - return new TRadGradFillStyle(*this); +TColorStyle *TRadGradFillStyle::clone() const { + return new TRadGradFillStyle(*this); } //------------------------------------------------------------ -int TRadGradFillStyle::getParamCount() const -{ - return 4; -} +int TRadGradFillStyle::getParamCount() const { return 4; } //----------------------------------------------------------------------------- -TColorStyle::ParamType TRadGradFillStyle::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +TColorStyle::ParamType TRadGradFillStyle::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -QString TRadGradFillStyle::getParamNames(int index) const -{ - assert(0 <= index && index < 4); - - QString value; - switch (index) { - case 0: - value = QCoreApplication::translate("TRadGradFillStyle", "X Position"); - break; - case 1: - value = QCoreApplication::translate("TRadGradFillStyle", "Y Position"); - break; - case 2: - value = QCoreApplication::translate("TRadGradFillStyle", "Radius"); - break; - case 3: - value = QCoreApplication::translate("TRadGradFillStyle", "Smoothness"); - break; - } - - return value; +QString TRadGradFillStyle::getParamNames(int index) const { + assert(0 <= index && index < 4); + + QString value; + switch (index) { + case 0: + value = QCoreApplication::translate("TRadGradFillStyle", "X Position"); + break; + case 1: + value = QCoreApplication::translate("TRadGradFillStyle", "Y Position"); + break; + case 2: + value = QCoreApplication::translate("TRadGradFillStyle", "Radius"); + break; + case 3: + value = QCoreApplication::translate("TRadGradFillStyle", "Smoothness"); + break; + } + + return value; } //----------------------------------------------------------------------------- -void TRadGradFillStyle::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 4); - switch (index) { - case 0: - min = -100.0; - max = 100.0; - break; - case 1: - min = -100.0; - max = 100.0; - break; - case 2: - min = 0.01; - max = 100.0; - break; - case 3: - min = 0.01; - max = 100.0; - break; - } +void TRadGradFillStyle::getParamRange(int index, double &min, + double &max) const { + assert(0 <= index && index < 4); + switch (index) { + case 0: + min = -100.0; + max = 100.0; + break; + case 1: + min = -100.0; + max = 100.0; + break; + case 2: + min = 0.01; + max = 100.0; + break; + case 3: + min = 0.01; + max = 100.0; + break; + } } //----------------------------------------------------------------------------- -double TRadGradFillStyle::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 4); - - switch (index) { - case 0: - return m_XPos; - case 1: - return m_YPos; - case 2: - return m_Radius; - case 3: - return m_Smooth; - } - return 0.0; +double TRadGradFillStyle::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 4); + + switch (index) { + case 0: + return m_XPos; + case 1: + return m_YPos; + case 2: + return m_Radius; + case 3: + return m_Smooth; + } + return 0.0; } //----------------------------------------------------------------------------- -void TRadGradFillStyle::setParamValue(int index, double value) -{ - assert(0 <= index && index < 4); +void TRadGradFillStyle::setParamValue(int index, double value) { + assert(0 <= index && index < 4); + + switch (index) { + case 0: + m_XPos = value; + break; + case 1: + m_YPos = value; + break; + case 2: + m_Radius = value; + break; + case 3: + m_Smooth = value; + break; + } +} + +//------------------------------------------------------------ - switch (index) { - case 0: - m_XPos = value; - break; - case 1: - m_YPos = value; - break; - case 2: - m_Radius = value; - break; - case 3: - m_Smooth = value; - break; - } +void TRadGradFillStyle::loadData(TInputStreamInterface &is) { + TSolidColorStyle::loadData(is); + is >> m_XPos; + is >> m_YPos; + is >> m_Radius; + is >> m_Smooth; + is >> m_pointColor; } //------------------------------------------------------------ -void TRadGradFillStyle::loadData(TInputStreamInterface &is) -{ - TSolidColorStyle::loadData(is); - is >> m_XPos; - is >> m_YPos; - is >> m_Radius; - is >> m_Smooth; - is >> m_pointColor; +void TRadGradFillStyle::saveData(TOutputStreamInterface &os) const { + TSolidColorStyle::saveData(os); + os << m_XPos; + os << m_YPos; + os << m_Radius; + os << m_Smooth; + os << m_pointColor; } //------------------------------------------------------------ -void TRadGradFillStyle::saveData(TOutputStreamInterface &os) const -{ - TSolidColorStyle::saveData(os); - os << m_XPos; - os << m_YPos; - os << m_Radius; - os << m_Smooth; - os << m_pointColor; +TPixel32 TRadGradFillStyle::getColorParamValue(int index) const { + return index == 0 ? m_pointColor : TSolidColorStyle::getMainColor(); } //------------------------------------------------------------ -TPixel32 TRadGradFillStyle::getColorParamValue(int index) const -{ - return index == 0 ? m_pointColor : TSolidColorStyle::getMainColor(); +void TRadGradFillStyle::setColorParamValue(int index, const TPixel32 &color) { + if (index == 0) + m_pointColor = color; + else { + TSolidColorStyle::setMainColor(color); + } } //------------------------------------------------------------ -void TRadGradFillStyle::setColorParamValue(int index, const TPixel32 &color) -{ - if (index == 0) - m_pointColor = color; - else { - TSolidColorStyle::setMainColor(color); - } +void TRadGradFillStyle::drawRegion(const TColorFunction *cf, + const bool antiAliasing, + TRegionOutline &boundary) const { + TStencilControl *stenc = TStencilControl::instance(); + // only to create stencil mask + TSolidColorStyle appStyle(TPixel32::White); + stenc->beginMask(); // does not draw on screen + appStyle.drawRegion(0, false, boundary); + stenc->endMask(); + + TPixel32 backgroundColor, color; + if (cf) { + backgroundColor = (*(cf))(TSolidColorStyle::getMainColor()); + color = (*(cf))(m_pointColor); + } else { + backgroundColor = TSolidColorStyle::getMainColor(); + color = m_pointColor; + } + + TRectD bbox(boundary.m_bbox); + double lx = bbox.x1 - bbox.x0; + double ly = bbox.y1 - bbox.y0; + double r2 = std::max(lx, ly) * 5.0; + double r1 = 0.5 * std::max(lx, ly) * m_Radius * 0.01; + double r0 = r1 * (100.0 - m_Smooth) * 0.01; + + TPointD center((bbox.x1 + bbox.x0) / 2.0, (bbox.y1 + bbox.y0) / 2.0); + center = center + TPointD(m_XPos * 0.01 * lx * 0.5, m_YPos * 0.01 * ly * 0.5); + + const double dAngle = 5.0; + std::vector sincos; + for (double angle = 0.0; angle <= 360.0; angle += dAngle) + sincos.push_back(TPointD(sin(degree2rad(angle)), cos(degree2rad(angle)))); + + stenc->enableMask(TStencilControl::SHOW_INSIDE); + + glBegin(GL_TRIANGLE_FAN); + tglColor(color); + tglVertex(center); + int i = 0; + for (; i < (int)sincos.size(); i++) + tglVertex(center + TPointD(r0 * sincos[i].x, r0 * sincos[i].y)); + glEnd(); + + if (fabs(r0 - r1) > TConsts::epsilon) { + glBegin(GL_QUAD_STRIP); + for (i = 0; i < (int)sincos.size(); i++) { + tglColor(color); + tglVertex(center + TPointD(r0 * sincos[i].x, r0 * sincos[i].y)); + tglColor(backgroundColor); + tglVertex(center + TPointD(r1 * sincos[i].x, r1 * sincos[i].y)); + } + glEnd(); + } + + tglColor(backgroundColor); + glBegin(GL_QUAD_STRIP); + for (i = 0; i < (int)sincos.size(); i++) { + tglVertex(center + TPointD(r1 * sincos[i].x, r1 * sincos[i].y)); + tglVertex(center + TPointD(r2 * sincos[i].x, r2 * sincos[i].y)); + } + glEnd(); + + stenc->disableMask(); } //------------------------------------------------------------ -void TRadGradFillStyle::drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const -{ - TStencilControl *stenc = TStencilControl::instance(); - //only to create stencil mask - TSolidColorStyle appStyle(TPixel32::White); - stenc->beginMask(); //does not draw on screen - appStyle.drawRegion(0, false, boundary); - stenc->endMask(); - - TPixel32 backgroundColor, color; - if (cf) { - backgroundColor = (*(cf))(TSolidColorStyle::getMainColor()); - color = (*(cf))(m_pointColor); - } else { - backgroundColor = TSolidColorStyle::getMainColor(); - color = m_pointColor; - } - - TRectD bbox(boundary.m_bbox); - double lx = bbox.x1 - bbox.x0; - double ly = bbox.y1 - bbox.y0; - double r2 = std::max(lx, ly) * 5.0; - double r1 = 0.5 * std::max(lx, ly) * m_Radius * 0.01; - double r0 = r1 * (100.0 - m_Smooth) * 0.01; - - TPointD center((bbox.x1 + bbox.x0) / 2.0, (bbox.y1 + bbox.y0) / 2.0); - center = center + TPointD(m_XPos * 0.01 * lx * 0.5, m_YPos * 0.01 * ly * 0.5); - - const double dAngle = 5.0; - std::vector sincos; - for (double angle = 0.0; angle <= 360.0; angle += dAngle) - sincos.push_back(TPointD(sin(degree2rad(angle)), cos(degree2rad(angle)))); - - stenc->enableMask(TStencilControl::SHOW_INSIDE); - - glBegin(GL_TRIANGLE_FAN); - tglColor(color); - tglVertex(center); - int i = 0; - for (; i < (int)sincos.size(); i++) - tglVertex(center + TPointD(r0 * sincos[i].x, r0 * sincos[i].y)); - glEnd(); - - if (fabs(r0 - r1) > TConsts::epsilon) { - glBegin(GL_QUAD_STRIP); - for (i = 0; i < (int)sincos.size(); i++) { - tglColor(color); - tglVertex(center + TPointD(r0 * sincos[i].x, r0 * sincos[i].y)); - tglColor(backgroundColor); - tglVertex(center + TPointD(r1 * sincos[i].x, r1 * sincos[i].y)); - } - glEnd(); - } - - tglColor(backgroundColor); - glBegin(GL_QUAD_STRIP); - for (i = 0; i < (int)sincos.size(); i++) { - tglVertex(center + TPointD(r1 * sincos[i].x, r1 * sincos[i].y)); - tglVertex(center + TPointD(r2 * sincos[i].x, r2 * sincos[i].y)); - } - glEnd(); - - stenc->disableMask(); -} - -//------------------------------------------------------------ - -void TRadGradFillStyle::drawRegion(TFlash &flash, const TRegion *r) const -{ - TRectD bbox(r->getBBox()); - double lx = bbox.x1 - bbox.x0; - double ly = bbox.y1 - bbox.y0; - double r1 = 0.5 * std::max(lx, ly) * m_Radius * 0.01; - if (m_Smooth < 50) - r1 *= (0.3 * ((100 - m_Smooth) / 50.0) + 0.7); - TPointD center((bbox.x1 + bbox.x0) / 2.0, (bbox.y1 + bbox.y0) / 2.0); - center = center + TPointD(m_XPos * 0.01 * lx * 0.5, m_YPos * 0.01 * ly * 0.5); - - flash.setThickness(0.0); - TPixel32 mc(getMainColor()); - flash.setGradientFill(false, m_pointColor, mc, m_Smooth); - const double flashGrad = 16384.0; // size of gradient square - TTranslation tM(center.x, center.y); - TScale sM(2.0 * r1 / (flashGrad), 2.0 * r1 / (flashGrad)); - flash.setFillStyleMatrix(tM * sM); - flash.drawRegion(*r); +void TRadGradFillStyle::drawRegion(TFlash &flash, const TRegion *r) const { + TRectD bbox(r->getBBox()); + double lx = bbox.x1 - bbox.x0; + double ly = bbox.y1 - bbox.y0; + double r1 = 0.5 * std::max(lx, ly) * m_Radius * 0.01; + if (m_Smooth < 50) r1 *= (0.3 * ((100 - m_Smooth) / 50.0) + 0.7); + TPointD center((bbox.x1 + bbox.x0) / 2.0, (bbox.y1 + bbox.y0) / 2.0); + center = center + TPointD(m_XPos * 0.01 * lx * 0.5, m_YPos * 0.01 * ly * 0.5); + + flash.setThickness(0.0); + TPixel32 mc(getMainColor()); + flash.setGradientFill(false, m_pointColor, mc, m_Smooth); + const double flashGrad = 16384.0; // size of gradient square + TTranslation tM(center.x, center.y); + TScale sM(2.0 * r1 / (flashGrad), 2.0 * r1 / (flashGrad)); + flash.setFillStyleMatrix(tM * sM); + flash.drawRegion(*r); } //*************************************************************************** @@ -4108,331 +3938,320 @@ void TRadGradFillStyle::drawRegion(TFlash &flash, const TRegion *r) const //*************************************************************************** TCircleStripeFillStyle::TCircleStripeFillStyle( - const TPixel32 &bgColor, const TPixel32 &pointColor, - const double XPos, const double YPos, - const double Dist, const double Thickness) - : TSolidColorStyle(bgColor), m_pointColor(pointColor), m_XPos(XPos), m_YPos(YPos), m_Dist(Dist), m_Thickness(Thickness) -{ -} + const TPixel32 &bgColor, const TPixel32 &pointColor, const double XPos, + const double YPos, const double Dist, const double Thickness) + : TSolidColorStyle(bgColor) + , m_pointColor(pointColor) + , m_XPos(XPos) + , m_YPos(YPos) + , m_Dist(Dist) + , m_Thickness(Thickness) {} //------------------------------------------------------------ TCircleStripeFillStyle::TCircleStripeFillStyle(const TPixel32 &color) - : TSolidColorStyle(TPixel32::Transparent), m_pointColor(color), m_XPos(0.0), m_YPos(0.0), m_Dist(15.0), m_Thickness(3.0) -{ -} + : TSolidColorStyle(TPixel32::Transparent) + , m_pointColor(color) + , m_XPos(0.0) + , m_YPos(0.0) + , m_Dist(15.0) + , m_Thickness(3.0) {} //------------------------------------------------------------ -TColorStyle *TCircleStripeFillStyle::clone() const -{ - return new TCircleStripeFillStyle(*this); +TColorStyle *TCircleStripeFillStyle::clone() const { + return new TCircleStripeFillStyle(*this); } //------------------------------------------------------------ -int TCircleStripeFillStyle::getParamCount() const -{ - return 4; -} +int TCircleStripeFillStyle::getParamCount() const { return 4; } //----------------------------------------------------------------------------- -TColorStyle::ParamType TCircleStripeFillStyle::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +TColorStyle::ParamType TCircleStripeFillStyle::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -QString TCircleStripeFillStyle::getParamNames(int index) const -{ - assert(0 <= index && index < 4); - - QString value; - switch (index) { - case 0: - value = QCoreApplication::translate("TCircleStripeFillStyle", "X Position"); - break; - case 1: - value = QCoreApplication::translate("TCircleStripeFillStyle", "Y Position"); - break; - case 2: - value = QCoreApplication::translate("TCircleStripeFillStyle", "Distance"); - break; - case 3: - value = QCoreApplication::translate("TCircleStripeFillStyle", "Thickness"); - break; - } - - return value; +QString TCircleStripeFillStyle::getParamNames(int index) const { + assert(0 <= index && index < 4); + + QString value; + switch (index) { + case 0: + value = QCoreApplication::translate("TCircleStripeFillStyle", "X Position"); + break; + case 1: + value = QCoreApplication::translate("TCircleStripeFillStyle", "Y Position"); + break; + case 2: + value = QCoreApplication::translate("TCircleStripeFillStyle", "Distance"); + break; + case 3: + value = QCoreApplication::translate("TCircleStripeFillStyle", "Thickness"); + break; + } + + return value; } //----------------------------------------------------------------------------- -void TCircleStripeFillStyle::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 4); - switch (index) { - case 0: - min = -200.0; - max = 200.0; - break; - case 1: - min = -200.0; - max = 200.0; - break; - case 2: - min = 0.5; - max = 100.0; - break; - case 3: - min = 0.5; - max = 100.0; - break; - } +void TCircleStripeFillStyle::getParamRange(int index, double &min, + double &max) const { + assert(0 <= index && index < 4); + switch (index) { + case 0: + min = -200.0; + max = 200.0; + break; + case 1: + min = -200.0; + max = 200.0; + break; + case 2: + min = 0.5; + max = 100.0; + break; + case 3: + min = 0.5; + max = 100.0; + break; + } } //----------------------------------------------------------------------------- -double TCircleStripeFillStyle::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 4); - - switch (index) { - case 0: - return m_XPos; - case 1: - return m_YPos; - case 2: - return m_Dist; - case 3: - return m_Thickness; - } - return 0.0; +double TCircleStripeFillStyle::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 4); + + switch (index) { + case 0: + return m_XPos; + case 1: + return m_YPos; + case 2: + return m_Dist; + case 3: + return m_Thickness; + } + return 0.0; } //----------------------------------------------------------------------------- -void TCircleStripeFillStyle::setParamValue(int index, double value) -{ - assert(0 <= index && index < 4); - - switch (index) { - case 0: - m_XPos = value; - break; - case 1: - m_YPos = value; - break; - case 2: - m_Dist = value; - break; - case 3: - m_Thickness = value; - break; - } +void TCircleStripeFillStyle::setParamValue(int index, double value) { + assert(0 <= index && index < 4); + + switch (index) { + case 0: + m_XPos = value; + break; + case 1: + m_YPos = value; + break; + case 2: + m_Dist = value; + break; + case 3: + m_Thickness = value; + break; + } } //------------------------------------------------------------ -void TCircleStripeFillStyle::loadData(TInputStreamInterface &is) -{ - TSolidColorStyle::loadData(is); - is >> m_XPos; - is >> m_YPos; - is >> m_Dist; - is >> m_Thickness; - is >> m_pointColor; +void TCircleStripeFillStyle::loadData(TInputStreamInterface &is) { + TSolidColorStyle::loadData(is); + is >> m_XPos; + is >> m_YPos; + is >> m_Dist; + is >> m_Thickness; + is >> m_pointColor; } //------------------------------------------------------------ -void TCircleStripeFillStyle::saveData(TOutputStreamInterface &os) const -{ - TSolidColorStyle::saveData(os); - os << m_XPos; - os << m_YPos; - os << m_Dist; - os << m_Thickness; - os << m_pointColor; +void TCircleStripeFillStyle::saveData(TOutputStreamInterface &os) const { + TSolidColorStyle::saveData(os); + os << m_XPos; + os << m_YPos; + os << m_Dist; + os << m_Thickness; + os << m_pointColor; } //------------------------------------------------------------ -TPixel32 TCircleStripeFillStyle::getColorParamValue(int index) const -{ - return index == 0 ? m_pointColor : TSolidColorStyle::getMainColor(); +TPixel32 TCircleStripeFillStyle::getColorParamValue(int index) const { + return index == 0 ? m_pointColor : TSolidColorStyle::getMainColor(); } //------------------------------------------------------------ -void TCircleStripeFillStyle::setColorParamValue(int index, const TPixel32 &color) -{ - if (index == 0) - m_pointColor = color; - else { - TSolidColorStyle::setMainColor(color); - } +void TCircleStripeFillStyle::setColorParamValue(int index, + const TPixel32 &color) { + if (index == 0) + m_pointColor = color; + else { + TSolidColorStyle::setMainColor(color); + } } //------------------------------------------------------------ -void TCircleStripeFillStyle::getCircleStripeQuads(const TPointD ¢er, - const double r1, const double r2, - std::vector &pv) const -{ - pv.clear(); - const double dAng = 10.0; - for (double ang = 0.0; ang <= 360; ang += dAng) { - pv.push_back(center + TPointD(r1 * cos(degree2rad(ang)), r1 * sin(degree2rad(ang)))); - pv.push_back(center + TPointD(r2 * cos(degree2rad(ang)), r2 * sin(degree2rad(ang)))); - } +void TCircleStripeFillStyle::getCircleStripeQuads( + const TPointD ¢er, const double r1, const double r2, + std::vector &pv) const { + pv.clear(); + const double dAng = 10.0; + for (double ang = 0.0; ang <= 360; ang += dAng) { + pv.push_back(center + + TPointD(r1 * cos(degree2rad(ang)), r1 * sin(degree2rad(ang)))); + pv.push_back(center + + TPointD(r2 * cos(degree2rad(ang)), r2 * sin(degree2rad(ang)))); + } } //------------------------------------------------------------ void TCircleStripeFillStyle::drawCircleStripe(const TPointD ¢er, - const double r1, const double r2, - const TPixel32 &col) const -{ - std::vector pv; - getCircleStripeQuads(center, r1, r2, pv); + const double r1, const double r2, + const TPixel32 &col) const { + std::vector pv; + getCircleStripeQuads(center, r1, r2, pv); - TStencilControl *stencil = TStencilControl::instance(); - stencil->beginMask(TStencilControl::DRAW_ALSO_ON_SCREEN); + TStencilControl *stencil = TStencilControl::instance(); + stencil->beginMask(TStencilControl::DRAW_ALSO_ON_SCREEN); - glBegin(GL_QUAD_STRIP); - tglColor(col); - int i = 0; - for (; i < (int)pv.size(); i++) - tglVertex(pv[i]); - glEnd(); + glBegin(GL_QUAD_STRIP); + tglColor(col); + int i = 0; + for (; i < (int)pv.size(); i++) tglVertex(pv[i]); + glEnd(); - stencil->endMask(); - stencil->enableMask(TStencilControl::SHOW_OUTSIDE); + stencil->endMask(); + stencil->enableMask(TStencilControl::SHOW_OUTSIDE); - //glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); - //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - //glEnable(GL_BLEND); - //glEnable(GL_LINE_SMOOTH); - tglEnableLineSmooth(); + // glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + // glEnable(GL_BLEND); + // glEnable(GL_LINE_SMOOTH); + tglEnableLineSmooth(); - // Just for the antialiasing - glBegin(GL_LINE_STRIP); - tglColor(col); - for (i = 0; i < (int)pv.size(); i += 2) - tglVertex(pv[i]); - glEnd(); + // Just for the antialiasing + glBegin(GL_LINE_STRIP); + tglColor(col); + for (i = 0; i < (int)pv.size(); i += 2) tglVertex(pv[i]); + glEnd(); - glBegin(GL_LINE_STRIP); - tglColor(col); - for (i = 1; i < (int)pv.size(); i += 2) - tglVertex(pv[i]); - glEnd(); + glBegin(GL_LINE_STRIP); + tglColor(col); + for (i = 1; i < (int)pv.size(); i += 2) tglVertex(pv[i]); + glEnd(); - stencil->disableMask(); + stencil->disableMask(); } //------------------------------------------------------------ -void TCircleStripeFillStyle::drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const -{ - const bool isTransparent = m_pointColor.m < 255; - - TStencilControl *stenc = TStencilControl::instance(); - TPixel32 backgroundColor = TSolidColorStyle::getMainColor(); - if (cf) - backgroundColor = (*(cf))(m_pointColor); - - TPixel32 foregroundColor; - if (cf) - foregroundColor = (*(cf))(m_pointColor); - else - foregroundColor = m_pointColor; - - if (backgroundColor.m == 0) { //only to create stencil mask - TSolidColorStyle appStyle(TPixel32::White); - stenc->beginMask(); //does not draw on screen - appStyle.drawRegion(0, false, boundary); - } else { //create stencil mask and draw on screen - stenc->beginMask(TStencilControl::DRAW_ALSO_ON_SCREEN); - TSolidColorStyle::drawRegion(cf, antiAliasing, boundary); - } - stenc->endMask(); - stenc->enableMask(TStencilControl::SHOW_INSIDE); - - if (isTransparent) { - //glEnable(GL_BLEND); - //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - //// <-- tglEnableBlending(); - } - - TRectD bbox = boundary.m_bbox; - double lx = bbox.x1 - bbox.x0; - double ly = bbox.y1 - bbox.y0; - TPointD center((bbox.x1 + bbox.x0) * 0.5, (bbox.y1 + bbox.y0) * 0.5); - center.x = center.x + m_XPos * 0.01 * 0.5 * lx; - center.y = center.y + m_YPos * 0.01 * 0.5 * ly; - - double maxDist = 0.0; - maxDist = std::max(tdistance(center, TPointD(bbox.x0, bbox.y0)), maxDist); - maxDist = std::max(tdistance(center, TPointD(bbox.x0, bbox.y1)), maxDist); - maxDist = std::max(tdistance(center, TPointD(bbox.x1, bbox.y0)), maxDist); - maxDist = std::max(tdistance(center, TPointD(bbox.x1, bbox.y1)), maxDist); - - double halfThick = m_Thickness * 0.5; - for (double d = 0; d <= maxDist; d += m_Dist) - drawCircleStripe(center, d - halfThick, d + halfThick, foregroundColor); - - if (isTransparent) { - //tglColor(TPixel32::White); - //glDisable(GL_BLEND); - } - - stenc->disableMask(); -} - -//------------------------------------------------------------ - -void TCircleStripeFillStyle::drawRegion(TFlash &flash, const TRegion *r) const -{ - TRectD bbox(r->getBBox()); - - double lx = bbox.x1 - bbox.x0; - double ly = bbox.y1 - bbox.y0; - TPointD center((bbox.x1 + bbox.x0) * 0.5, (bbox.y1 + bbox.y0) * 0.5); - center.x = center.x + m_XPos * 0.01 * 0.5 * lx; - center.y = center.y + m_YPos * 0.01 * 0.5 * ly; - - double maxDist = 0.0; - maxDist = std::max(tdistance(center, TPointD(bbox.x0, bbox.y0)), maxDist); - maxDist = std::max(tdistance(center, TPointD(bbox.x0, bbox.y1)), maxDist); - maxDist = std::max(tdistance(center, TPointD(bbox.x1, bbox.y0)), maxDist); - maxDist = std::max(tdistance(center, TPointD(bbox.x1, bbox.y1)), maxDist); - - int nbClip = 2; - double d = m_Dist; - for (; d <= maxDist; d += m_Dist) - nbClip++; - flash.setFillColor(TPixel::Black); - flash.drawRegion(*r, nbClip); - - flash.setFillColor(getMainColor()); - flash.drawRectangle(bbox); - - flash.setFillColor(m_pointColor); - flash.setLineColor(m_pointColor); - flash.setThickness(0.0); - d = m_Thickness / 2.0; - flash.drawEllipse(center, d, d); - - flash.setFillColor(TPixel32(0, 0, 0, 0)); - flash.setLineColor(m_pointColor); - flash.setThickness(m_Thickness / 2.0); - for (d = m_Dist; d <= maxDist; d += m_Dist) - flash.drawEllipse(center, d, d); +void TCircleStripeFillStyle::drawRegion(const TColorFunction *cf, + const bool antiAliasing, + TRegionOutline &boundary) const { + const bool isTransparent = m_pointColor.m < 255; + + TStencilControl *stenc = TStencilControl::instance(); + TPixel32 backgroundColor = TSolidColorStyle::getMainColor(); + if (cf) backgroundColor = (*(cf))(m_pointColor); + + TPixel32 foregroundColor; + if (cf) + foregroundColor = (*(cf))(m_pointColor); + else + foregroundColor = m_pointColor; + + if (backgroundColor.m == 0) { // only to create stencil mask + TSolidColorStyle appStyle(TPixel32::White); + stenc->beginMask(); // does not draw on screen + appStyle.drawRegion(0, false, boundary); + } else { // create stencil mask and draw on screen + stenc->beginMask(TStencilControl::DRAW_ALSO_ON_SCREEN); + TSolidColorStyle::drawRegion(cf, antiAliasing, boundary); + } + stenc->endMask(); + stenc->enableMask(TStencilControl::SHOW_INSIDE); + + if (isTransparent) { + // glEnable(GL_BLEND); + // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + //// <-- tglEnableBlending(); + } + + TRectD bbox = boundary.m_bbox; + double lx = bbox.x1 - bbox.x0; + double ly = bbox.y1 - bbox.y0; + TPointD center((bbox.x1 + bbox.x0) * 0.5, (bbox.y1 + bbox.y0) * 0.5); + center.x = center.x + m_XPos * 0.01 * 0.5 * lx; + center.y = center.y + m_YPos * 0.01 * 0.5 * ly; + + double maxDist = 0.0; + maxDist = std::max(tdistance(center, TPointD(bbox.x0, bbox.y0)), maxDist); + maxDist = std::max(tdistance(center, TPointD(bbox.x0, bbox.y1)), maxDist); + maxDist = std::max(tdistance(center, TPointD(bbox.x1, bbox.y0)), maxDist); + maxDist = std::max(tdistance(center, TPointD(bbox.x1, bbox.y1)), maxDist); + + double halfThick = m_Thickness * 0.5; + for (double d = 0; d <= maxDist; d += m_Dist) + drawCircleStripe(center, d - halfThick, d + halfThick, foregroundColor); + + if (isTransparent) { + // tglColor(TPixel32::White); + // glDisable(GL_BLEND); + } + + stenc->disableMask(); +} + +//------------------------------------------------------------ + +void TCircleStripeFillStyle::drawRegion(TFlash &flash, const TRegion *r) const { + TRectD bbox(r->getBBox()); + + double lx = bbox.x1 - bbox.x0; + double ly = bbox.y1 - bbox.y0; + TPointD center((bbox.x1 + bbox.x0) * 0.5, (bbox.y1 + bbox.y0) * 0.5); + center.x = center.x + m_XPos * 0.01 * 0.5 * lx; + center.y = center.y + m_YPos * 0.01 * 0.5 * ly; + + double maxDist = 0.0; + maxDist = std::max(tdistance(center, TPointD(bbox.x0, bbox.y0)), maxDist); + maxDist = std::max(tdistance(center, TPointD(bbox.x0, bbox.y1)), maxDist); + maxDist = std::max(tdistance(center, TPointD(bbox.x1, bbox.y0)), maxDist); + maxDist = std::max(tdistance(center, TPointD(bbox.x1, bbox.y1)), maxDist); + + int nbClip = 2; + double d = m_Dist; + for (; d <= maxDist; d += m_Dist) nbClip++; + flash.setFillColor(TPixel::Black); + flash.drawRegion(*r, nbClip); + + flash.setFillColor(getMainColor()); + flash.drawRectangle(bbox); + + flash.setFillColor(m_pointColor); + flash.setLineColor(m_pointColor); + flash.setThickness(0.0); + d = m_Thickness / 2.0; + flash.drawEllipse(center, d, d); + + flash.setFillColor(TPixel32(0, 0, 0, 0)); + flash.setLineColor(m_pointColor); + flash.setThickness(m_Thickness / 2.0); + for (d = m_Dist; d <= maxDist; d += m_Dist) flash.drawEllipse(center, d, d); } //*************************************************************************** @@ -4440,339 +4259,324 @@ void TCircleStripeFillStyle::drawRegion(TFlash &flash, const TRegion *r) const //*************************************************************************** TMosaicFillStyle::TMosaicFillStyle(const TPixel32 &bgColor, - const TPixel32 pointColor[4], - const double size, - const double deform, - const double minThickness, - const double maxThickness) - : TSolidColorStyle(bgColor), m_size(size), m_deform(deform), m_minThickness(minThickness), m_maxThickness(maxThickness) -{ - for (int i = 0; i < 4; i++) - m_pointColor[i] = pointColor[i]; + const TPixel32 pointColor[4], + const double size, const double deform, + const double minThickness, + const double maxThickness) + : TSolidColorStyle(bgColor) + , m_size(size) + , m_deform(deform) + , m_minThickness(minThickness) + , m_maxThickness(maxThickness) { + for (int i = 0; i < 4; i++) m_pointColor[i] = pointColor[i]; } //------------------------------------------------------------ TMosaicFillStyle::TMosaicFillStyle(const TPixel32 bgColor) - : TSolidColorStyle(bgColor), m_size(25.0), m_deform(70.0), m_minThickness(20), m_maxThickness(40) -{ - m_pointColor[0] = TPixel32::Blue; - m_pointColor[1] = TPixel32::Green; - m_pointColor[2] = TPixel32::Yellow; - m_pointColor[3] = TPixel32::Cyan; + : TSolidColorStyle(bgColor) + , m_size(25.0) + , m_deform(70.0) + , m_minThickness(20) + , m_maxThickness(40) { + m_pointColor[0] = TPixel32::Blue; + m_pointColor[1] = TPixel32::Green; + m_pointColor[2] = TPixel32::Yellow; + m_pointColor[3] = TPixel32::Cyan; } //------------------------------------------------------------ -TColorStyle *TMosaicFillStyle::clone() const -{ - return new TMosaicFillStyle(*this); +TColorStyle *TMosaicFillStyle::clone() const { + return new TMosaicFillStyle(*this); } //------------------------------------------------------------ -int TMosaicFillStyle::getParamCount() const -{ - return 4; -} +int TMosaicFillStyle::getParamCount() const { return 4; } //----------------------------------------------------------------------------- -TColorStyle::ParamType TMosaicFillStyle::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +TColorStyle::ParamType TMosaicFillStyle::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -QString TMosaicFillStyle::getParamNames(int index) const -{ - assert(0 <= index && index < 4); - QString value; - switch (index) { - case 0: - value = QCoreApplication::translate("TMosaicFillStyle", "Size"); - break; - case 1: - value = QCoreApplication::translate("TMosaicFillStyle", "Distortion"); - break; - case 2: - value = QCoreApplication::translate("TMosaicFillStyle", "Min Thick"); - break; - case 3: - value = QCoreApplication::translate("TMosaicFillStyle", "Max Thick"); - break; - } - - return value; +QString TMosaicFillStyle::getParamNames(int index) const { + assert(0 <= index && index < 4); + QString value; + switch (index) { + case 0: + value = QCoreApplication::translate("TMosaicFillStyle", "Size"); + break; + case 1: + value = QCoreApplication::translate("TMosaicFillStyle", "Distortion"); + break; + case 2: + value = QCoreApplication::translate("TMosaicFillStyle", "Min Thick"); + break; + case 3: + value = QCoreApplication::translate("TMosaicFillStyle", "Max Thick"); + break; + } + + return value; } //----------------------------------------------------------------------------- -void TMosaicFillStyle::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 4); - min = (index == 0) ? 2 : 0.001; - max = 100.0; +void TMosaicFillStyle::getParamRange(int index, double &min, + double &max) const { + assert(0 <= index && index < 4); + min = (index == 0) ? 2 : 0.001; + max = 100.0; } //----------------------------------------------------------------------------- -double TMosaicFillStyle::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 4); - - double value; - switch (index) { - case 0: - value = m_size; - break; - case 1: - value = m_deform; - break; - case 2: - value = m_minThickness; - break; - case 3: - value = m_maxThickness; - break; - } - return value; +double TMosaicFillStyle::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 4); + + double value; + switch (index) { + case 0: + value = m_size; + break; + case 1: + value = m_deform; + break; + case 2: + value = m_minThickness; + break; + case 3: + value = m_maxThickness; + break; + } + return value; } //----------------------------------------------------------------------------- -void TMosaicFillStyle::setParamValue(int index, double value) -{ - assert(0 <= index && index < 4); - - switch (index) { - case 0: - m_size = value; - break; - case 1: - m_deform = value; - break; - case 2: - m_minThickness = value; - break; - case 3: - m_maxThickness = value; - break; - } +void TMosaicFillStyle::setParamValue(int index, double value) { + assert(0 <= index && index < 4); + + switch (index) { + case 0: + m_size = value; + break; + case 1: + m_deform = value; + break; + case 2: + m_minThickness = value; + break; + case 3: + m_maxThickness = value; + break; + } } //------------------------------------------------------------ -void TMosaicFillStyle::loadData(TInputStreamInterface &is) -{ - TSolidColorStyle::loadData(is); - is >> m_size; - is >> m_deform; - is >> m_minThickness; - is >> m_maxThickness; - is >> m_pointColor[0]; - is >> m_pointColor[1]; - is >> m_pointColor[2]; - is >> m_pointColor[3]; +void TMosaicFillStyle::loadData(TInputStreamInterface &is) { + TSolidColorStyle::loadData(is); + is >> m_size; + is >> m_deform; + is >> m_minThickness; + is >> m_maxThickness; + is >> m_pointColor[0]; + is >> m_pointColor[1]; + is >> m_pointColor[2]; + is >> m_pointColor[3]; } //------------------------------------------------------------ -void TMosaicFillStyle::saveData(TOutputStreamInterface &os) const -{ - TSolidColorStyle::saveData(os); - os << m_size; - os << m_deform; - os << m_minThickness; - os << m_maxThickness; - os << m_pointColor[0]; - os << m_pointColor[1]; - os << m_pointColor[2]; - os << m_pointColor[3]; +void TMosaicFillStyle::saveData(TOutputStreamInterface &os) const { + TSolidColorStyle::saveData(os); + os << m_size; + os << m_deform; + os << m_minThickness; + os << m_maxThickness; + os << m_pointColor[0]; + os << m_pointColor[1]; + os << m_pointColor[2]; + os << m_pointColor[3]; } //------------------------------------------------------------ -TPixel32 TMosaicFillStyle::getColorParamValue(int index) const -{ - TPixel32 tmp; - if (index == 0) - tmp = TSolidColorStyle::getMainColor(); - else if (index >= 1 && index <= 4) - tmp = m_pointColor[index - 1]; - else - assert(!"bad color index"); +TPixel32 TMosaicFillStyle::getColorParamValue(int index) const { + TPixel32 tmp; + if (index == 0) + tmp = TSolidColorStyle::getMainColor(); + else if (index >= 1 && index <= 4) + tmp = m_pointColor[index - 1]; + else + assert(!"bad color index"); - return tmp; + return tmp; } //------------------------------------------------------------ -void TMosaicFillStyle::setColorParamValue(int index, const TPixel32 &color) -{ - if (index == 0) - TSolidColorStyle::setMainColor(color); - else if (index >= 1 && index <= 4) - m_pointColor[index - 1] = color; - else - assert(!"bad color index"); +void TMosaicFillStyle::setColorParamValue(int index, const TPixel32 &color) { + if (index == 0) + TSolidColorStyle::setMainColor(color); + else if (index >= 1 && index <= 4) + m_pointColor[index - 1] = color; + else + assert(!"bad color index"); } //------------------------------------------------------------ void TMosaicFillStyle::preaprePos(const TRectD &box, std::vector &v, - int &lX, int &lY, TRandom &rand) const -{ - double dist = 5.0 + (60.0 - 5.0) * tcrop(m_size, 0.0, 100.0) * 0.01; - lY = lX = 0; - double ld = 0.4 * tcrop(m_deform, 0.0, 100.0) * 0.01; - for (double y = box.y0 - dist; y <= (box.y1 + dist); y += dist, lY++) { - lX = 0; - for (double x = box.x0 - dist; x <= (box.x1 + dist); x += dist, lX++) { - double dx = (rand.getInt(0, 2001) * 0.001 - 1.0) * ld * dist; - double dy = (rand.getInt(0, 2001) * 0.001 - 1.0) * ld * dist; - TPointD pos(x + dx, y + dy); - v.push_back(pos); - } - } -} - -//------------------------------------------------------------ - -bool TMosaicFillStyle::getQuad(const int ix, const int iy, - const int lX, const int lY, - std::vector &v, - TPointD *pquad, TRandom &rand) const -{ - if (ix < 0 || iy < 0 || ix >= (lX - 1) || iy >= (lY - 1)) - return false; + int &lX, int &lY, TRandom &rand) const { + double dist = 5.0 + (60.0 - 5.0) * tcrop(m_size, 0.0, 100.0) * 0.01; + lY = lX = 0; + double ld = 0.4 * tcrop(m_deform, 0.0, 100.0) * 0.01; + for (double y = box.y0 - dist; y <= (box.y1 + dist); y += dist, lY++) { + lX = 0; + for (double x = box.x0 - dist; x <= (box.x1 + dist); x += dist, lX++) { + double dx = (rand.getInt(0, 2001) * 0.001 - 1.0) * ld * dist; + double dy = (rand.getInt(0, 2001) * 0.001 - 1.0) * ld * dist; + TPointD pos(x + dx, y + dy); + v.push_back(pos); + } + } +} + +//------------------------------------------------------------ - double dmin = tcrop(m_minThickness, 0.0, 100.0) * 0.01; - double dmax = tcrop(m_maxThickness, 0.0, 100.0) * 0.01; +bool TMosaicFillStyle::getQuad(const int ix, const int iy, const int lX, + const int lY, std::vector &v, + TPointD *pquad, TRandom &rand) const { + if (ix < 0 || iy < 0 || ix >= (lX - 1) || iy >= (lY - 1)) return false; - TPointD &p1 = v[iy * lX + ix]; - TPointD &p2 = v[iy * lX + ix + 1]; - TPointD &p3 = v[(iy + 1) * lX + ix + 1]; - TPointD &p4 = v[(iy + 1) * lX + ix]; + double dmin = tcrop(m_minThickness, 0.0, 100.0) * 0.01; + double dmax = tcrop(m_maxThickness, 0.0, 100.0) * 0.01; - double q1 = 0.5 * (dmin + (dmax - dmin) * rand.getInt(0, 101) * 0.01); - double q2 = 0.5 * (dmin + (dmax - dmin) * rand.getInt(0, 101) * 0.01); - double q3 = 0.5 * (dmin + (dmax - dmin) * rand.getInt(0, 101) * 0.01); - double q4 = 0.5 * (dmin + (dmax - dmin) * rand.getInt(0, 101) * 0.01); + TPointD &p1 = v[iy * lX + ix]; + TPointD &p2 = v[iy * lX + ix + 1]; + TPointD &p3 = v[(iy + 1) * lX + ix + 1]; + TPointD &p4 = v[(iy + 1) * lX + ix]; - pquad[0] = (1.0 - q1) * p1 + q1 * p3; - pquad[1] = (1.0 - q2) * p2 + q2 * p4; - pquad[2] = (1.0 - q3) * p3 + q3 * p1; - pquad[3] = (1.0 - q4) * p4 + q4 * p2; + double q1 = 0.5 * (dmin + (dmax - dmin) * rand.getInt(0, 101) * 0.01); + double q2 = 0.5 * (dmin + (dmax - dmin) * rand.getInt(0, 101) * 0.01); + double q3 = 0.5 * (dmin + (dmax - dmin) * rand.getInt(0, 101) * 0.01); + double q4 = 0.5 * (dmin + (dmax - dmin) * rand.getInt(0, 101) * 0.01); - return true; + pquad[0] = (1.0 - q1) * p1 + q1 * p3; + pquad[1] = (1.0 - q2) * p2 + q2 * p4; + pquad[2] = (1.0 - q3) * p3 + q3 * p1; + pquad[3] = (1.0 - q4) * p4 + q4 * p2; + + return true; } //------------------------------------------------------------ -void TMosaicFillStyle::drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const -{ +void TMosaicFillStyle::drawRegion(const TColorFunction *cf, + const bool antiAliasing, + TRegionOutline &boundary) const { + TStencilControl *stenc = TStencilControl::instance(); + TPixel32 backgroundColor = TSolidColorStyle::getMainColor(); + if (cf) backgroundColor = (*(cf))(backgroundColor); - TStencilControl *stenc = TStencilControl::instance(); - TPixel32 backgroundColor = TSolidColorStyle::getMainColor(); - if (cf) - backgroundColor = (*(cf))(backgroundColor); - - if (backgroundColor.m == 0) { //only to create stencil mask - TSolidColorStyle appStyle(TPixel32::White); - stenc->beginMask(); //does not draw on screen - appStyle.drawRegion(0, false, boundary); - } else { //create stencil mask and draw on screen - stenc->beginMask(TStencilControl::DRAW_ALSO_ON_SCREEN); - TSolidColorStyle::drawRegion(cf, antiAliasing, boundary); - } - stenc->endMask(); - stenc->enableMask(TStencilControl::SHOW_INSIDE); - - //glEnable(GL_BLEND); - //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - //// <-- tglEnableBlending(); - - TPixel32 color[4]; - for (int i = 0; i < 4; i++) { - if (cf) - color[i] = (*(cf))(m_pointColor[i]); - else - color[i] = m_pointColor[i]; - } - TPixel32 currentColor; - - std::vector pos; - int posLX, posLY; - TRandom rand; - TPointD quad[4]; - - preaprePos(boundary.m_bbox, pos, posLX, posLY, rand); - - glBegin(GL_QUADS); - - /* ma serve ? - tglColor(getMainColor()); - tglVertex(TPointD(boundary.m_bbox.x0,boundary.m_bbox.y0)); - tglVertex(TPointD(boundary.m_bbox.x0,boundary.m_bbox.y1)); - tglVertex(TPointD(boundary.m_bbox.x1,boundary.m_bbox.y1)); - tglVertex(TPointD(boundary.m_bbox.x1,boundary.m_bbox.y0)); - */ - - for (int y = 0; y < (posLY - 1); y++) - for (int x = 0; x < (posLX - 1); x++) - if (getQuad(x, y, posLX, posLY, pos, quad, rand)) { - currentColor = color[rand.getInt(0, 4)]; - if (currentColor.m != 0) { - tglColor(currentColor); - tglVertex(quad[0]); - tglVertex(quad[1]); - tglVertex(quad[2]); - tglVertex(quad[3]); - } - } - glEnd(); - - //tglColor(TPixel32::White); - - stenc->disableMask(); -} - -//------------------------------------------------------------ - -void TMosaicFillStyle::drawRegion(TFlash &flash, const TRegion *r) const -{ + if (backgroundColor.m == 0) { // only to create stencil mask + TSolidColorStyle appStyle(TPixel32::White); + stenc->beginMask(); // does not draw on screen + appStyle.drawRegion(0, false, boundary); + } else { // create stencil mask and draw on screen + stenc->beginMask(TStencilControl::DRAW_ALSO_ON_SCREEN); + TSolidColorStyle::drawRegion(cf, antiAliasing, boundary); + } + stenc->endMask(); + stenc->enableMask(TStencilControl::SHOW_INSIDE); + + // glEnable(GL_BLEND); + // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + //// <-- tglEnableBlending(); + + TPixel32 color[4]; + for (int i = 0; i < 4; i++) { + if (cf) + color[i] = (*(cf))(m_pointColor[i]); + else + color[i] = m_pointColor[i]; + } + TPixel32 currentColor; + + std::vector pos; + int posLX, posLY; + TRandom rand; + TPointD quad[4]; + + preaprePos(boundary.m_bbox, pos, posLX, posLY, rand); + + glBegin(GL_QUADS); - TRectD bbox(r->getBBox()); + /* ma serve ? + tglColor(getMainColor()); + tglVertex(TPointD(boundary.m_bbox.x0,boundary.m_bbox.y0)); + tglVertex(TPointD(boundary.m_bbox.x0,boundary.m_bbox.y1)); + tglVertex(TPointD(boundary.m_bbox.x1,boundary.m_bbox.y1)); + tglVertex(TPointD(boundary.m_bbox.x1,boundary.m_bbox.y0)); +*/ + + for (int y = 0; y < (posLY - 1); y++) + for (int x = 0; x < (posLX - 1); x++) + if (getQuad(x, y, posLX, posLY, pos, quad, rand)) { + currentColor = color[rand.getInt(0, 4)]; + if (currentColor.m != 0) { + tglColor(currentColor); + tglVertex(quad[0]); + tglVertex(quad[1]); + tglVertex(quad[2]); + tglVertex(quad[3]); + } + } + glEnd(); - std::vector pos; - int posLX, posLY; - TRandom rand; - TPointD quad[4]; + // tglColor(TPixel32::White); - preaprePos(bbox, pos, posLX, posLY, rand); + stenc->disableMask(); +} - if (pos.size() <= 0) - return; +//------------------------------------------------------------ - int nbClip = (posLX - 1) * (posLY - 1) + 1; - flash.drawRegion(*r, nbClip); +void TMosaicFillStyle::drawRegion(TFlash &flash, const TRegion *r) const { + TRectD bbox(r->getBBox()); - flash.setFillColor(TSolidColorStyle::getMainColor()); - flash.setThickness(0); - flash.drawRectangle(bbox); - for (int y = 0; y < (posLY - 1); y++) - for (int x = 0; x < (posLX - 1); x++) - if (getQuad(x, y, posLX, posLY, pos, quad, rand)) { - std::vector lvert; - lvert.push_back(quad[0]); - lvert.push_back(quad[1]); - lvert.push_back(quad[2]); - lvert.push_back(quad[3]); - flash.setFillColor(m_pointColor[rand.getInt(0, 4)]); - flash.drawPolyline(lvert); - } + std::vector pos; + int posLX, posLY; + TRandom rand; + TPointD quad[4]; + + preaprePos(bbox, pos, posLX, posLY, rand); + + if (pos.size() <= 0) return; + + int nbClip = (posLX - 1) * (posLY - 1) + 1; + flash.drawRegion(*r, nbClip); + + flash.setFillColor(TSolidColorStyle::getMainColor()); + flash.setThickness(0); + flash.drawRectangle(bbox); + for (int y = 0; y < (posLY - 1); y++) + for (int x = 0; x < (posLX - 1); x++) + if (getQuad(x, y, posLX, posLY, pos, quad, rand)) { + std::vector lvert; + lvert.push_back(quad[0]); + lvert.push_back(quad[1]); + lvert.push_back(quad[2]); + lvert.push_back(quad[3]); + flash.setFillColor(m_pointColor[rand.getInt(0, 4)]); + flash.drawPolyline(lvert); + } } //*************************************************************************** @@ -4780,452 +4584,429 @@ void TMosaicFillStyle::drawRegion(TFlash &flash, const TRegion *r) const //*************************************************************************** TPatchFillStyle::TPatchFillStyle(const TPixel32 &bgColor, - const TPixel32 pointColor[6], - const double size, - const double deform, - const double thickness) - : TSolidColorStyle(bgColor), m_size(size), m_deform(deform), m_thickness(thickness) -{ - for (int i = 0; i < 6; i++) - m_pointColor[i] = pointColor[i]; + const TPixel32 pointColor[6], + const double size, const double deform, + const double thickness) + : TSolidColorStyle(bgColor) + , m_size(size) + , m_deform(deform) + , m_thickness(thickness) { + for (int i = 0; i < 6; i++) m_pointColor[i] = pointColor[i]; } //----------------------------------------------------------------------------- TPatchFillStyle::TPatchFillStyle(const TPixel32 &bgColor) - : TSolidColorStyle(bgColor), m_size(25.0), m_deform(50.0), m_thickness(30) -{ - m_pointColor[0] = TPixel32::Red; - m_pointColor[1] = TPixel32::Green; - m_pointColor[2] = TPixel32::Yellow; - m_pointColor[3] = TPixel32::Cyan; - m_pointColor[4] = TPixel32::Magenta; - m_pointColor[5] = TPixel32::White; + : TSolidColorStyle(bgColor), m_size(25.0), m_deform(50.0), m_thickness(30) { + m_pointColor[0] = TPixel32::Red; + m_pointColor[1] = TPixel32::Green; + m_pointColor[2] = TPixel32::Yellow; + m_pointColor[3] = TPixel32::Cyan; + m_pointColor[4] = TPixel32::Magenta; + m_pointColor[5] = TPixel32::White; } //----------------------------------------------------------------------------- -TColorStyle *TPatchFillStyle::clone() const -{ - return new TPatchFillStyle(*this); +TColorStyle *TPatchFillStyle::clone() const { + return new TPatchFillStyle(*this); } //------------------------------------------------------------ -int TPatchFillStyle::getParamCount() const -{ - return 3; -} +int TPatchFillStyle::getParamCount() const { return 3; } //----------------------------------------------------------------------------- -TColorStyle::ParamType TPatchFillStyle::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +TColorStyle::ParamType TPatchFillStyle::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -QString TPatchFillStyle::getParamNames(int index) const -{ - assert(0 <= index && index < 3); - QString value; - switch (index) { - case 0: - value = QCoreApplication::translate("TPatchFillStyle", "Size"); - break; - case 1: - value = QCoreApplication::translate("TPatchFillStyle", "Distortion"); - break; - case 2: - value = QCoreApplication::translate("TPatchFillStyle", "Thickness"); - break; - } - - return value; +QString TPatchFillStyle::getParamNames(int index) const { + assert(0 <= index && index < 3); + QString value; + switch (index) { + case 0: + value = QCoreApplication::translate("TPatchFillStyle", "Size"); + break; + case 1: + value = QCoreApplication::translate("TPatchFillStyle", "Distortion"); + break; + case 2: + value = QCoreApplication::translate("TPatchFillStyle", "Thickness"); + break; + } + + return value; } //----------------------------------------------------------------------------- -void TPatchFillStyle::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 3); - min = (index == 0) ? 2 : 0.001; - max = 100.0; +void TPatchFillStyle::getParamRange(int index, double &min, double &max) const { + assert(0 <= index && index < 3); + min = (index == 0) ? 2 : 0.001; + max = 100.0; } //----------------------------------------------------------------------------- -double TPatchFillStyle::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 3); - - double value; - switch (index) { - case 0: - value = m_size; - break; - case 1: - value = m_deform; - break; - case 2: - value = m_thickness; - break; - } - return value; +double TPatchFillStyle::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 3); + + double value; + switch (index) { + case 0: + value = m_size; + break; + case 1: + value = m_deform; + break; + case 2: + value = m_thickness; + break; + } + return value; } //----------------------------------------------------------------------------- -void TPatchFillStyle::setParamValue(int index, double value) -{ - assert(0 <= index && index < 3); - - switch (index) { - case 0: - m_size = value; - break; - case 1: - m_deform = value; - break; - case 2: - m_thickness = value; - break; - } +void TPatchFillStyle::setParamValue(int index, double value) { + assert(0 <= index && index < 3); + + switch (index) { + case 0: + m_size = value; + break; + case 1: + m_deform = value; + break; + case 2: + m_thickness = value; + break; + } } //------------------------------------------------------------ -void TPatchFillStyle::loadData(TInputStreamInterface &is) -{ - TSolidColorStyle::loadData(is); - is >> m_size; - is >> m_deform; - is >> m_thickness; - for (int i = 0; i < 6; i++) - is >> m_pointColor[i]; +void TPatchFillStyle::loadData(TInputStreamInterface &is) { + TSolidColorStyle::loadData(is); + is >> m_size; + is >> m_deform; + is >> m_thickness; + for (int i = 0; i < 6; i++) is >> m_pointColor[i]; } //------------------------------------------------------------ -void TPatchFillStyle::saveData(TOutputStreamInterface &os) const -{ - TSolidColorStyle::saveData(os); - os << m_size; - os << m_deform; - os << m_thickness; - for (int i = 0; i < 6; i++) - os << m_pointColor[i]; +void TPatchFillStyle::saveData(TOutputStreamInterface &os) const { + TSolidColorStyle::saveData(os); + os << m_size; + os << m_deform; + os << m_thickness; + for (int i = 0; i < 6; i++) os << m_pointColor[i]; } //------------------------------------------------------------ -TPixel32 TPatchFillStyle::getColorParamValue(int index) const -{ - TPixel32 tmp; - if (index == 0) - tmp = TSolidColorStyle::getMainColor(); - else if (index >= 1 && index <= 6) - tmp = m_pointColor[index - 1]; - else - assert(!"bad color index"); +TPixel32 TPatchFillStyle::getColorParamValue(int index) const { + TPixel32 tmp; + if (index == 0) + tmp = TSolidColorStyle::getMainColor(); + else if (index >= 1 && index <= 6) + tmp = m_pointColor[index - 1]; + else + assert(!"bad color index"); - return tmp; + return tmp; } //------------------------------------------------------------ -void TPatchFillStyle::setColorParamValue(int index, const TPixel32 &color) -{ - if (index == 0) - TSolidColorStyle::setMainColor(color); - else if (index >= 1 && index <= 6) - m_pointColor[index - 1] = color; - else - assert(!"bad color index"); +void TPatchFillStyle::setColorParamValue(int index, const TPixel32 &color) { + if (index == 0) + TSolidColorStyle::setMainColor(color); + else if (index >= 1 && index <= 6) + m_pointColor[index - 1] = color; + else + assert(!"bad color index"); } //------------------------------------------------------------ void TPatchFillStyle::preaprePos(const TRectD &box, std::vector &v, - int &lX, int &lY, TRandom &rand) const -{ - double q = tcrop(m_size, 0.0, 100.0) * 0.01; - double r = 5.0 + (60.0 - 5.0) * q; - double m = r * sqrt(3.0) / 2.0; - lY = 5 + (int)((box.y1 - box.y0) / (2 * m)); - int ix = 0; - for (double x = box.x0 - r; x <= (box.x1 + r); ix++) { - int nb = ix % 4; - double y = (nb == 0 || nb == 1) ? box.y0 - 2 * m : box.y0 - m; - for (int iy = 0; iy < lY; iy++, y += (2 * m)) - v.push_back(TPointD(x, y)); - x = (nb == 0 || nb == 2) ? x + r : x + r / 2.0; - } - lX = ix; + int &lX, int &lY, TRandom &rand) const { + double q = tcrop(m_size, 0.0, 100.0) * 0.01; + double r = 5.0 + (60.0 - 5.0) * q; + double m = r * sqrt(3.0) / 2.0; + lY = 5 + (int)((box.y1 - box.y0) / (2 * m)); + int ix = 0; + for (double x = box.x0 - r; x <= (box.x1 + r); ix++) { + int nb = ix % 4; + double y = (nb == 0 || nb == 1) ? box.y0 - 2 * m : box.y0 - m; + for (int iy = 0; iy < lY; iy++, y += (2 * m)) v.push_back(TPointD(x, y)); + x = (nb == 0 || nb == 2) ? x + r : x + r / 2.0; + } + lX = ix; - double maxDeform = r * 0.6 * tcrop(m_deform, 0.0, 100.0) * 0.01; - for (UINT i = 0; i < v.size(); i++) { - v[i].x += (rand.getInt(0, 200) - 100) * 0.01 * maxDeform; - v[i].y += (rand.getInt(0, 200) - 100) * 0.01 * maxDeform; - } + double maxDeform = r * 0.6 * tcrop(m_deform, 0.0, 100.0) * 0.01; + for (UINT i = 0; i < v.size(); i++) { + v[i].x += (rand.getInt(0, 200) - 100) * 0.01 * maxDeform; + v[i].y += (rand.getInt(0, 200) - 100) * 0.01 * maxDeform; + } } //------------------------------------------------------------ bool TPatchFillStyle::getQuadLine(const TPointD &a, const TPointD &b, - const double thickn, TPointD *quad) const -{ - if (tdistance(a, b) < TConsts::epsilon) - return false; + const double thickn, TPointD *quad) const { + if (tdistance(a, b) < TConsts::epsilon) return false; - TPointD ab(b - a); - ab = normalize(ab); - ab = rotate90(ab); - ab = ab * thickn; + TPointD ab(b - a); + ab = normalize(ab); + ab = rotate90(ab); + ab = ab * thickn; - quad[0] = a + ab; - quad[1] = a - ab; - quad[2] = b - ab; - quad[3] = b + ab; + quad[0] = a + ab; + quad[1] = a - ab; + quad[2] = b - ab; + quad[3] = b + ab; - return true; + return true; } //------------------------------------------------------------ -void TPatchFillStyle::drawGLQuad(const TPointD *quad) const -{ - glBegin(GL_QUADS); - tglVertex(quad[0]); - tglVertex(quad[1]); - tglVertex(quad[2]); - tglVertex(quad[3]); - glEnd(); - double r = tdistance(quad[0], quad[1]) / 2.0; - tglDrawDisk(quad[0] * 0.5 + quad[1] * 0.5, r); - tglDrawDisk(quad[2] * 0.5 + quad[3] * 0.5, r); +void TPatchFillStyle::drawGLQuad(const TPointD *quad) const { + glBegin(GL_QUADS); + tglVertex(quad[0]); + tglVertex(quad[1]); + tglVertex(quad[2]); + tglVertex(quad[3]); + glEnd(); + double r = tdistance(quad[0], quad[1]) / 2.0; + tglDrawDisk(quad[0] * 0.5 + quad[1] * 0.5, r); + tglDrawDisk(quad[2] * 0.5 + quad[3] * 0.5, r); } //------------------------------------------------------------ -void TPatchFillStyle::drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const -{ +void TPatchFillStyle::drawRegion(const TColorFunction *cf, + const bool antiAliasing, + TRegionOutline &boundary) const { + TStencilControl *stenc = TStencilControl::instance(); + TPixel32 backgroundColor = TSolidColorStyle::getMainColor(); + if (cf) backgroundColor = (*(cf))(backgroundColor); - TStencilControl *stenc = TStencilControl::instance(); - TPixel32 backgroundColor = TSolidColorStyle::getMainColor(); - if (cf) - backgroundColor = (*(cf))(backgroundColor); - - if (backgroundColor.m == 0) { //only to create stencil mask - TSolidColorStyle appStyle(TPixel32::White); - stenc->beginMask(); //does not draw on screen - appStyle.drawRegion(0, false, boundary); - } else { //create stencil mask and draw on screen - stenc->beginMask(TStencilControl::DRAW_ALSO_ON_SCREEN); - TSolidColorStyle::drawRegion(cf, antiAliasing, boundary); - } - stenc->endMask(); - stenc->enableMask(TStencilControl::SHOW_INSIDE); - - //glEnable(GL_BLEND); - //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - //// <-- tglEnableBlending(); - - TPixel32 color[6]; - for (int i = 0; i < 6; i++) - if (cf) - color[i] = (*(cf))(m_pointColor[i]); - else - color[i] = m_pointColor[i]; - - TPixel32 currentColor; - - std::vector pos; - int posLX, posLY; - TRandom rand; - TPointD quad[4]; - - preaprePos(boundary.m_bbox, pos, posLX, posLY, rand); - glBegin(GL_TRIANGLES); - int x = 2; - for (; x < (posLX - 2); x += 2) - for (int y = 1; y < posLY; y++) { - TPointD q[6]; - if ((x % 4) == 2) { - q[0] = pos[(x - 1) * posLY + y]; - q[1] = pos[(x)*posLY + y]; - q[2] = pos[(x + 1) * posLY + y]; - q[3] = pos[(x + 2) * posLY + y]; - q[4] = pos[(x + 1) * posLY + y - 1]; - q[5] = pos[(x)*posLY + y - 1]; - } else { - q[0] = pos[(x - 1) * posLY + y - 1]; - q[1] = pos[(x)*posLY + y - 1]; - q[2] = pos[(x + 1) * posLY + y - 1]; - q[3] = pos[(x + 2) * posLY + y - 1]; - q[4] = pos[(x + 1) * posLY + y]; - q[5] = pos[(x)*posLY + y]; - } - - currentColor = color[rand.getInt(0, 6)]; - if (currentColor.m != 0) { - tglColor(currentColor); - - tglVertex(q[0]); - tglVertex(q[1]); - tglVertex(q[2]); - - tglVertex(q[2]); - tglVertex(q[3]); - tglVertex(q[4]); - - tglVertex(q[4]); - tglVertex(q[5]); - tglVertex(q[0]); - - tglVertex(q[0]); - tglVertex(q[2]); - tglVertex(q[4]); - } - } - glEnd(); - - double thickn = tcrop(m_thickness, 0.0, 100.0) * 0.01 * 5.0; - if (thickn > 0.001) - tglColor(backgroundColor); - for (x = 0; x < (posLX - 1); x++) { - int nb = x % 4; - for (int y = 0; y < posLY; y++) { - if (getQuadLine(pos[x * posLY + y], pos[(x + 1) * posLY + y], thickn, quad)) - drawGLQuad(quad); - if (y > 0 && nb == 1) - if (getQuadLine(pos[x * posLY + y], pos[(x + 1) * posLY + y - 1], thickn, quad)) - drawGLQuad(quad); - if (y < (posLY - 1) && nb == 3) - if (getQuadLine(pos[x * posLY + y], pos[(x + 1) * posLY + y + 1], thickn, quad)) - drawGLQuad(quad); - } - } - - //tglColor(TPixel32::White); - - stenc->disableMask(); -} - -//------------------------------------------------------------ - -int TPatchFillStyle::nbClip(const int lX, const int lY, const std::vector &v) const -{ - TPointD quad[4]; - double thickn = tcrop(m_thickness, 0.0, 100.0) * 0.01 * 5.0; - int nbC = 0; - int x = 2; - for (; x < (lX - 2); x += 2) - for (int y = 1; y < lY; y++) - nbC += 1; - if (thickn > 0.001) - for (x = 0; x < (lX - 1); x++) { - int nb = x % 4; - for (int y = 0; y < lY; y++) { - if (getQuadLine(v[x * lY + y], v[(x + 1) * lY + y], thickn, quad)) - nbC += 3; - if (y > 0 && nb == 1) - if (getQuadLine(v[x * lY + y], v[(x + 1) * lY + y - 1], thickn, quad)) - nbC += 3; - if (y < (lY - 1) && nb == 3) - if (getQuadLine(v[x * lY + y], v[(x + 1) * lY + y + 1], thickn, quad)) - nbC += 3; - } - } - return nbC; -} - -//------------------------------------------------------------ - -void TPatchFillStyle::drawFlashQuad(TFlash &flash, const TPointD *quad) const -{ - std::vector lvert; - lvert.push_back(quad[0]); - lvert.push_back(quad[1]); - lvert.push_back(quad[2]); - lvert.push_back(quad[3]); - flash.drawPolyline(lvert); + if (backgroundColor.m == 0) { // only to create stencil mask + TSolidColorStyle appStyle(TPixel32::White); + stenc->beginMask(); // does not draw on screen + appStyle.drawRegion(0, false, boundary); + } else { // create stencil mask and draw on screen + stenc->beginMask(TStencilControl::DRAW_ALSO_ON_SCREEN); + TSolidColorStyle::drawRegion(cf, antiAliasing, boundary); + } + stenc->endMask(); + stenc->enableMask(TStencilControl::SHOW_INSIDE); + + // glEnable(GL_BLEND); + // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + //// <-- tglEnableBlending(); + + TPixel32 color[6]; + for (int i = 0; i < 6; i++) + if (cf) + color[i] = (*(cf))(m_pointColor[i]); + else + color[i] = m_pointColor[i]; + + TPixel32 currentColor; + + std::vector pos; + int posLX, posLY; + TRandom rand; + TPointD quad[4]; + + preaprePos(boundary.m_bbox, pos, posLX, posLY, rand); + glBegin(GL_TRIANGLES); + int x = 2; + for (; x < (posLX - 2); x += 2) + for (int y = 1; y < posLY; y++) { + TPointD q[6]; + if ((x % 4) == 2) { + q[0] = pos[(x - 1) * posLY + y]; + q[1] = pos[(x)*posLY + y]; + q[2] = pos[(x + 1) * posLY + y]; + q[3] = pos[(x + 2) * posLY + y]; + q[4] = pos[(x + 1) * posLY + y - 1]; + q[5] = pos[(x)*posLY + y - 1]; + } else { + q[0] = pos[(x - 1) * posLY + y - 1]; + q[1] = pos[(x)*posLY + y - 1]; + q[2] = pos[(x + 1) * posLY + y - 1]; + q[3] = pos[(x + 2) * posLY + y - 1]; + q[4] = pos[(x + 1) * posLY + y]; + q[5] = pos[(x)*posLY + y]; + } + + currentColor = color[rand.getInt(0, 6)]; + if (currentColor.m != 0) { + tglColor(currentColor); + + tglVertex(q[0]); + tglVertex(q[1]); + tglVertex(q[2]); + + tglVertex(q[2]); + tglVertex(q[3]); + tglVertex(q[4]); + + tglVertex(q[4]); + tglVertex(q[5]); + tglVertex(q[0]); + + tglVertex(q[0]); + tglVertex(q[2]); + tglVertex(q[4]); + } + } + glEnd(); + + double thickn = tcrop(m_thickness, 0.0, 100.0) * 0.01 * 5.0; + if (thickn > 0.001) tglColor(backgroundColor); + for (x = 0; x < (posLX - 1); x++) { + int nb = x % 4; + for (int y = 0; y < posLY; y++) { + if (getQuadLine(pos[x * posLY + y], pos[(x + 1) * posLY + y], thickn, + quad)) + drawGLQuad(quad); + if (y > 0 && nb == 1) + if (getQuadLine(pos[x * posLY + y], pos[(x + 1) * posLY + y - 1], + thickn, quad)) + drawGLQuad(quad); + if (y < (posLY - 1) && nb == 3) + if (getQuadLine(pos[x * posLY + y], pos[(x + 1) * posLY + y + 1], + thickn, quad)) + drawGLQuad(quad); + } + } - double r = tdistance(quad[0], quad[1]) / 2.0; - flash.drawEllipse(quad[0] * 0.5 + quad[1] * 0.5, r, r); - flash.drawEllipse(quad[2] * 0.5 + quad[3] * 0.5, r, r); + // tglColor(TPixel32::White); + + stenc->disableMask(); +} + +//------------------------------------------------------------ + +int TPatchFillStyle::nbClip(const int lX, const int lY, + const std::vector &v) const { + TPointD quad[4]; + double thickn = tcrop(m_thickness, 0.0, 100.0) * 0.01 * 5.0; + int nbC = 0; + int x = 2; + for (; x < (lX - 2); x += 2) + for (int y = 1; y < lY; y++) nbC += 1; + if (thickn > 0.001) + for (x = 0; x < (lX - 1); x++) { + int nb = x % 4; + for (int y = 0; y < lY; y++) { + if (getQuadLine(v[x * lY + y], v[(x + 1) * lY + y], thickn, quad)) + nbC += 3; + if (y > 0 && nb == 1) + if (getQuadLine(v[x * lY + y], v[(x + 1) * lY + y - 1], thickn, quad)) + nbC += 3; + if (y < (lY - 1) && nb == 3) + if (getQuadLine(v[x * lY + y], v[(x + 1) * lY + y + 1], thickn, quad)) + nbC += 3; + } + } + return nbC; } //------------------------------------------------------------ -void TPatchFillStyle::drawFlashTriangle(TFlash &flash, - const TPointD &p1, - const TPointD &p2, - const TPointD &p3) const -{ - std::vector lvert; - lvert.push_back(p1); - lvert.push_back(p2); - lvert.push_back(p3); - flash.drawPolyline(lvert); +void TPatchFillStyle::drawFlashQuad(TFlash &flash, const TPointD *quad) const { + std::vector lvert; + lvert.push_back(quad[0]); + lvert.push_back(quad[1]); + lvert.push_back(quad[2]); + lvert.push_back(quad[3]); + flash.drawPolyline(lvert); + + double r = tdistance(quad[0], quad[1]) / 2.0; + flash.drawEllipse(quad[0] * 0.5 + quad[1] * 0.5, r, r); + flash.drawEllipse(quad[2] * 0.5 + quad[3] * 0.5, r, r); } //------------------------------------------------------------ -void TPatchFillStyle::drawRegion(TFlash &flash, const TRegion *r) const -{ +void TPatchFillStyle::drawFlashTriangle(TFlash &flash, const TPointD &p1, + const TPointD &p2, + const TPointD &p3) const { + std::vector lvert; + lvert.push_back(p1); + lvert.push_back(p2); + lvert.push_back(p3); + flash.drawPolyline(lvert); +} + +//------------------------------------------------------------ + +void TPatchFillStyle::drawRegion(TFlash &flash, const TRegion *r) const { + TRectD bbox(r->getBBox()); + + std::vector pos; + int posLX, posLY; + TRandom rand; + TPointD quad[4]; + + preaprePos(bbox, pos, posLX, posLY, rand); + if (pos.size() <= 0) return; + flash.drawRegion(*r, nbClip(posLX, posLY, pos)); + + flash.setThickness(0.0); + int x; + for (x = 2; x < (posLX - 2); x += 2) + for (int y = 1; y < posLY; y++) { + std::vector lvert; + if ((x % 4) == 2) { + lvert.push_back(pos[(x - 1) * posLY + y]); + lvert.push_back(pos[(x)*posLY + y]); + lvert.push_back(pos[(x + 1) * posLY + y]); + lvert.push_back(pos[(x + 2) * posLY + y]); + lvert.push_back(pos[(x + 1) * posLY + y - 1]); + lvert.push_back(pos[(x)*posLY + y - 1]); + } else { + lvert.push_back(pos[(x - 1) * posLY + y - 1]); + lvert.push_back(pos[(x)*posLY + y - 1]); + lvert.push_back(pos[(x + 1) * posLY + y - 1]); + lvert.push_back(pos[(x + 2) * posLY + y - 1]); + lvert.push_back(pos[(x + 1) * posLY + y]); + lvert.push_back(pos[(x)*posLY + y]); + } + flash.setFillColor(m_pointColor[rand.getInt(0, 6)]); + flash.drawPolyline(lvert); + } - TRectD bbox(r->getBBox()); - - std::vector pos; - int posLX, posLY; - TRandom rand; - TPointD quad[4]; - - preaprePos(bbox, pos, posLX, posLY, rand); - if (pos.size() <= 0) - return; - flash.drawRegion(*r, nbClip(posLX, posLY, pos)); - - flash.setThickness(0.0); - int x; - for (x = 2; x < (posLX - 2); x += 2) - for (int y = 1; y < posLY; y++) { - std::vector lvert; - if ((x % 4) == 2) { - lvert.push_back(pos[(x - 1) * posLY + y]); - lvert.push_back(pos[(x)*posLY + y]); - lvert.push_back(pos[(x + 1) * posLY + y]); - lvert.push_back(pos[(x + 2) * posLY + y]); - lvert.push_back(pos[(x + 1) * posLY + y - 1]); - lvert.push_back(pos[(x)*posLY + y - 1]); - } else { - lvert.push_back(pos[(x - 1) * posLY + y - 1]); - lvert.push_back(pos[(x)*posLY + y - 1]); - lvert.push_back(pos[(x + 1) * posLY + y - 1]); - lvert.push_back(pos[(x + 2) * posLY + y - 1]); - lvert.push_back(pos[(x + 1) * posLY + y]); - lvert.push_back(pos[(x)*posLY + y]); - } - flash.setFillColor(m_pointColor[rand.getInt(0, 6)]); - flash.drawPolyline(lvert); - } - - flash.setFillColor(TSolidColorStyle::getMainColor()); - flash.setThickness(0.0); - double thickn = tcrop(m_thickness, 0.0, 100.0) * 0.01 * 5.0; - if (thickn > 0.001) - for (x = 0; x < (posLX - 1); x++) { - int nb = x % 4; - for (int y = 0; y < posLY; y++) { - if (getQuadLine(pos[x * posLY + y], pos[(x + 1) * posLY + y], thickn, quad)) - drawFlashQuad(flash, quad); - if (y > 0 && nb == 1) - if (getQuadLine(pos[x * posLY + y], pos[(x + 1) * posLY + y - 1], thickn, quad)) - drawFlashQuad(flash, quad); - if (y < (posLY - 1) && nb == 3) - if (getQuadLine(pos[x * posLY + y], pos[(x + 1) * posLY + y + 1], thickn, quad)) - drawFlashQuad(flash, quad); - } - } + flash.setFillColor(TSolidColorStyle::getMainColor()); + flash.setThickness(0.0); + double thickn = tcrop(m_thickness, 0.0, 100.0) * 0.01 * 5.0; + if (thickn > 0.001) + for (x = 0; x < (posLX - 1); x++) { + int nb = x % 4; + for (int y = 0; y < posLY; y++) { + if (getQuadLine(pos[x * posLY + y], pos[(x + 1) * posLY + y], thickn, + quad)) + drawFlashQuad(flash, quad); + if (y > 0 && nb == 1) + if (getQuadLine(pos[x * posLY + y], pos[(x + 1) * posLY + y - 1], + thickn, quad)) + drawFlashQuad(flash, quad); + if (y < (posLY - 1) && nb == 3) + if (getQuadLine(pos[x * posLY + y], pos[(x + 1) * posLY + y + 1], + thickn, quad)) + drawFlashQuad(flash, quad); + } + } } diff --git a/toonz/sources/colorfx/regionstyles.h b/toonz/sources/colorfx/regionstyles.h index 3df1f37..601b03d 100644 --- a/toonz/sources/colorfx/regionstyles.h +++ b/toonz/sources/colorfx/regionstyles.h @@ -29,886 +29,886 @@ class TRandom; //============================================================ -class MovingModifier : public TOutlineStyle::RegionOutlineModifier -{ - TPointD m_move; +class MovingModifier : public TOutlineStyle::RegionOutlineModifier { + TPointD m_move; public: - MovingModifier(const TPointD &point) - : m_move(point) {} + MovingModifier(const TPointD &point) : m_move(point) {} - TOutlineStyle::RegionOutlineModifier *clone() const; + TOutlineStyle::RegionOutlineModifier *clone() const; - TPointD getMovePoint() const { return m_move; } + TPointD getMovePoint() const { return m_move; } - void modify(TRegionOutline &outline) const; + void modify(TRegionOutline &outline) const; public: - void loadData(TInputStreamInterface &is) - { - is >> m_move.x >> m_move.y; - } - - void saveData(TOutputStreamInterface &os) const - { - os << m_move.x << m_move.y; - } + void loadData(TInputStreamInterface &is) { is >> m_move.x >> m_move.y; } + + void saveData(TOutputStreamInterface &os) const { + os << m_move.x << m_move.y; + } }; //============================================================ -class MovingSolidColor : public TSolidColorStyle -{ +class MovingSolidColor : public TSolidColorStyle { public: - MovingSolidColor(const TPixel32 &color, const TPointD &move); + MovingSolidColor(const TPixel32 &color, const TPointD &move); - TColorStyle *clone() const; + TColorStyle *clone() const; - bool isRegionStyle() const { return true; } - bool isStrokeStyle() const { return false; } + bool isRegionStyle() const { return true; } + bool isStrokeStyle() const { return false; } - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); - int getTagId() const { return 1125; }; - QString getDescription() const { return QCoreApplication::translate("MovingSolidColor", "Offset"); } + int getTagId() const { return 1125; }; + QString getDescription() const { + return QCoreApplication::translate("MovingSolidColor", "Offset"); + } - void drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const; - void drawRegion(TFlash &flash, const TRegion *r) const; + void drawRegion(const TColorFunction *cf, const bool antiAliasing, + TRegionOutline &boundary) const; + void drawRegion(TFlash &flash, const TRegion *r) const; protected: - void loadData(TInputStreamInterface &is); - void saveData(TOutputStreamInterface &os) const; + void loadData(TInputStreamInterface &is); + void saveData(TOutputStreamInterface &os) const; }; //============================================================ -class DVAPI ShadowStyle : public TSolidColorStyle -{ - TPointD m_shadowDirection; - TPixel32 m_shadowColor; - double m_density; - double m_len; +class DVAPI ShadowStyle : public TSolidColorStyle { + TPointD m_shadowDirection; + TPixel32 m_shadowColor; + double m_density; + double m_len; public: - ShadowStyle( - const TPixel32 &bgColor, - const TPixel32 &shadowColor, - const TPointD &shadowDirection = TPointD(-1, -1), - double len = 30.0, - double density = 0.4); + ShadowStyle(const TPixel32 &bgColor, const TPixel32 &shadowColor, + const TPointD &shadowDirection = TPointD(-1, -1), + double len = 30.0, double density = 0.4); - TColorStyle *clone() const; + TColorStyle *clone() const; - void makeIcon(const TDimension &d); - bool isRegionStyle() const { return true; } - bool isStrokeStyle() const { return false; } + void makeIcon(const TDimension &d); + bool isRegionStyle() const { return true; } + bool isStrokeStyle() const { return false; } - //TPixel32 getMainColor() const {return m_shadowColor; } - //void setMainColor(const TPixel32 &color){ m_shadowColor=color; } + // TPixel32 getMainColor() const {return m_shadowColor; } + // void setMainColor(const TPixel32 &color){ m_shadowColor=color; } - int getColorParamCount() const { return 2; } - TPixel32 getColorParamValue(int index) const; - void setColorParamValue(int index, const TPixel32 &color); + int getColorParamCount() const { return 2; } + TPixel32 getColorParamValue(int index) const; + void setColorParamValue(int index, const TPixel32 &color); - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); - int getTagId() const { return 1127; }; - QString getDescription() const { return QCoreApplication::translate("ShadowStyle", "Hatched Shading"); } + int getTagId() const { return 1127; }; + QString getDescription() const { + return QCoreApplication::translate("ShadowStyle", "Hatched Shading"); + } - void drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const; + void drawRegion(const TColorFunction *cf, const bool antiAliasing, + TRegionOutline &boundary) const; - //it is too slow and if the region is too complex, some flash readers (IExplorer) crash. - // So it's better drawing it as a normal solid color - //void drawRegion( TFlash& flash, const TRegion* r) const; + // it is too slow and if the region is too complex, some flash readers + // (IExplorer) crash. + // So it's better drawing it as a normal solid color + // void drawRegion( TFlash& flash, const TRegion* r) const; protected: - void loadData(TInputStreamInterface &is); - void saveData(TOutputStreamInterface &os) const; + void loadData(TInputStreamInterface &is); + void saveData(TOutputStreamInterface &os) const; private: - void drawPolyline(const TColorFunction *cf, std::vector &polyline, TPointD shadowDirection) const; + void drawPolyline(const TColorFunction *cf, std::vector &polyline, + TPointD shadowDirection) const; }; //============================================================ -class DVAPI ShadowStyle2 : public TSolidColorStyle -{ - TPointD m_shadowDirection; - TPixel32 m_shadowColor; - double m_shadowLength; +class DVAPI ShadowStyle2 : public TSolidColorStyle { + TPointD m_shadowDirection; + TPixel32 m_shadowColor; + double m_shadowLength; public: - ShadowStyle2( - const TPixel32 &bgColor, - const TPixel32 &shadowColor, - const TPointD &shadowDirection = TPointD(-1, -1), - double shadowLength = 70.0); + ShadowStyle2(const TPixel32 &bgColor, const TPixel32 &shadowColor, + const TPointD &shadowDirection = TPointD(-1, -1), + double shadowLength = 70.0); - TColorStyle *clone() const; + TColorStyle *clone() const; - bool isRegionStyle() const { return true; } - bool isStrokeStyle() const { return false; } + bool isRegionStyle() const { return true; } + bool isStrokeStyle() const { return false; } - //TPixel32 getMainColor() const {return m_shadowColor; } - //void setMainColor(const TPixel32 &color){ m_shadowColor=color; } + // TPixel32 getMainColor() const {return m_shadowColor; } + // void setMainColor(const TPixel32 &color){ m_shadowColor=color; } - int getColorParamCount() const { return 2; } - TPixel32 getColorParamValue(int index) const; - void setColorParamValue(int index, const TPixel32 &color); + int getColorParamCount() const { return 2; } + TPixel32 getColorParamValue(int index) const; + void setColorParamValue(int index, const TPixel32 &color); - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); - int getTagId() const { return 1135; }; - QString getDescription() const { return QCoreApplication::translate("ShadowStyle2", "Plain Shadow"); } + int getTagId() const { return 1135; }; + QString getDescription() const { + return QCoreApplication::translate("ShadowStyle2", "Plain Shadow"); + } - void drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const; - void drawRegion(TFlash &flash, const TRegion *r) const; + void drawRegion(const TColorFunction *cf, const bool antiAliasing, + TRegionOutline &boundary) const; + void drawRegion(TFlash &flash, const TRegion *r) const; protected: - void loadData(TInputStreamInterface &is); - void saveData(TOutputStreamInterface &os) const; + void loadData(TInputStreamInterface &is); + void saveData(TOutputStreamInterface &os) const; private: - void drawPolyline(const TColorFunction *cf, const std::vector &polyline, TPointD shadowDirection) const; - int drawPolyline(TFlash &flash, std::vector &polyline, - TPointD shadowDirection, const bool isDraw = true) const; + void drawPolyline(const TColorFunction *cf, + const std::vector &polyline, + TPointD shadowDirection) const; + int drawPolyline(TFlash &flash, std::vector &polyline, + TPointD shadowDirection, const bool isDraw = true) const; }; //============================================================ -class RubberModifier : public TOutlineStyle::RegionOutlineModifier -{ - double m_deform; +class RubberModifier : public TOutlineStyle::RegionOutlineModifier { + double m_deform; public: - RubberModifier(double deform) - : m_deform(deform) {} + RubberModifier(double deform) : m_deform(deform) {} - void loadData(TInputStreamInterface &is) - { - is >> m_deform; - } - void saveData(TOutputStreamInterface &os) const - { - os << m_deform; - } + void loadData(TInputStreamInterface &is) { is >> m_deform; } + void saveData(TOutputStreamInterface &os) const { os << m_deform; } - double getDeform() { return m_deform; } - void setDeform(const double deform) { m_deform = deform; } + double getDeform() { return m_deform; } + void setDeform(const double deform) { m_deform = deform; } - void modify(TRegionOutline &outline) const; + void modify(TRegionOutline &outline) const; - TOutlineStyle::RegionOutlineModifier *clone() const; + TOutlineStyle::RegionOutlineModifier *clone() const; }; //============================================================ -class DVAPI TRubberFillStyle : public TSolidColorStyle -{ - typedef std::vector QuadraticVector; - typedef std::vector QuadraticPVector; +class DVAPI TRubberFillStyle : public TSolidColorStyle { + typedef std::vector QuadraticVector; + typedef std::vector QuadraticPVector; public: - TRubberFillStyle(const TPixel32 &color, double deform); + TRubberFillStyle(const TPixel32 &color, double deform); - TColorStyle *clone() const; + TColorStyle *clone() const; - bool isRegionStyle() const { return true; } - bool isStrokeStyle() const { return false; } + bool isRegionStyle() const { return true; } + bool isStrokeStyle() const { return false; } - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); - void makeIcon(const TDimension &d); + void makeIcon(const TDimension &d); - int getTagId() const { return 1128; }; - QString getDescription() const { return QCoreApplication::translate("TRubberFillStyle", "Blob"); } + int getTagId() const { return 1128; }; + QString getDescription() const { + return QCoreApplication::translate("TRubberFillStyle", "Blob"); + } - void drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const; - void drawRegion(TFlash &flash, const TRegion *r) const; + void drawRegion(const TColorFunction *cf, const bool antiAliasing, + TRegionOutline &boundary) const; + void drawRegion(TFlash &flash, const TRegion *r) const; protected: - void loadData(TInputStreamInterface &is); - void saveData(TOutputStreamInterface &os) const; + void loadData(TInputStreamInterface &is); + void saveData(TOutputStreamInterface &os) const; private: - void transformPolylines(); + void transformPolylines(); }; //============================================================ -class DVAPI TPointShadowFillStyle : public TSolidColorStyle -{ - TPointD m_shadowDirection; - TPixel32 m_shadowColor; - double m_shadowSize; - double m_density; - double m_pointSize; +class DVAPI TPointShadowFillStyle : public TSolidColorStyle { + TPointD m_shadowDirection; + TPixel32 m_shadowColor; + double m_shadowSize; + double m_density; + double m_pointSize; public: - TPointShadowFillStyle(const TPixel32 &bgColor, - const TPixel32 &shadowColor, - const TPointD &shadowDirection = TPointD(-1, -1), - double density = 0.1, - double shadowSize = 30.0, - double pointSize = 5.0); + TPointShadowFillStyle(const TPixel32 &bgColor, const TPixel32 &shadowColor, + const TPointD &shadowDirection = TPointD(-1, -1), + double density = 0.1, double shadowSize = 30.0, + double pointSize = 5.0); - TColorStyle *clone() const; + TColorStyle *clone() const; - bool isRegionStyle() const { return true; } - bool isStrokeStyle() const { return false; } + bool isRegionStyle() const { return true; } + bool isStrokeStyle() const { return false; } - /* - TPixel32 getMainColor() const {return m_shadowColor; } - void setMainColor(const TPixel32 &color){ m_shadowColor=color; } - */ + /* +TPixel32 getMainColor() const {return m_shadowColor; } +void setMainColor(const TPixel32 &color){ m_shadowColor=color; } +*/ - int getColorParamCount() const { return 2; } - TPixel32 getColorParamValue(int index) const; - void setColorParamValue(int index, const TPixel32 &color); + int getColorParamCount() const { return 2; } + TPixel32 getColorParamValue(int index) const; + void setColorParamValue(int index, const TPixel32 &color); - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); - int getTagId() const { return 1129; }; - QString getDescription() const { return QCoreApplication::translate("TPointShadowFillStyle", "Sponge Shading"); } + int getTagId() const { return 1129; }; + QString getDescription() const { + return QCoreApplication::translate("TPointShadowFillStyle", + "Sponge Shading"); + } - void drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const; - void drawRegion(TFlash &flash, const TRegion *r) const; + void drawRegion(const TColorFunction *cf, const bool antiAliasing, + TRegionOutline &boundary) const; + void drawRegion(TFlash &flash, const TRegion *r) const; protected: - void loadData(TInputStreamInterface &is); - void saveData(TOutputStreamInterface &os) const; + void loadData(TInputStreamInterface &is); + void saveData(TOutputStreamInterface &os) const; private: - double triangleArea(const TPointD &a, const TPointD &b, const TPointD &c) const; - void shadowOnEdge_parallel(const TPointD &p0, const TPointD &p1, - const TPointD &p2, TRandom &rnd) const; - int shadowOnEdge_parallel(TFlash &flash, - const TPointD &p0, const TPointD &p1, - const TPointD &p2, TRandom &rnd, - const double radius, - const bool isDraw) const; - - void deleteSameVerts(TRegionOutline::Boundary::iterator &rit, - std::vector &pv) const; + double triangleArea(const TPointD &a, const TPointD &b, + const TPointD &c) const; + void shadowOnEdge_parallel(const TPointD &p0, const TPointD &p1, + const TPointD &p2, TRandom &rnd) const; + int shadowOnEdge_parallel(TFlash &flash, const TPointD &p0, const TPointD &p1, + const TPointD &p2, TRandom &rnd, + const double radius, const bool isDraw) const; + + void deleteSameVerts(TRegionOutline::Boundary::iterator &rit, + std::vector &pv) const; }; //============================================================ -class DVAPI TDottedFillStyle : public TSolidColorStyle -{ - TPixel32 m_pointColor; - double m_dotSize; - double m_dotDist; - bool m_isShifted; +class DVAPI TDottedFillStyle : public TSolidColorStyle { + TPixel32 m_pointColor; + double m_dotSize; + double m_dotDist; + bool m_isShifted; public: - TDottedFillStyle(const TPixel32 &bgColor, - const TPixel32 &pointColor, - const double dotSize, - const double dotDist, - const bool isShifted); + TDottedFillStyle(const TPixel32 &bgColor, const TPixel32 &pointColor, + const double dotSize, const double dotDist, + const bool isShifted); - TDottedFillStyle(const TPixel32 &color); + TDottedFillStyle(const TPixel32 &color); - TColorStyle *clone() const; + TColorStyle *clone() const; - /* - TPixel32 getMainColor() const {return m_pointColor; } - void setMainColor(const TPixel32 &color){ m_pointColor=color; } - */ + /* +TPixel32 getMainColor() const {return m_pointColor; } +void setMainColor(const TPixel32 &color){ m_pointColor=color; } +*/ - int getColorParamCount() const { return 2; } - TPixel32 getColorParamValue(int index) const; - void setColorParamValue(int index, const TPixel32 &color); + int getColorParamCount() const { return 2; } + TPixel32 getColorParamValue(int index) const; + void setColorParamValue(int index, const TPixel32 &color); - bool isRegionStyle() const { return true; } - bool isStrokeStyle() const { return false; } + bool isRegionStyle() const { return true; } + bool isStrokeStyle() const { return false; } - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); - void drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const; - void drawRegion(TFlash &flash, const TRegion *r) const; + void drawRegion(const TColorFunction *cf, const bool antiAliasing, + TRegionOutline &boundary) const; + void drawRegion(TFlash &flash, const TRegion *r) const; - int getTagId() const { return 1130; }; - QString getDescription() const { return QCoreApplication::translate("TDottedFillStyle", "Polka Dots"); } + int getTagId() const { return 1130; }; + QString getDescription() const { + return QCoreApplication::translate("TDottedFillStyle", "Polka Dots"); + } protected: - void loadData(TInputStreamInterface &is); - void saveData(TOutputStreamInterface &os) const; + void loadData(TInputStreamInterface &is); + void saveData(TOutputStreamInterface &os) const; private: - int nbClip(const double LDotDist, const bool LIsShifted, - const TRectD &bbox) const; + int nbClip(const double LDotDist, const bool LIsShifted, + const TRectD &bbox) const; }; //============================================================ -class DVAPI TCheckedFillStyle : public TSolidColorStyle -{ - TPixel32 m_pointColor; - double m_HDist, m_HAngle; - double m_VDist, m_VAngle, m_Thickness; +class DVAPI TCheckedFillStyle : public TSolidColorStyle { + TPixel32 m_pointColor; + double m_HDist, m_HAngle; + double m_VDist, m_VAngle, m_Thickness; public: - TCheckedFillStyle(const TPixel32 &bgColor, const TPixel32 &pointColor, - const double HDist, const double HAngle, - const double VDist, const double VAngle, const double Thickness); + TCheckedFillStyle(const TPixel32 &bgColor, const TPixel32 &pointColor, + const double HDist, const double HAngle, const double VDist, + const double VAngle, const double Thickness); - TCheckedFillStyle(const TPixel32 &color); + TCheckedFillStyle(const TPixel32 &color); - TColorStyle *clone() const; + TColorStyle *clone() const; - /* - TPixel32 getMainColor() const {return m_pointColor; } - void setMainColor(const TPixel32 &color){ m_pointColor=color; } - */ + /* +TPixel32 getMainColor() const {return m_pointColor; } +void setMainColor(const TPixel32 &color){ m_pointColor=color; } +*/ - int getColorParamCount() const { return 2; } - TPixel32 getColorParamValue(int index) const; - void setColorParamValue(int index, const TPixel32 &color); + int getColorParamCount() const { return 2; } + TPixel32 getColorParamValue(int index) const; + void setColorParamValue(int index, const TPixel32 &color); - bool isRegionStyle() const { return true; } - bool isStrokeStyle() const { return false; } + bool isRegionStyle() const { return true; } + bool isStrokeStyle() const { return false; } - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); - void drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const; - void drawRegion(TFlash &flash, const TRegion *r) const; + void drawRegion(const TColorFunction *cf, const bool antiAliasing, + TRegionOutline &boundary) const; + void drawRegion(TFlash &flash, const TRegion *r) const; - int getTagId() const { return 1131; }; - QString getDescription() const { return QCoreApplication::translate("TCheckedFillStyle", "Square"); } + int getTagId() const { return 1131; }; + QString getDescription() const { + return QCoreApplication::translate("TCheckedFillStyle", "Square"); + } private: - void getHThickline(const TPointD &lc, const double lx, - TPointD &p0, TPointD &p1, - TPointD &p2, TPointD &p3) const; - void getVThickline(const TPointD &lc, const double ly, - TPointD &p0, TPointD &p1, - TPointD &p2, TPointD &p3) const; - int nbClip(const TRectD &bbox) const; + void getHThickline(const TPointD &lc, const double lx, TPointD &p0, + TPointD &p1, TPointD &p2, TPointD &p3) const; + void getVThickline(const TPointD &lc, const double ly, TPointD &p0, + TPointD &p1, TPointD &p2, TPointD &p3) const; + int nbClip(const TRectD &bbox) const; protected: - void loadData(TInputStreamInterface &is); - void saveData(TOutputStreamInterface &os) const; + void loadData(TInputStreamInterface &is); + void saveData(TOutputStreamInterface &os) const; }; //============================================================ -class ArtisticModifier : public TOutlineStyle::RegionOutlineModifier -{ - TPointD m_move; - double m_period; +class ArtisticModifier : public TOutlineStyle::RegionOutlineModifier { + TPointD m_move; + double m_period; public: - ArtisticModifier(const TPointD &point, double period) - : m_move(point), m_period(period) {} + ArtisticModifier(const TPointD &point, double period) + : m_move(point), m_period(period) {} - TOutlineStyle::RegionOutlineModifier *clone() const; + TOutlineStyle::RegionOutlineModifier *clone() const; - void loadData(TInputStreamInterface &is) - { - is >> m_move.x >> m_move.y >> m_period; - } - void saveData(TOutputStreamInterface &os) const - { - os << m_move.x << m_move.y << m_period; - } + void loadData(TInputStreamInterface &is) { + is >> m_move.x >> m_move.y >> m_period; + } + void saveData(TOutputStreamInterface &os) const { + os << m_move.x << m_move.y << m_period; + } - TPointD getMovePoint() const { return m_move; } - double getPeriod() const { return m_period; } + TPointD getMovePoint() const { return m_move; } + double getPeriod() const { return m_period; } - void modify(TRegionOutline &outline) const; + void modify(TRegionOutline &outline) const; }; //============================================================ -class ArtisticSolidColor : public TSolidColorStyle -{ +class ArtisticSolidColor : public TSolidColorStyle { public: - ArtisticSolidColor(const TPixel32 &color, const TPointD &move, double period); + ArtisticSolidColor(const TPixel32 &color, const TPointD &move, double period); - TColorStyle *clone() const; + TColorStyle *clone() const; - bool isRegionStyle() const { return true; } - bool isStrokeStyle() const { return false; } + bool isRegionStyle() const { return true; } + bool isStrokeStyle() const { return false; } - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); - int getTagId() const { return 1132; }; - QString getDescription() const { return QCoreApplication::translate("ArtisticSolidColor", "Irregular"); } + int getTagId() const { return 1132; }; + QString getDescription() const { + return QCoreApplication::translate("ArtisticSolidColor", "Irregular"); + } - void drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const; - void drawRegion(TFlash &flash, const TRegion *r) const; + void drawRegion(const TColorFunction *cf, const bool antiAliasing, + TRegionOutline &boundary) const; + void drawRegion(TFlash &flash, const TRegion *r) const; protected: - void loadData(TInputStreamInterface &is); - void saveData(TOutputStreamInterface &os) const; + void loadData(TInputStreamInterface &is); + void saveData(TOutputStreamInterface &os) const; }; //============================================================ -class DVAPI TChalkFillStyle : public TSolidColorStyle -{ - TPixel32 m_color0; - double m_density, m_size; +class DVAPI TChalkFillStyle : public TSolidColorStyle { + TPixel32 m_color0; + double m_density, m_size; public: - TChalkFillStyle(const TPixel32 &color0, const TPixel32 &color1, - const double density, const double size); - TChalkFillStyle(const TPixel32 &color0, const TPixel32 &color1); + TChalkFillStyle(const TPixel32 &color0, const TPixel32 &color1, + const double density, const double size); + TChalkFillStyle(const TPixel32 &color0, const TPixel32 &color1); - TColorStyle *clone() const; + TColorStyle *clone() const; - /* - TPixel32 getMainColor() const {return m_color0; } - void setMainColor(const TPixel32 &color){ m_color0=color; } - */ + /* +TPixel32 getMainColor() const {return m_color0; } +void setMainColor(const TPixel32 &color){ m_color0=color; } +*/ - int getColorParamCount() const { return 2; } - TPixel32 getColorParamValue(int index) const; - void setColorParamValue(int index, const TPixel32 &color); + int getColorParamCount() const { return 2; } + TPixel32 getColorParamValue(int index) const; + void setColorParamValue(int index, const TPixel32 &color); - bool isRegionStyle() const { return true; } - bool isStrokeStyle() const { return false; } + bool isRegionStyle() const { return true; } + bool isStrokeStyle() const { return false; } - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); - void drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const; - void drawRegion(TFlash &flash, const TRegion *r) const; + void drawRegion(const TColorFunction *cf, const bool antiAliasing, + TRegionOutline &boundary) const; + void drawRegion(TFlash &flash, const TRegion *r) const; - QString getDescription() const { return QCoreApplication::translate("TChalkFillStyle", "Chalk"); } - void loadData(int oldId, TInputStreamInterface &); - void getObsoleteTagIds(std::vector &ids) const { ids.push_back(1133); } - int getTagId() const { return 1143; }; + QString getDescription() const { + return QCoreApplication::translate("TChalkFillStyle", "Chalk"); + } + void loadData(int oldId, TInputStreamInterface &); + void getObsoleteTagIds(std::vector &ids) const { ids.push_back(1133); } + int getTagId() const { return 1143; }; protected: - void loadData(TInputStreamInterface &is); - void saveData(TOutputStreamInterface &os) const; + void loadData(TInputStreamInterface &is); + void saveData(TOutputStreamInterface &os) const; }; //============================================================ -class DVAPI TChessFillStyle : public TSolidColorStyle -{ - TPixel32 m_pointColor; - double m_HDist, m_VDist, m_Angle; +class DVAPI TChessFillStyle : public TSolidColorStyle { + TPixel32 m_pointColor; + double m_HDist, m_VDist, m_Angle; public: - TChessFillStyle(const TPixel32 &bgColor, const TPixel32 &pointColor, - const double HDist, const double VDist, const double Angle); - TChessFillStyle(const TPixel32 &color); + TChessFillStyle(const TPixel32 &bgColor, const TPixel32 &pointColor, + const double HDist, const double VDist, const double Angle); + TChessFillStyle(const TPixel32 &color); - TColorStyle *clone() const; + TColorStyle *clone() const; - /* - TPixel32 getMainColor() const {return m_pointColor; } - void setMainColor(const TPixel32 &color){ m_pointColor=color; } - */ + /* +TPixel32 getMainColor() const {return m_pointColor; } +void setMainColor(const TPixel32 &color){ m_pointColor=color; } +*/ - int getColorParamCount() const { return 2; } - TPixel32 getColorParamValue(int index) const; - void setColorParamValue(int index, const TPixel32 &color); + int getColorParamCount() const { return 2; } + TPixel32 getColorParamValue(int index) const; + void setColorParamValue(int index, const TPixel32 &color); - bool isRegionStyle() const { return true; } - bool isStrokeStyle() const { return false; } + bool isRegionStyle() const { return true; } + bool isStrokeStyle() const { return false; } - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); - void drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const; - void drawRegion(TFlash &flash, const TRegion *r) const; + void drawRegion(const TColorFunction *cf, const bool antiAliasing, + TRegionOutline &boundary) const; + void drawRegion(TFlash &flash, const TRegion *r) const; - int getTagId() const { return 1136; }; - QString getDescription() const { return QCoreApplication::translate("TChessFillStyle", "Chessboard"); } + int getTagId() const { return 1136; }; + QString getDescription() const { + return QCoreApplication::translate("TChessFillStyle", "Chessboard"); + } protected: - void loadData(TInputStreamInterface &is); - void saveData(TOutputStreamInterface &os) const; + void loadData(TInputStreamInterface &is); + void saveData(TOutputStreamInterface &os) const; private: - void makeGrid(TRectD &bbox, TRotation &rotM, - std::vector &grid, int &nbClip) const; + void makeGrid(TRectD &bbox, TRotation &rotM, std::vector &grid, + int &nbClip) const; }; //============================================================ -class DVAPI TStripeFillStyle : public TSolidColorStyle -{ - TPixel32 m_pointColor; - double m_Dist, m_Angle, m_Thickness; +class DVAPI TStripeFillStyle : public TSolidColorStyle { + TPixel32 m_pointColor; + double m_Dist, m_Angle, m_Thickness; public: - TStripeFillStyle(const TPixel32 &bgColor, const TPixel32 &pointColor, - const double Dist, const double Angle, const double Thickness); - TStripeFillStyle(const TPixel32 &color); + TStripeFillStyle(const TPixel32 &bgColor, const TPixel32 &pointColor, + const double Dist, const double Angle, + const double Thickness); + TStripeFillStyle(const TPixel32 &color); - TColorStyle *clone() const; + TColorStyle *clone() const; - /* - TPixel32 getMainColor() const {return m_pointColor; } - void setMainColor(const TPixel32 &color){ m_pointColor=color; } - */ + /* +TPixel32 getMainColor() const {return m_pointColor; } +void setMainColor(const TPixel32 &color){ m_pointColor=color; } +*/ - int getColorParamCount() const { return 2; } - TPixel32 getColorParamValue(int index) const; - void setColorParamValue(int index, const TPixel32 &color); + int getColorParamCount() const { return 2; } + TPixel32 getColorParamValue(int index) const; + void setColorParamValue(int index, const TPixel32 &color); - bool isRegionStyle() const { return true; } - bool isStrokeStyle() const { return false; } + bool isRegionStyle() const { return true; } + bool isStrokeStyle() const { return false; } - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); - void drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const; - void drawRegion(TFlash &flash, const TRegion *r) const; + void drawRegion(const TColorFunction *cf, const bool antiAliasing, + TRegionOutline &boundary) const; + void drawRegion(TFlash &flash, const TRegion *r) const; - int getTagId() const { return 1137; }; - QString getDescription() const { return QCoreApplication::translate("TStripeFillStyle", "Banded"); } + int getTagId() const { return 1137; }; + QString getDescription() const { + return QCoreApplication::translate("TStripeFillStyle", "Banded"); + } protected: - void loadData(TInputStreamInterface &is); - void saveData(TOutputStreamInterface &os) const; + void loadData(TInputStreamInterface &is); + void saveData(TOutputStreamInterface &os) const; - void makeIcon(const TDimension &d); + void makeIcon(const TDimension &d); private: - void getThickline(const TPointD &lc, const double ly, - TPointD &p0, TPointD &p1, - TPointD &p2, TPointD &p3) const; - int nbClip(const TRectD &bbox) const; + void getThickline(const TPointD &lc, const double ly, TPointD &p0, + TPointD &p1, TPointD &p2, TPointD &p3) const; + int nbClip(const TRectD &bbox) const; }; //============================================================ -class DVAPI TLinGradFillStyle : public TSolidColorStyle -{ - TPixel32 m_pointColor; - double m_Angle; - double m_XPos, m_YPos, m_Size; +class DVAPI TLinGradFillStyle : public TSolidColorStyle { + TPixel32 m_pointColor; + double m_Angle; + double m_XPos, m_YPos, m_Size; public: - TLinGradFillStyle(const TPixel32 &bgColor, const TPixel32 &pointColor, - const double Angle, const double XPos, const double YPos, - const double Size); - TLinGradFillStyle(const TPixel32 &color); + TLinGradFillStyle(const TPixel32 &bgColor, const TPixel32 &pointColor, + const double Angle, const double XPos, const double YPos, + const double Size); + TLinGradFillStyle(const TPixel32 &color); - TColorStyle *clone() const; + TColorStyle *clone() const; - /* - TPixel32 getMainColor() const {return m_pointColor; } - void setMainColor(const TPixel32 &color){ m_pointColor=color; } - */ + /* +TPixel32 getMainColor() const {return m_pointColor; } +void setMainColor(const TPixel32 &color){ m_pointColor=color; } +*/ - int getColorParamCount() const { return 2; } - TPixel32 getColorParamValue(int index) const; - void setColorParamValue(int index, const TPixel32 &color); + int getColorParamCount() const { return 2; } + TPixel32 getColorParamValue(int index) const; + void setColorParamValue(int index, const TPixel32 &color); - bool isRegionStyle() const { return true; } - bool isStrokeStyle() const { return false; } + bool isRegionStyle() const { return true; } + bool isStrokeStyle() const { return false; } - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); - void drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const; - void drawRegion(TFlash &flash, const TRegion *r) const; + void drawRegion(const TColorFunction *cf, const bool antiAliasing, + TRegionOutline &boundary) const; + void drawRegion(TFlash &flash, const TRegion *r) const; - int getTagId() const { return 1138; }; - QString getDescription() const { return QCoreApplication::translate("TLinGradFillStyle", "Linear Gradient"); } + int getTagId() const { return 1138; }; + QString getDescription() const { + return QCoreApplication::translate("TLinGradFillStyle", "Linear Gradient"); + } protected: - void loadData(TInputStreamInterface &is); - void saveData(TOutputStreamInterface &os) const; + void loadData(TInputStreamInterface &is); + void saveData(TOutputStreamInterface &os) const; private: - void getRects(const TRectD &bbox, std::vector &r0, - std::vector &r1, std::vector &r2) const; + void getRects(const TRectD &bbox, std::vector &r0, + std::vector &r1, std::vector &r2) const; - void getRect(const TRectD &bbox, std::vector &r) const; + void getRect(const TRectD &bbox, std::vector &r) const; }; //============================================================ -class DVAPI TRadGradFillStyle : public TSolidColorStyle -{ - TPixel32 m_pointColor; - double m_Radius; - double m_XPos, m_YPos; - double m_Smooth; +class DVAPI TRadGradFillStyle : public TSolidColorStyle { + TPixel32 m_pointColor; + double m_Radius; + double m_XPos, m_YPos; + double m_Smooth; public: - TRadGradFillStyle(const TPixel32 &bgColor, const TPixel32 &pointColor, - const double XPos, const double YPos, - const double Radius, const double Smooth); - TRadGradFillStyle(const TPixel32 &color); + TRadGradFillStyle(const TPixel32 &bgColor, const TPixel32 &pointColor, + const double XPos, const double YPos, const double Radius, + const double Smooth); + TRadGradFillStyle(const TPixel32 &color); - TColorStyle *clone() const; + TColorStyle *clone() const; - // TPixel32 getMainColor() const {return m_pointColor; } - // void setMainColor(const TPixel32 &color){ m_pointColor=color; } + // TPixel32 getMainColor() const {return m_pointColor; } + // void setMainColor(const TPixel32 &color){ m_pointColor=color; } - int getColorParamCount() const { return 2; } - TPixel32 getColorParamValue(int index) const; - void setColorParamValue(int index, const TPixel32 &color); + int getColorParamCount() const { return 2; } + TPixel32 getColorParamValue(int index) const; + void setColorParamValue(int index, const TPixel32 &color); - bool isRegionStyle() const { return true; } - bool isStrokeStyle() const { return false; } + bool isRegionStyle() const { return true; } + bool isStrokeStyle() const { return false; } - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); - void drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const; - void drawRegion(TFlash &flash, const TRegion *r) const; + void drawRegion(const TColorFunction *cf, const bool antiAliasing, + TRegionOutline &boundary) const; + void drawRegion(TFlash &flash, const TRegion *r) const; - int getTagId() const { return 1139; }; - QString getDescription() const { return QCoreApplication::translate("TRadGradFillStyle", "Radial Gradient"); } + int getTagId() const { return 1139; }; + QString getDescription() const { + return QCoreApplication::translate("TRadGradFillStyle", "Radial Gradient"); + } protected: - void loadData(TInputStreamInterface &is); - void saveData(TOutputStreamInterface &os) const; + void loadData(TInputStreamInterface &is); + void saveData(TOutputStreamInterface &os) const; }; //============================================================ -class DVAPI TCircleStripeFillStyle : public TSolidColorStyle -{ - TPixel32 m_pointColor; - double m_XPos, m_YPos; - double m_Dist, m_Thickness; +class DVAPI TCircleStripeFillStyle : public TSolidColorStyle { + TPixel32 m_pointColor; + double m_XPos, m_YPos; + double m_Dist, m_Thickness; public: - TCircleStripeFillStyle(const TPixel32 &bgColor, const TPixel32 &pointColor, - const double XPos, const double YPos, - const double Dist, const double Thickness); - TCircleStripeFillStyle(const TPixel32 &color); + TCircleStripeFillStyle(const TPixel32 &bgColor, const TPixel32 &pointColor, + const double XPos, const double YPos, + const double Dist, const double Thickness); + TCircleStripeFillStyle(const TPixel32 &color); - TColorStyle *clone() const; + TColorStyle *clone() const; - /* - TPixel32 getMainColor() const {return m_pointColor; } - void setMainColor(const TPixel32 &color){ m_pointColor=color; } - */ + /* +TPixel32 getMainColor() const {return m_pointColor; } +void setMainColor(const TPixel32 &color){ m_pointColor=color; } +*/ - int getColorParamCount() const { return 2; } - TPixel32 getColorParamValue(int index) const; - void setColorParamValue(int index, const TPixel32 &color); + int getColorParamCount() const { return 2; } + TPixel32 getColorParamValue(int index) const; + void setColorParamValue(int index, const TPixel32 &color); - bool isRegionStyle() const { return true; } - bool isStrokeStyle() const { return false; } + bool isRegionStyle() const { return true; } + bool isStrokeStyle() const { return false; } - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); - void drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const; - void drawRegion(TFlash &flash, const TRegion *r) const; + void drawRegion(const TColorFunction *cf, const bool antiAliasing, + TRegionOutline &boundary) const; + void drawRegion(TFlash &flash, const TRegion *r) const; - int getTagId() const { return 1140; }; - QString getDescription() const { return QCoreApplication::translate("TCircleStripeFillStyle", "Concentric"); } + int getTagId() const { return 1140; }; + QString getDescription() const { + return QCoreApplication::translate("TCircleStripeFillStyle", "Concentric"); + } protected: - void loadData(TInputStreamInterface &is); - void saveData(TOutputStreamInterface &os) const; + void loadData(TInputStreamInterface &is); + void saveData(TOutputStreamInterface &os) const; private: - void getCircleStripeQuads(const TPointD ¢er, - const double r1, const double r2, - std::vector &pv) const; - void drawCircleStripe(const TPointD ¢er, - const double r1, const double r2, - const TPixel32 &col) const; + void getCircleStripeQuads(const TPointD ¢er, const double r1, + const double r2, std::vector &pv) const; + void drawCircleStripe(const TPointD ¢er, const double r1, const double r2, + const TPixel32 &col) const; }; //============================================================ -class DVAPI TMosaicFillStyle : public TSolidColorStyle -{ - TPixel32 m_pointColor[4]; - double m_size; - double m_deform; - double m_minThickness; - double m_maxThickness; +class DVAPI TMosaicFillStyle : public TSolidColorStyle { + TPixel32 m_pointColor[4]; + double m_size; + double m_deform; + double m_minThickness; + double m_maxThickness; public: - TMosaicFillStyle(const TPixel32 &bgColor, - const TPixel32 pointColor[4], - const double size, - const double deform, - const double minThickness, - const double maxThickness); - TMosaicFillStyle(const TPixel32 bgColor); + TMosaicFillStyle(const TPixel32 &bgColor, const TPixel32 pointColor[4], + const double size, const double deform, + const double minThickness, const double maxThickness); + TMosaicFillStyle(const TPixel32 bgColor); - TColorStyle *clone() const; + TColorStyle *clone() const; - /* - TPixel32 getMainColor() const {return m_pointColor[0]; } - void setMainColor(const TPixel32 &color){ m_pointColor[0]=color; } - */ + /* +TPixel32 getMainColor() const {return m_pointColor[0]; } +void setMainColor(const TPixel32 &color){ m_pointColor[0]=color; } +*/ - int getColorParamCount() const { return 5; } - TPixel32 getColorParamValue(int index) const; - void setColorParamValue(int index, const TPixel32 &color); + int getColorParamCount() const { return 5; } + TPixel32 getColorParamValue(int index) const; + void setColorParamValue(int index, const TPixel32 &color); - bool isRegionStyle() const { return true; } - bool isStrokeStyle() const { return false; } + bool isRegionStyle() const { return true; } + bool isStrokeStyle() const { return false; } - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); - void drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const; - void drawRegion(TFlash &flash, const TRegion *r) const; + void drawRegion(const TColorFunction *cf, const bool antiAliasing, + TRegionOutline &boundary) const; + void drawRegion(TFlash &flash, const TRegion *r) const; - int getTagId() const { return 1141; }; - QString getDescription() const { return QCoreApplication::translate("TMosaicFillStyle", "Stained Glass"); } + int getTagId() const { return 1141; }; + QString getDescription() const { + return QCoreApplication::translate("TMosaicFillStyle", "Stained Glass"); + } protected: - void loadData(TInputStreamInterface &is); - void saveData(TOutputStreamInterface &os) const; + void loadData(TInputStreamInterface &is); + void saveData(TOutputStreamInterface &os) const; private: - void preaprePos(const TRectD &box, std::vector &v, - int &lX, int &lY, TRandom &rand) const; - bool getQuad(const int ix, const int iy, - const int lX, const int lY, - std::vector &v, TPointD *pquad, TRandom &rand) const; + void preaprePos(const TRectD &box, std::vector &v, int &lX, int &lY, + TRandom &rand) const; + bool getQuad(const int ix, const int iy, const int lX, const int lY, + std::vector &v, TPointD *pquad, TRandom &rand) const; }; //============================================================ -class DVAPI TPatchFillStyle : public TSolidColorStyle -{ - TPixel32 m_pointColor[6]; - double m_size; - double m_deform; - double m_thickness; +class DVAPI TPatchFillStyle : public TSolidColorStyle { + TPixel32 m_pointColor[6]; + double m_size; + double m_deform; + double m_thickness; public: - TPatchFillStyle(const TPixel32 &bgColor, - const TPixel32 pointColor[6], - const double size, - const double deform, - const double thickness); - TPatchFillStyle(const TPixel32 &bgColor); + TPatchFillStyle(const TPixel32 &bgColor, const TPixel32 pointColor[6], + const double size, const double deform, + const double thickness); + TPatchFillStyle(const TPixel32 &bgColor); - TColorStyle *clone() const; + TColorStyle *clone() const; - int getColorParamCount() const { return 7; } - TPixel32 getColorParamValue(int index) const; - void setColorParamValue(int index, const TPixel32 &color); + int getColorParamCount() const { return 7; } + TPixel32 getColorParamValue(int index) const; + void setColorParamValue(int index, const TPixel32 &color); - bool isRegionStyle() const { return true; } - bool isStrokeStyle() const { return false; } + bool isRegionStyle() const { return true; } + bool isStrokeStyle() const { return false; } - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); - void drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const; - void drawRegion(TFlash &flash, const TRegion *r) const; + void drawRegion(const TColorFunction *cf, const bool antiAliasing, + TRegionOutline &boundary) const; + void drawRegion(TFlash &flash, const TRegion *r) const; - int getTagId() const { return 1142; }; - QString getDescription() const { return QCoreApplication::translate("TPatchFillStyle", "Beehive"); } + int getTagId() const { return 1142; }; + QString getDescription() const { + return QCoreApplication::translate("TPatchFillStyle", "Beehive"); + } private: - void preaprePos(const TRectD &box, std::vector &v, - int &lX, int &lY, TRandom &rand) const; - bool getQuadLine(const TPointD &a, const TPointD &b, - const double thickn, TPointD *quad) const; - void drawGLQuad(const TPointD *quad) const; - int nbClip(const int lX, const int lY, const std::vector &v) const; - void drawFlashQuad(TFlash &flash, const TPointD *quad) const; - void drawFlashTriangle(TFlash &flash, const TPointD &p1, - const TPointD &p2, const TPointD &p3) const; + void preaprePos(const TRectD &box, std::vector &v, int &lX, int &lY, + TRandom &rand) const; + bool getQuadLine(const TPointD &a, const TPointD &b, const double thickn, + TPointD *quad) const; + void drawGLQuad(const TPointD *quad) const; + int nbClip(const int lX, const int lY, const std::vector &v) const; + void drawFlashQuad(TFlash &flash, const TPointD *quad) const; + void drawFlashTriangle(TFlash &flash, const TPointD &p1, const TPointD &p2, + const TPointD &p3) const; protected: - void loadData(TInputStreamInterface &is); - void saveData(TOutputStreamInterface &os) const; + void loadData(TInputStreamInterface &is); + void saveData(TOutputStreamInterface &os) const; }; -#endif // TDERIVEDREGIONSTYLES_H +#endif // TDERIVEDREGIONSTYLES_H diff --git a/toonz/sources/colorfx/strokestyles.cpp b/toonz/sources/colorfx/strokestyles.cpp index 1668d67..3a06d78 100644 --- a/toonz/sources/colorfx/strokestyles.cpp +++ b/toonz/sources/colorfx/strokestyles.cpp @@ -25,6322 +25,6115 @@ using namespace std; //============================================================================= -namespace -{ +namespace { template -class TOptimizedStrokePropT : public TStrokeProp -{ +class TOptimizedStrokePropT : public TStrokeProp { protected: - double m_pixelSize; + double m_pixelSize; - TOptimizedStrokeStyleT *m_colorStyle; - T m_data; + TOptimizedStrokeStyleT *m_colorStyle; + T m_data; public: - TOptimizedStrokePropT(const TStroke *stroke, TOptimizedStrokeStyleT *style); - ~TOptimizedStrokePropT() { m_colorStyle->release(); } + TOptimizedStrokePropT(const TStroke *stroke, + TOptimizedStrokeStyleT *style); + ~TOptimizedStrokePropT() { m_colorStyle->release(); } - const TColorStyle *getColorStyle() const; + const TColorStyle *getColorStyle() const; - TStrokeProp *clone(const TStroke *stroke) const; - void draw(const TVectorRenderData &rd); - void draw(TFlash &flash) - { - getColorStyle()->drawStroke(flash, getStroke()); - } + TStrokeProp *clone(const TStroke *stroke) const; + void draw(const TVectorRenderData &rd); + void draw(TFlash &flash) { getColorStyle()->drawStroke(flash, getStroke()); } }; //----------------------------------------------------------------------------- template -TOptimizedStrokePropT::TOptimizedStrokePropT(const TStroke *stroke, TOptimizedStrokeStyleT *style) - : TStrokeProp(stroke), m_colorStyle(style), m_pixelSize(0) -{ - m_styleVersionNumber = style->getVersionNumber(); - m_colorStyle->addRef(); +TOptimizedStrokePropT::TOptimizedStrokePropT( + const TStroke *stroke, TOptimizedStrokeStyleT *style) + : TStrokeProp(stroke), m_colorStyle(style), m_pixelSize(0) { + m_styleVersionNumber = style->getVersionNumber(); + m_colorStyle->addRef(); } //----------------------------------------------------------------------------- template -const TColorStyle *TOptimizedStrokePropT::getColorStyle() const -{ - return m_colorStyle; +const TColorStyle *TOptimizedStrokePropT::getColorStyle() const { + return m_colorStyle; } //----------------------------------------------------------------------------- template -TStrokeProp *TOptimizedStrokePropT::clone(const TStroke *stroke) const -{ - TOptimizedStrokePropT *prop = new TOptimizedStrokePropT(stroke, m_colorStyle); - prop->m_strokeChanged = m_strokeChanged; - prop->m_data = m_data; - return prop; +TStrokeProp *TOptimizedStrokePropT::clone(const TStroke *stroke) const { + TOptimizedStrokePropT *prop = + new TOptimizedStrokePropT(stroke, m_colorStyle); + prop->m_strokeChanged = m_strokeChanged; + prop->m_data = m_data; + return prop; } //----------------------------------------------------------------------------- template -void TOptimizedStrokePropT::draw(const TVectorRenderData &rd) /*assenza di const non e' una dimenticanza! Alcune sottoclassi devono ridefinire questo metodo e serbve che non sia const*/ -{ - if (rd.m_clippingRect != TRect() && !rd.m_is3dView && !convert(rd.m_aff * m_stroke->getBBox()).overlaps(rd.m_clippingRect)) - return; - - glPushMatrix(); - tglMultMatrix(rd.m_aff); - - double pixelSize = sqrt(tglGetPixelSize2()); - if (m_strokeChanged || - m_styleVersionNumber != m_colorStyle->getVersionNumber() || - !isAlmostZero(pixelSize - m_pixelSize, 1e-5)) { - m_strokeChanged = false; - m_pixelSize = pixelSize; - m_styleVersionNumber = m_colorStyle->getVersionNumber(); - m_colorStyle->computeData(m_data, m_stroke, rd.m_cf); - } +void TOptimizedStrokePropT::draw( + const TVectorRenderData + &rd) /*assenza di const non e' una dimenticanza! Alcune sottoclassi + devono ridefinire questo metodo e serbve che non sia const*/ +{ + if (rd.m_clippingRect != TRect() && !rd.m_is3dView && + !convert(rd.m_aff * m_stroke->getBBox()).overlaps(rd.m_clippingRect)) + return; + + glPushMatrix(); + tglMultMatrix(rd.m_aff); + + double pixelSize = sqrt(tglGetPixelSize2()); + if (m_strokeChanged || + m_styleVersionNumber != m_colorStyle->getVersionNumber() || + !isAlmostZero(pixelSize - m_pixelSize, 1e-5)) { + m_strokeChanged = false; + m_pixelSize = pixelSize; + m_styleVersionNumber = m_colorStyle->getVersionNumber(); + m_colorStyle->computeData(m_data, m_stroke, rd.m_cf); + } - m_colorStyle->drawStroke(rd.m_cf, m_data, m_stroke); + m_colorStyle->drawStroke(rd.m_cf, m_data, m_stroke); - glPopMatrix(); + glPopMatrix(); } } //============================================================================= template -TStrokeProp *TOptimizedStrokeStyleT::makeStrokeProp(const TStroke *stroke) -{ - return new TOptimizedStrokePropT(stroke, this); +TStrokeProp *TOptimizedStrokeStyleT::makeStrokeProp(const TStroke *stroke) { + return new TOptimizedStrokePropT(stroke, this); } //============================================================================= -inline void tglNormal(const T3DPointD &p) -{ - glNormal3d(p.x, p.y, p.z); -} +inline void tglNormal(const T3DPointD &p) { glNormal3d(p.x, p.y, p.z); } -inline void tglVertex(const T3DPointD &p) -{ - glVertex3d(p.x, p.y, p.z); -} +inline void tglVertex(const T3DPointD &p) { glVertex3d(p.x, p.y, p.z); } //============================================================================= TFurStrokeStyle::TFurStrokeStyle() - : m_color(TPixel32::Black), m_angle(120.0), m_length(1.0), m_cs(0.0), m_sn(0.0) -{ - double rad = TConsts::pi_180 * m_angle; - m_cs = cos(rad); - m_sn = sin(rad); + : m_color(TPixel32::Black) + , m_angle(120.0) + , m_length(1.0) + , m_cs(0.0) + , m_sn(0.0) { + double rad = m_angle * M_PI_180; + m_cs = cos(rad); + m_sn = sin(rad); } //----------------------------------------------------------------------------- -TColorStyle *TFurStrokeStyle::clone() const -{ - return new TFurStrokeStyle(*this); +TColorStyle *TFurStrokeStyle::clone() const { + return new TFurStrokeStyle(*this); } //----------------------------------------------------------------------------- -int TFurStrokeStyle::getParamCount() const -{ - return 2; -} +int TFurStrokeStyle::getParamCount() const { return 2; } //----------------------------------------------------------------------------- -TColorStyle::ParamType TFurStrokeStyle::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +TColorStyle::ParamType TFurStrokeStyle::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -QString TFurStrokeStyle::getParamNames(int index) const -{ - assert(0 <= index && index < getParamCount()); - return index == 0 ? QCoreApplication::translate("TFurStrokeStyle", "Angle") : QCoreApplication::translate("TFurStrokeStyle", "Size"); +QString TFurStrokeStyle::getParamNames(int index) const { + assert(0 <= index && index < getParamCount()); + return index == 0 ? QCoreApplication::translate("TFurStrokeStyle", "Angle") + : QCoreApplication::translate("TFurStrokeStyle", "Size"); } //----------------------------------------------------------------------------- -void TFurStrokeStyle::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < getParamCount()); - if (index == 0) { - min = 0.0; - max = 180.0; - } else { - min = 0.0; - max = 1.0; - } +void TFurStrokeStyle::getParamRange(int index, double &min, double &max) const { + assert(0 <= index && index < getParamCount()); + if (index == 0) { + min = 0.0; + max = 180.0; + } else { + min = 0.0; + max = 1.0; + } } //----------------------------------------------------------------------------- -double TFurStrokeStyle::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < getParamCount()); - return index == 0 ? m_angle : m_length; +double TFurStrokeStyle::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < getParamCount()); + return index == 0 ? m_angle : m_length; } //----------------------------------------------------------------------------- -void TFurStrokeStyle::setParamValue(int index, double value) -{ - assert(0 <= index && index < getParamCount()); - if (index == 0) { - m_angle = value; - double rad = TConsts::pi_180 * m_angle; - m_cs = cos(rad); - m_sn = sin(rad); - } else - m_length = value; +void TFurStrokeStyle::setParamValue(int index, double value) { + assert(0 <= index && index < getParamCount()); + if (index == 0) { + m_angle = value; + double rad = m_angle * M_PI_180; + m_cs = cos(rad); + m_sn = sin(rad); + } else + m_length = value; - updateVersionNumber(); + updateVersionNumber(); } //----------------------------------------------------------------------------- -void TFurStrokeStyle::drawStroke(TFlash &flash, const TStroke *stroke) const -{ - using TConsts::pi; - //TStroke *stroke = getStroke(); - double length = stroke->getLength(); - - double s = 0.0; - double ds = 4; - double vs = 1; - TRandom rnd; - flash.setLineColor(m_color); - vector segmentsArray; - - while (s <= length) { - double w = stroke->getParameterAtLength(s); - TThickPoint pos = stroke->getThickPoint(w); - TPointD pos1 = (TPointD)pos; - - TPointD u = stroke->getSpeed(w); - if (norm2(u) == 0.0) { - s += 0.5; - continue; - } - u = normalize(u); - TPointD v = rotate90(u); +void TFurStrokeStyle::drawStroke(TFlash &flash, const TStroke *stroke) const { + // TStroke *stroke = getStroke(); + double length = stroke->getLength(); - double length = m_length * pos.thick; - vs = -vs; - - double q = 0.01 * (rnd.getFloat() * 2 - 1); - segmentsArray.push_back(TSegment(pos1, pos1 + length * ((m_cs + q) * u + (vs * m_sn) * v))); - s += ds; - } + double s = 0.0; + double ds = 4; + double vs = 1; + TRandom rnd; + flash.setLineColor(m_color); + vector segmentsArray; + + while (s <= length) { + double w = stroke->getParameterAtLength(s); + TThickPoint pos = stroke->getThickPoint(w); + TPointD pos1 = (TPointD)pos; + + TPointD u = stroke->getSpeed(w); + if (norm2(u) == 0.0) { + s += 0.5; + continue; + } + u = normalize(u); + TPointD v = rotate90(u); + + double length = m_length * pos.thick; + vs = -vs; + + double q = 0.01 * (rnd.getFloat() * 2 - 1); + segmentsArray.push_back( + TSegment(pos1, pos1 + length * ((m_cs + q) * u + (vs * m_sn) * v))); + s += ds; + } - flash.drawSegments(segmentsArray, true); + flash.drawSegments(segmentsArray, true); } //----------------------------------------------------------------------------- -void TFurStrokeStyle::computeData(Points &positions, - const TStroke *stroke, - const TColorFunction *cf) const -{ - using TConsts::pi; - double length = stroke->getLength(); +void TFurStrokeStyle::computeData(Points &positions, const TStroke *stroke, + const TColorFunction *cf) const { + double length = stroke->getLength(); - double s = 0.0; - double ds = 4; - double vs = 1; - TRandom rnd; + double s = 0.0; + double ds = 4; + double vs = 1; + TRandom rnd; - positions.clear(); - positions.reserve(tceil(length / ds) + 1); + positions.clear(); + positions.reserve(tceil(length / ds) + 1); - while (s <= length) { - double w = stroke->getParameterAtLength(s); - TThickPoint pos = stroke->getThickPoint(w); - TPointD u = stroke->getSpeed(w); - if (norm2(u) == 0.0) { - s += 0.5; - continue; - } - u = normalize(u); - TPointD v = rotate90(u); + while (s <= length) { + double w = stroke->getParameterAtLength(s); + TThickPoint pos = stroke->getThickPoint(w); + TPointD u = stroke->getSpeed(w); + if (norm2(u) == 0.0) { + s += 0.5; + continue; + } + u = normalize(u); + TPointD v = rotate90(u); - double length = 0; - if (pos.thick) - length = m_length * pos.thick; - else - length = 1.0; + double length = 0; + if (pos.thick) + length = m_length * pos.thick; + else + length = 1.0; - vs = -vs; + vs = -vs; - positions.push_back(pos); - double q = 0.01 * (rnd.getFloat() * 2 - 1); - positions.push_back(pos + length * ((m_cs + q) * u + (vs * m_sn) * v)); + positions.push_back(pos); + double q = 0.01 * (rnd.getFloat() * 2 - 1); + positions.push_back(pos + length * ((m_cs + q) * u + (vs * m_sn) * v)); - s += ds; - } + s += ds; + } } //----------------------------------------------------------------------------- -void TFurStrokeStyle::drawStroke(const TColorFunction *cf, Points &positions, const TStroke *stroke) const -{ - TPixel32 color; - if (cf) - color = (*(cf))(m_color); - else - color = m_color; +void TFurStrokeStyle::drawStroke(const TColorFunction *cf, Points &positions, + const TStroke *stroke) const { + TPixel32 color; + if (cf) + color = (*(cf))(m_color); + else + color = m_color; - tglColor(color); + tglColor(color); - for (UINT i = 0; i < positions.size(); i += 2) { - glBegin(GL_LINE_STRIP); - tglColor(color); - tglVertex(positions[i]); - glColor4d(1, 1, 1, 0.0); - tglVertex(positions[i + 1]); - glEnd(); - } + for (UINT i = 0; i < positions.size(); i += 2) { + glBegin(GL_LINE_STRIP); + tglColor(color); + tglVertex(positions[i]); + glColor4d(1, 1, 1, 0.0); + tglVertex(positions[i + 1]); + glEnd(); + } } //============================================================================= -TChainStrokeStyle::TChainStrokeStyle(const TPixel32 &color) - : m_color(color) -{ -} +TChainStrokeStyle::TChainStrokeStyle(const TPixel32 &color) : m_color(color) {} //----------------------------------------------------------------------------- -TChainStrokeStyle::TChainStrokeStyle() - : m_color(TPixel32(20, 10, 0)) -{ -} +TChainStrokeStyle::TChainStrokeStyle() : m_color(TPixel32(20, 10, 0)) {} //----------------------------------------------------------------------------- -TColorStyle *TChainStrokeStyle::clone() const -{ - return new TChainStrokeStyle(*this); +TColorStyle *TChainStrokeStyle::clone() const { + return new TChainStrokeStyle(*this); } //----------------------------------------------------------------------------- -void TChainStrokeStyle::computeData(Points &data, const TStroke *stroke, const TColorFunction *cf) const -{ - //TStroke *stroke = getStroke(); - double length = stroke->getLength(); +void TChainStrokeStyle::computeData(Points &data, const TStroke *stroke, + const TColorFunction *cf) const { + // TStroke *stroke = getStroke(); + double length = stroke->getLength(); - // spessore della catena = spessore "medio" dello stroke - double thickness = 0.25 * (stroke->getThickPoint(0).thick + - stroke->getThickPoint(1.0 / 3.0).thick + - stroke->getThickPoint(2.0 / 3.0).thick + - stroke->getThickPoint(1).thick); + // spessore della catena = spessore "medio" dello stroke + double thickness = + 0.25 * + (stroke->getThickPoint(0).thick + stroke->getThickPoint(1.0 / 3.0).thick + + stroke->getThickPoint(2.0 / 3.0).thick + stroke->getThickPoint(1).thick); - if (thickness == 0) - thickness = 0.1; - double ringHeight = thickness; - double ringWidth = 1.5 * ringHeight; + if (thickness == 0) thickness = 0.1; + double ringHeight = thickness; + double ringWidth = 1.5 * ringHeight; - // distanza fra i centri degli anelli - double ringDistance = 2 * 1.2 * ringWidth; + // distanza fra i centri degli anelli + double ringDistance = 2 * 1.2 * ringWidth; - // distanza fra il centro dell'anello e il punto di attacco dell'anello trasversale - //double joinPos = 0.45 * ringWidth; + // distanza fra il centro dell'anello e il punto di attacco dell'anello + // trasversale + // double joinPos = 0.45 * ringWidth; - TPointD oldPos; - //bool firstRing = true; - double s = 0; + TPointD oldPos; + // bool firstRing = true; + double s = 0; - data.clear(); - data.reserve(tceil(length / ringDistance) * 2 + 2); + data.clear(); + data.reserve(tceil(length / ringDistance) * 2 + 2); - while (s <= length) { - double w = stroke->getParameterAtLength(s); - //if(w<0) {s+=0.1; continue;} // per tamponare il baco della getParameterAtLength() - TThickPoint pos = stroke->getThickPoint(w); - TPointD u = stroke->getSpeed(w); - if (norm2(u) == 0) { - s += 0.1; - continue; - } // non dovrebbe succedere mai, ma per prudenza.... - u = normalize(u); + while (s <= length) { + double w = stroke->getParameterAtLength(s); + // if(w<0) {s+=0.1; continue;} // per tamponare il baco della + // getParameterAtLength() + TThickPoint pos = stroke->getThickPoint(w); + TPointD u = stroke->getSpeed(w); + if (norm2(u) == 0) { + s += 0.1; + continue; + } // non dovrebbe succedere mai, ma per prudenza.... + u = normalize(u); - data.push_back(pos); - data.push_back(u); + data.push_back(pos); + data.push_back(u); - // se e' il caso unisco la catena alla precedente - s += ringDistance; - } + // se e' il caso unisco la catena alla precedente + s += ringDistance; + } } //----------------------------------------------------------------------------- -void TChainStrokeStyle::drawStroke(const TColorFunction *cf, Points &data, const TStroke *stroke) const -{ - //TStroke *stroke = getStroke(); - //double length = stroke->getLength(); - - // spessore della catena = spessore "medio" dello stroke - double thickness = 0.25 * (stroke->getThickPoint(0).thick + - stroke->getThickPoint(1.0 / 3.0).thick + - stroke->getThickPoint(2.0 / 3.0).thick + - stroke->getThickPoint(1).thick); - - if (thickness * thickness < 4 * tglGetPixelSize2()) { - TCenterLineStrokeStyle *appStyle = new TCenterLineStrokeStyle(m_color, 0x0, thickness); - appStyle->drawStroke(cf, stroke); - delete appStyle; - return; - } - - assert(thickness); - double ringHeight = thickness; - double ringWidth = 1.5 * ringHeight; - - // distanza fra i centri degli anelli - //double ringDistance = 2 * 1.2 * ringWidth; - - // distanza fra il centro dell'anello e il punto di attacco dell'anello trasversale - double joinPos = 0.45 * ringWidth; - - // definisco la forma dell'anello della catena - GLuint ringId; - ringId = glGenLists(1); - double a = .6, b = .6; - glNewList(ringId, GL_COMPILE); - glPushMatrix(); - glScaled(ringWidth, ringHeight, 1); - glBegin(GL_LINE_STRIP); - glVertex2d(1, b); - glVertex2d(a, 1); - glVertex2d(-a, 1); - glVertex2d(-1, b); - glVertex2d(-1, -b); - glVertex2d(-a, -1); - glVertex2d(a, -1); - glVertex2d(1, -b); - glVertex2d(1, b); - glEnd(); - glPopMatrix(); - glEndList(); - - // disegno la catena - - if (cf) - tglColor((*cf)(m_color)); - else - tglColor(m_color); - - TPointD oldPos; - //bool firstRing = true; - //double s = 0; - for (UINT i = 0; i < data.size(); i += 2) { - TPointD pos = data[i]; - TPointD u = data[i + 1]; - TPointD v = rotate90(u); - - // disegno un anello della catena - glPushMatrix(); - TAffine aff(u.x, v.x, pos.x, u.y, v.y, pos.y); - tglMultMatrix(aff); - glCallList(ringId); - glPopMatrix(); - - // se e' il caso unisco la catena alla precedente - if (i != 0) { - TPointD q = pos - u * joinPos; - tglDrawSegment(oldPos, q); - } - - oldPos = pos + u * joinPos; - } - - glDeleteLists(ringId, 1); -} - -//----------------------------------------------------------------------------- - -void TChainStrokeStyle::drawStroke(TFlash &flash, const TStroke *stroke) const -{ - //TStroke *stroke = getStroke(); - double length = stroke->getLength(); - - // spessore della catena = spessore "medio" dello stroke - double thickness = 0.25 * (stroke->getThickPoint(0).thick + - stroke->getThickPoint(1.0 / 3.0).thick + - stroke->getThickPoint(2.0 / 3.0).thick + - stroke->getThickPoint(1).thick); - - if (thickness < 2) { - TCenterLineStrokeStyle *appStyle = new TCenterLineStrokeStyle(m_color, 0x0, thickness); - appStyle->drawStroke(flash, stroke); - delete appStyle; - return; - } - - assert(thickness); - double ringHeight = thickness; - double ringWidth = 1.5 * ringHeight; - double ringDistance = 2 * 1.2 * ringWidth; - - double joinPos = 0.45 * ringWidth; - //const int ringId = 124; - double a = .6, b = .6; - - TScale scaleM(ringWidth, ringHeight); - vector chain; - chain.push_back(scaleM * TPointD(1, b)); //0 - chain.push_back(scaleM * TPointD(a, 1)); //1 - chain.push_back(scaleM * TPointD(-a, 1)); //2 - chain.push_back(scaleM * TPointD(-1, b)); //3 - chain.push_back(scaleM * TPointD(-1, -b)); //4 - chain.push_back(scaleM * TPointD(-a, -1)); //5 - chain.push_back(scaleM * TPointD(a, -1)); //6 - chain.push_back(scaleM * TPointD(1, -b)); //7 - chain.push_back(scaleM * TPointD(1, b)); //8 - - /* - chain.push_back( TPointD(1, b)); //0 - chain.push_back( TPointD( a, 1)); //1 - chain.push_back( TPointD(-a, 1)); //2 - chain.push_back( TPointD(-1, b)); //3 - chain.push_back( TPointD(-1,-b)); //4 - chain.push_back( TPointD(-a,-1)); //5 - chain.push_back( TPointD( a,-1)); //6 - chain.push_back( TPointD( 1,-b)); //7 - chain.push_back( TPointD(1, b)); //8 +void TChainStrokeStyle::drawStroke(const TColorFunction *cf, Points &data, + const TStroke *stroke) const { + // TStroke *stroke = getStroke(); + // double length = stroke->getLength(); + + // spessore della catena = spessore "medio" dello stroke + double thickness = + 0.25 * + (stroke->getThickPoint(0).thick + stroke->getThickPoint(1.0 / 3.0).thick + + stroke->getThickPoint(2.0 / 3.0).thick + stroke->getThickPoint(1).thick); + + if (thickness * thickness < 4 * tglGetPixelSize2()) { + TCenterLineStrokeStyle *appStyle = + new TCenterLineStrokeStyle(m_color, 0x0, thickness); + appStyle->drawStroke(cf, stroke); + delete appStyle; + return; + } + + assert(thickness); + double ringHeight = thickness; + double ringWidth = 1.5 * ringHeight; + + // distanza fra i centri degli anelli + // double ringDistance = 2 * 1.2 * ringWidth; + + // distanza fra il centro dell'anello e il punto di attacco dell'anello + // trasversale + double joinPos = 0.45 * ringWidth; + + // definisco la forma dell'anello della catena + GLuint ringId; + ringId = glGenLists(1); + double a = .6, b = .6; + glNewList(ringId, GL_COMPILE); + glPushMatrix(); + glScaled(ringWidth, ringHeight, 1); + glBegin(GL_LINE_STRIP); + glVertex2d(1, b); + glVertex2d(a, 1); + glVertex2d(-a, 1); + glVertex2d(-1, b); + glVertex2d(-1, -b); + glVertex2d(-a, -1); + glVertex2d(a, -1); + glVertex2d(1, -b); + glVertex2d(1, b); + glEnd(); + glPopMatrix(); + glEndList(); + + // disegno la catena + + if (cf) + tglColor((*cf)(m_color)); + else + tglColor(m_color); + + TPointD oldPos; + // bool firstRing = true; + // double s = 0; + for (UINT i = 0; i < data.size(); i += 2) { + TPointD pos = data[i]; + TPointD u = data[i + 1]; + TPointD v = rotate90(u); + + // disegno un anello della catena + glPushMatrix(); + TAffine aff(u.x, v.x, pos.x, u.y, v.y, pos.y); + tglMultMatrix(aff); + glCallList(ringId); + glPopMatrix(); + + // se e' il caso unisco la catena alla precedente + if (i != 0) { + TPointD q = pos - u * joinPos; + tglDrawSegment(oldPos, q); + } + + oldPos = pos + u * joinPos; + } + + glDeleteLists(ringId, 1); +} + +//----------------------------------------------------------------------------- + +void TChainStrokeStyle::drawStroke(TFlash &flash, const TStroke *stroke) const { + // TStroke *stroke = getStroke(); + double length = stroke->getLength(); + + // spessore della catena = spessore "medio" dello stroke + double thickness = + 0.25 * + (stroke->getThickPoint(0).thick + stroke->getThickPoint(1.0 / 3.0).thick + + stroke->getThickPoint(2.0 / 3.0).thick + stroke->getThickPoint(1).thick); + + if (thickness < 2) { + TCenterLineStrokeStyle *appStyle = + new TCenterLineStrokeStyle(m_color, 0x0, thickness); + appStyle->drawStroke(flash, stroke); + delete appStyle; + return; + } + + assert(thickness); + double ringHeight = thickness; + double ringWidth = 1.5 * ringHeight; + double ringDistance = 2 * 1.2 * ringWidth; + + double joinPos = 0.45 * ringWidth; + // const int ringId = 124; + double a = .6, b = .6; + + TScale scaleM(ringWidth, ringHeight); + vector chain; + chain.push_back(scaleM * TPointD(1, b)); // 0 + chain.push_back(scaleM * TPointD(a, 1)); // 1 + chain.push_back(scaleM * TPointD(-a, 1)); // 2 + chain.push_back(scaleM * TPointD(-1, b)); // 3 + chain.push_back(scaleM * TPointD(-1, -b)); // 4 + chain.push_back(scaleM * TPointD(-a, -1)); // 5 + chain.push_back(scaleM * TPointD(a, -1)); // 6 + chain.push_back(scaleM * TPointD(1, -b)); // 7 + chain.push_back(scaleM * TPointD(1, b)); // 8 + + /* +chain.push_back( TPointD(1, b)); //0 +chain.push_back( TPointD( a, 1)); //1 +chain.push_back( TPointD(-a, 1)); //2 +chain.push_back( TPointD(-1, b)); //3 +chain.push_back( TPointD(-1,-b)); //4 +chain.push_back( TPointD(-a,-1)); //5 +chain.push_back( TPointD( a,-1)); //6 +chain.push_back( TPointD( 1,-b)); //7 +chain.push_back( TPointD(1, b)); //8 */ - vector chainS; - chainS.push_back(TSegment(chain[0], chain[1])); - chainS.push_back(TSegment(chain[1], chain[2])); - chainS.push_back(TSegment(chain[2], chain[3])); - chainS.push_back(TSegment(chain[3], chain[4])); - chainS.push_back(TSegment(chain[4], chain[5])); - chainS.push_back(TSegment(chain[5], chain[6])); - chainS.push_back(TSegment(chain[6], chain[7])); - chainS.push_back(TSegment(chain[7], chain[0])); - - flash.setLineColor(m_color); - - TPointD oldPos; - bool firstRing = true; - double s = 0; - while (s <= length) { - double w = stroke->getParameterAtLength(s); - //if(w<0) {s+=0.1; continue;} // per tamponare il baco della getParameterAtLength() - TThickPoint pos = stroke->getThickPoint(w); - TPointD u = stroke->getSpeed(w); - if (norm2(u) == 0) { - s += 0.1; - continue; - } // non dovrebbe succedere mai, ma per prudenza.... - u = normalize(u); - // TPointD v = rotate90(u); - - TTranslation translM(pos.x, pos.y); - TRotation rotM(rad2degree(atan(u))); - TAffine tM = translM * rotM; - - // With direct transformation - vector lchainS; - for (int i = 0; i < 8; i++) - lchainS.push_back(TSegment(tM * chain[i], tM * chain[i + 1])); - flash.drawSegments(lchainS, false); - - /* + vector chainS; + chainS.push_back(TSegment(chain[0], chain[1])); + chainS.push_back(TSegment(chain[1], chain[2])); + chainS.push_back(TSegment(chain[2], chain[3])); + chainS.push_back(TSegment(chain[3], chain[4])); + chainS.push_back(TSegment(chain[4], chain[5])); + chainS.push_back(TSegment(chain[5], chain[6])); + chainS.push_back(TSegment(chain[6], chain[7])); + chainS.push_back(TSegment(chain[7], chain[0])); + + flash.setLineColor(m_color); + + TPointD oldPos; + bool firstRing = true; + double s = 0; + while (s <= length) { + double w = stroke->getParameterAtLength(s); + // if(w<0) {s+=0.1; continue;} // per tamponare il baco della + // getParameterAtLength() + TThickPoint pos = stroke->getThickPoint(w); + TPointD u = stroke->getSpeed(w); + if (norm2(u) == 0) { + s += 0.1; + continue; + } // non dovrebbe succedere mai, ma per prudenza.... + u = normalize(u); + // TPointD v = rotate90(u); + + TTranslation translM(pos.x, pos.y); + TRotation rotM(rad2degree(atan(u))); + TAffine tM = translM * rotM; + + // With direct transformation + vector lchainS; + for (int i = 0; i < 8; i++) + lchainS.push_back(TSegment(tM * chain[i], tM * chain[i + 1])); + flash.drawSegments(lchainS, false); + + /* // With TFlash transformations - flash.pushMatrix(); - flash.multMatrix(translM); - flash.multMatrix(rotM); +flash.pushMatrix(); +flash.multMatrix(translM); +flash.multMatrix(rotM); // flash.multMatrix(scaleM); - flash.drawSegments(chainS,false); -// if (chainId==-1) +flash.drawSegments(chainS,false); +// if (chainId==-1) // chainId=flash.drawSegments(chainS,false); // else // flash.drawShape(chainId); - flash.popMatrix(); +flash.popMatrix(); */ - if (!firstRing) { - TPointD q = pos - u * joinPos; - vector sv; - sv.push_back(TSegment(oldPos, q)); - flash.drawSegments(sv, false); - } else - firstRing = false; + if (!firstRing) { + TPointD q = pos - u * joinPos; + vector sv; + sv.push_back(TSegment(oldPos, q)); + flash.drawSegments(sv, false); + } else + firstRing = false; - oldPos = pos + u * joinPos; - s += ringDistance; - } + oldPos = pos + u * joinPos; + s += ringDistance; + } } //============================================================================= TSprayStrokeStyle::TSprayStrokeStyle() - : m_color(TPixel32::Blue), m_blend(0.5), m_intensity(10.0), m_radius(0.3) -{ -} + : m_color(TPixel32::Blue), m_blend(0.5), m_intensity(10.0), m_radius(0.3) {} //----------------------------------------------------------------------------- -TColorStyle *TSprayStrokeStyle::clone() const -{ - return new TSprayStrokeStyle(*this); +TColorStyle *TSprayStrokeStyle::clone() const { + return new TSprayStrokeStyle(*this); } //----------------------------------------------------------------------------- -int TSprayStrokeStyle::getParamCount() const -{ - return 3; -} +int TSprayStrokeStyle::getParamCount() const { return 3; } //----------------------------------------------------------------------------- -TColorStyle::ParamType TSprayStrokeStyle::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +TColorStyle::ParamType TSprayStrokeStyle::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -QString TSprayStrokeStyle::getParamNames(int index) const -{ - assert(0 <= index && index < 3); - QString value; - switch (index) { - case 0: - value = QCoreApplication::translate("TSprayStrokeStyle", "Border Fade"); - break; - case 1: - value = QCoreApplication::translate("TSprayStrokeStyle", "Density"); - break; - case 2: - value = QCoreApplication::translate("TSprayStrokeStyle", "Size"); - break; - } - return value; +QString TSprayStrokeStyle::getParamNames(int index) const { + assert(0 <= index && index < 3); + QString value; + switch (index) { + case 0: + value = QCoreApplication::translate("TSprayStrokeStyle", "Border Fade"); + break; + case 1: + value = QCoreApplication::translate("TSprayStrokeStyle", "Density"); + break; + case 2: + value = QCoreApplication::translate("TSprayStrokeStyle", "Size"); + break; + } + return value; +} + +//----------------------------------------------------------------------------- + +void TSprayStrokeStyle::getParamRange(int index, double &min, + double &max) const { + assert(0 <= index && index < 3); + switch (index) { + case 0: + min = 0.0; + max = 1.0; + break; + case 1: + min = 0.0; + max = 100.0; + break; + case 2: + min = 0.0; + max = 1.0; + break; + } } //----------------------------------------------------------------------------- -void TSprayStrokeStyle::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 3); - switch (index) { - case 0: - min = 0.0; - max = 1.0; - break; - case 1: - min = 0.0; - max = 100.0; - break; - case 2: - min = 0.0; - max = 1.0; - break; - } -} - -//----------------------------------------------------------------------------- - -double TSprayStrokeStyle::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 3); - double value = 0; - switch (index) { - case 0: - value = m_blend; - break; - case 1: - value = m_intensity; - break; - case 2: - value = m_radius; - break; - } - return value; +double TSprayStrokeStyle::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 3); + double value = 0; + switch (index) { + case 0: + value = m_blend; + break; + case 1: + value = m_intensity; + break; + case 2: + value = m_radius; + break; + } + return value; } //----------------------------------------------------------------------------- -void TSprayStrokeStyle::setParamValue(int index, double value) -{ - assert(0 <= index && index < 3); - switch (index) { - case 0: - m_blend = value; - break; - case 1: - m_intensity = value; - break; - case 2: - m_radius = value; - break; - } +void TSprayStrokeStyle::setParamValue(int index, double value) { + assert(0 <= index && index < 3); + switch (index) { + case 0: + m_blend = value; + break; + case 1: + m_intensity = value; + break; + case 2: + m_radius = value; + break; + } - updateVersionNumber(); + updateVersionNumber(); +} + +//----------------------------------------------------------------------------- + +void TSprayStrokeStyle::drawStroke(const TColorFunction *cf, + const TStroke *stroke) const { + // TStroke *stroke = getStroke(); + double length = stroke->getLength(); + double step = 4; + + double blend = m_blend; // distanza che controlla da dove il gessetto + // comincia il fade out (0, 1) + double intensity = m_intensity; // quanti punti vengono disegnati ad ogni + // step + double radius = m_radius; + double decay = 1 - blend; + bool fill = 0; + TPointD pos1; + TRandom rnd; + TPixelD dcolor; + TPixel32 color; + if (cf) + color = (*(cf))(m_color); + else + color = m_color; + dcolor = toPixelD(color); + double s = 0; + double minthickness = MINTHICK * sqrt(tglGetPixelSize2()); + double thickness = 0; + while (s <= length) { + double w = stroke->getParameterAtLength(s); + // if(w<0) {s+=0.1; continue;} // per tamponare il baco della + // getParameterAtLength() + TThickPoint pos = stroke->getThickPoint(w); + TPointD u = stroke->getSpeed(w); + double normu = norm2(u); + if (normu == 0) { + s += 0.1; + continue; + } // non dovrebbe succedere mai, ma per prudenza.... + u = normalize(u); + TPointD v = rotate90(u); + TPointD shift; + if (pos.thick < MINTHICK) + thickness = minthickness; + else + thickness = pos.thick; + for (int i = 0; i < intensity; i++) { + double vrandnorm = (0.5 - rnd.getFloat()) * 2; + double randomv = vrandnorm * pos.thick; + double randomu = (0.5 - rnd.getFloat()) * step; + shift = u * randomu + v * randomv; + pos1 = pos + shift; + double mod = fabs(vrandnorm); + if (mod < decay) + glColor4d(dcolor.r, dcolor.g, dcolor.b, rnd.getFloat() * dcolor.m); + else + glColor4d(dcolor.r, dcolor.g, dcolor.b, + rnd.getFloat() * (1 - mod) * dcolor.m); + if (fill) + tglDrawDisk(pos1, radius * thickness * rnd.getFloat()); + else + tglDrawCircle(pos1, radius * thickness * rnd.getFloat()); + } + s += step; + } } //----------------------------------------------------------------------------- -void TSprayStrokeStyle::drawStroke(const TColorFunction *cf, const TStroke *stroke) const -{ - // TStroke *stroke = getStroke(); - double length = stroke->getLength(); - double step = 4; - - double blend = m_blend; //distanza che controlla da dove il gessetto comincia il fade out (0, 1) - double intensity = m_intensity; //quanti punti vengono disegnati ad ogni step - double radius = m_radius; - double decay = 1 - blend; - bool fill = 0; - TPointD pos1; - TRandom rnd; - TPixelD dcolor; - TPixel32 color; - if (cf) - color = (*(cf))(m_color); - else - color = m_color; - dcolor = toPixelD(color); - double s = 0; - double minthickness = MINTHICK * sqrt(tglGetPixelSize2()); - double thickness = 0; - while (s <= length) { - double w = stroke->getParameterAtLength(s); - //if(w<0) {s+=0.1; continue;} // per tamponare il baco della getParameterAtLength() - TThickPoint pos = stroke->getThickPoint(w); - TPointD u = stroke->getSpeed(w); - double normu = norm2(u); - if (normu == 0) { - s += 0.1; - continue; - } // non dovrebbe succedere mai, ma per prudenza.... - u = normalize(u); - TPointD v = rotate90(u); - TPointD shift; - if (pos.thick < MINTHICK) - thickness = minthickness; - else - thickness = pos.thick; - for (int i = 0; i < intensity; i++) { - double vrandnorm = (0.5 - rnd.getFloat()) * 2; - double randomv = vrandnorm * pos.thick; - double randomu = (0.5 - rnd.getFloat()) * step; - shift = u * randomu + v * randomv; - pos1 = pos + shift; - double mod = fabs(vrandnorm); - if (mod < decay) - glColor4d(dcolor.r, dcolor.g, dcolor.b, rnd.getFloat() * dcolor.m); - else - glColor4d(dcolor.r, dcolor.g, dcolor.b, rnd.getFloat() * (1 - mod) * dcolor.m); - if (fill) - tglDrawDisk(pos1, radius * thickness * rnd.getFloat()); - else - tglDrawCircle(pos1, radius * thickness * rnd.getFloat()); - } - s += step; - } -} - -//----------------------------------------------------------------------------- - -void TSprayStrokeStyle::drawStroke(TFlash &flash, const TStroke *stroke) const -{ - double length = stroke->getLength(); - double step = 4; - - double blend = m_blend; //distanza che controlla da dove il gessetto comincia il fade out (0, 1) - double intensity = m_intensity; //quanti punti vengono disegnati ad ogni step - double radius = m_radius; - double decay = 1 - blend; - bool fill = 0; - TPointD pos1; - TRandom rnd; - TPixel32 color = m_color; - TPixelD dcolor; - dcolor = toPixelD(color); - - double s = 0; - while (s <= length) { - double w = stroke->getParameterAtLength(s); - //if(w<0) {s+=0.1; continue;} // per tamponare il baco della getParameterAtLength() - TThickPoint pos = stroke->getThickPoint(w); - TPointD u = stroke->getSpeed(w); - double normu = norm2(u); - if (normu == 0) { - s += 0.1; - continue; - } // non dovrebbe succedere mai, ma per prudenza.... - u = normalize(u); - TPointD v = rotate90(u); - TPointD shift; - for (int i = 0; i < intensity; i++) { - double vrandnorm = (0.5 - rnd.getFloat()) * 2; - double randomv = vrandnorm * pos.thick; - double randomu = (0.5 - rnd.getFloat()) * step; - shift = u * randomu + v * randomv; - pos1 = pos + shift; - double mod = fabs(vrandnorm); - TPixelD ldcolor = dcolor; - ldcolor.m = mod < decay ? rnd.getFloat() * dcolor.m : rnd.getFloat() * (1 - mod) * dcolor.m; - TPixel32 lcolor; - lcolor = toPixel32(ldcolor); - if (fill) { - flash.setFillColor(lcolor); - double r = radius * pos.thick * rnd.getFloat(); - flash.drawEllipse(pos1, r, r); - } else { - flash.setLineColor(lcolor); - flash.setFillColor(TPixel32(0, 0, 0, 0)); - flash.setThickness(0.5); - double r = radius * pos.thick * rnd.getFloat(); - flash.drawEllipse(pos1, r, r); - } - } - s += step; - } +void TSprayStrokeStyle::drawStroke(TFlash &flash, const TStroke *stroke) const { + double length = stroke->getLength(); + double step = 4; + + double blend = m_blend; // distanza che controlla da dove il gessetto + // comincia il fade out (0, 1) + double intensity = m_intensity; // quanti punti vengono disegnati ad ogni + // step + double radius = m_radius; + double decay = 1 - blend; + bool fill = 0; + TPointD pos1; + TRandom rnd; + TPixel32 color = m_color; + TPixelD dcolor; + dcolor = toPixelD(color); + + double s = 0; + while (s <= length) { + double w = stroke->getParameterAtLength(s); + // if(w<0) {s+=0.1; continue;} // per tamponare il baco della + // getParameterAtLength() + TThickPoint pos = stroke->getThickPoint(w); + TPointD u = stroke->getSpeed(w); + double normu = norm2(u); + if (normu == 0) { + s += 0.1; + continue; + } // non dovrebbe succedere mai, ma per prudenza.... + u = normalize(u); + TPointD v = rotate90(u); + TPointD shift; + for (int i = 0; i < intensity; i++) { + double vrandnorm = (0.5 - rnd.getFloat()) * 2; + double randomv = vrandnorm * pos.thick; + double randomu = (0.5 - rnd.getFloat()) * step; + shift = u * randomu + v * randomv; + pos1 = pos + shift; + double mod = fabs(vrandnorm); + TPixelD ldcolor = dcolor; + ldcolor.m = mod < decay ? rnd.getFloat() * dcolor.m + : rnd.getFloat() * (1 - mod) * dcolor.m; + TPixel32 lcolor; + lcolor = toPixel32(ldcolor); + if (fill) { + flash.setFillColor(lcolor); + double r = radius * pos.thick * rnd.getFloat(); + flash.drawEllipse(pos1, r, r); + } else { + flash.setLineColor(lcolor); + flash.setFillColor(TPixel32(0, 0, 0, 0)); + flash.setThickness(0.5); + double r = radius * pos.thick * rnd.getFloat(); + flash.drawEllipse(pos1, r, r); + } + } + s += step; + } } //============================================================================= TGraphicPenStrokeStyle::TGraphicPenStrokeStyle() - : m_color(TPixel32::Black), m_intensity(10.0) -{ -} + : m_color(TPixel32::Black), m_intensity(10.0) {} //----------------------------------------------------------------------------- -TColorStyle *TGraphicPenStrokeStyle::clone() const -{ - return new TGraphicPenStrokeStyle(*this); +TColorStyle *TGraphicPenStrokeStyle::clone() const { + return new TGraphicPenStrokeStyle(*this); } //----------------------------------------------------------------------------- -int TGraphicPenStrokeStyle::getParamCount() const -{ - return 1; -} +int TGraphicPenStrokeStyle::getParamCount() const { return 1; } //----------------------------------------------------------------------------- -TColorStyle::ParamType TGraphicPenStrokeStyle::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +TColorStyle::ParamType TGraphicPenStrokeStyle::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -QString TGraphicPenStrokeStyle::getParamNames(int index) const -{ - assert(0 <= index && index < 1); +QString TGraphicPenStrokeStyle::getParamNames(int index) const { + assert(0 <= index && index < 1); - return QCoreApplication::translate("TGraphicPenStrokeStyle", "Density"); + return QCoreApplication::translate("TGraphicPenStrokeStyle", "Density"); } //----------------------------------------------------------------------------- -void TGraphicPenStrokeStyle::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 1); - min = 0.0; - max = 10.0; +void TGraphicPenStrokeStyle::getParamRange(int index, double &min, + double &max) const { + assert(0 <= index && index < 1); + min = 0.0; + max = 10.0; } //----------------------------------------------------------------------------- -double TGraphicPenStrokeStyle::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 1); - return m_intensity; +double TGraphicPenStrokeStyle::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 1); + return m_intensity; } //----------------------------------------------------------------------------- -void TGraphicPenStrokeStyle::setParamValue(int index, double value) -{ - assert(0 <= index && index < 1); - m_intensity = value; - updateVersionNumber(); +void TGraphicPenStrokeStyle::setParamValue(int index, double value) { + assert(0 <= index && index < 1); + m_intensity = value; + updateVersionNumber(); } //----------------------------------------------------------------------------- void TGraphicPenStrokeStyle::computeData(DrawmodePointsMatrix &data, - const TStroke *stroke, - const TColorFunction *cf) const -{ - data.clear(); - double length = stroke->getLength(); - double step = 10; - TPointD pos1, pos2; - TRandom rnd; - double intensity = m_intensity; - data.reserve(tceil(length / 10.0)); - double s = 0; - while (s <= length) { - double w = stroke->getParameterAtLength(s); - //if(w<0) {s+=0.1; continue;} // per tamponare il baco della getParameterAtLength() - TThickPoint pos = stroke->getThickPoint(w); - TPointD u = stroke->getSpeed(w); - double normu = norm2(u); - if (normu == 0) { - s += 0.1; - continue; - } // non dovrebbe succedere mai, ma per prudenza.... - u = normalize(u); - TPointD v = rotate90(u); - TPointD shift; - Points tmpPoints; - tmpPoints.clear(); - GLenum drawMode; - for (int i = 0; i < intensity; i++) { - if (pos.thick) { - drawMode = GL_LINES; - tmpPoints.reserve((int)(intensity * 2 + 1)); - double randomv = (0.5 - rnd.getFloat()) * pos.thick; - double randomu = (0.5 - rnd.getFloat()) * step; - shift = randomu * u + randomv * v; - pos1 = pos + shift + v * (pos.thick); - pos2 = pos + shift - v * (pos.thick); - tmpPoints.push_back(pos1); - tmpPoints.push_back(pos2); - } else { - drawMode = GL_POINTS; - tmpPoints.reserve((int)(intensity + 1)); - tmpPoints.push_back((TPointD)pos); - } - } - if (!tmpPoints.empty()) { - assert(drawMode == GL_POINTS || drawMode == GL_LINES); - data.push_back(make_pair(drawMode, tmpPoints)); - } - s += step; - } + const TStroke *stroke, + const TColorFunction *cf) const { + data.clear(); + double length = stroke->getLength(); + double step = 10; + TPointD pos1, pos2; + TRandom rnd; + double intensity = m_intensity; + data.reserve(tceil(length / 10.0)); + double s = 0; + while (s <= length) { + double w = stroke->getParameterAtLength(s); + // if(w<0) {s+=0.1; continue;} // per tamponare il baco della + // getParameterAtLength() + TThickPoint pos = stroke->getThickPoint(w); + TPointD u = stroke->getSpeed(w); + double normu = norm2(u); + if (normu == 0) { + s += 0.1; + continue; + } // non dovrebbe succedere mai, ma per prudenza.... + u = normalize(u); + TPointD v = rotate90(u); + TPointD shift; + Points tmpPoints; + tmpPoints.clear(); + GLenum drawMode; + for (int i = 0; i < intensity; i++) { + if (pos.thick) { + drawMode = GL_LINES; + tmpPoints.reserve((int)(intensity * 2 + 1)); + double randomv = (0.5 - rnd.getFloat()) * pos.thick; + double randomu = (0.5 - rnd.getFloat()) * step; + shift = randomu * u + randomv * v; + pos1 = pos + shift + v * (pos.thick); + pos2 = pos + shift - v * (pos.thick); + tmpPoints.push_back(pos1); + tmpPoints.push_back(pos2); + } else { + drawMode = GL_POINTS; + tmpPoints.reserve((int)(intensity + 1)); + tmpPoints.push_back((TPointD)pos); + } + } + if (!tmpPoints.empty()) { + assert(drawMode == GL_POINTS || drawMode == GL_LINES); + data.push_back(make_pair(drawMode, tmpPoints)); + } + s += step; + } } //----------------------------------------------------------------------------- void TGraphicPenStrokeStyle::drawStroke(const TColorFunction *cf, - DrawmodePointsMatrix &data, - const TStroke *stroke) const -{ - TPixel32 color; - if (cf) - color = (*(cf))(m_color); - else - color = m_color; - tglColor(color); - - DrawmodePointsMatrix::iterator it1 = data.begin(); - for (; it1 != data.end(); ++it1) { - if (it1->first == GL_LINES) { - Points::iterator it2 = it1->second.begin(); - glBegin(GL_LINES); - for (; it2 != it1->second.end(); ++it2) - tglVertex(*it2); - glEnd(); - } else { - assert(it1->first == GL_POINTS); - Points::iterator it2 = it1->second.begin(); - glBegin(GL_POINTS); - for (; it2 != it1->second.end(); ++it2) - tglVertex(*it2); - glEnd(); - } - } -} - -//----------------------------------------------------------------------------- - -void TGraphicPenStrokeStyle::drawStroke(TFlash &flash, const TStroke *stroke) const + DrawmodePointsMatrix &data, + const TStroke *stroke) const { + TPixel32 color; + if (cf) + color = (*(cf))(m_color); + else + color = m_color; + tglColor(color); + + DrawmodePointsMatrix::iterator it1 = data.begin(); + for (; it1 != data.end(); ++it1) { + if (it1->first == GL_LINES) { + Points::iterator it2 = it1->second.begin(); + glBegin(GL_LINES); + for (; it2 != it1->second.end(); ++it2) tglVertex(*it2); + glEnd(); + } else { + assert(it1->first == GL_POINTS); + Points::iterator it2 = it1->second.begin(); + glBegin(GL_POINTS); + for (; it2 != it1->second.end(); ++it2) tglVertex(*it2); + glEnd(); + } + } +} + +//----------------------------------------------------------------------------- + +void TGraphicPenStrokeStyle::drawStroke(TFlash &flash, + const TStroke *stroke) const { - //TStroke *stroke = getStroke(); - vector segmentsArray; - double length = stroke->getLength(); - double step = 10; - TPointD pos1, pos2; - TRandom rnd; - double intensity = m_intensity; - flash.setLineColor(m_color); - - double s = 0; - while (s <= length) { - double w = stroke->getParameterAtLength(s); - //if(w<0) {s+=0.1; continue;} // per tamponare il baco della getParameterAtLength() - TThickPoint pos = stroke->getThickPoint(w); - TPointD u = stroke->getSpeed(w); - double normu = norm2(u); - if (normu == 0) { - s += 0.1; - continue; - } // non dovrebbe succedere mai, ma per prudenza.... - u = normalize(u); - TPointD v = rotate90(u); - TPointD shift; - for (int i = 0; i < intensity; i++) { - double randomv = (0.5 - rnd.getFloat()) * pos.thick; - double randomu = (0.5 - rnd.getFloat()) * step; - shift = randomu * u + randomv * v; - pos1 = pos + shift + v * (pos.thick); - pos2 = pos + shift - v * (pos.thick); - segmentsArray.push_back(TSegment(pos1, pos2)); - } - s += step; - } - - flash.drawSegments(segmentsArray, false); + // TStroke *stroke = getStroke(); + vector segmentsArray; + double length = stroke->getLength(); + double step = 10; + TPointD pos1, pos2; + TRandom rnd; + double intensity = m_intensity; + flash.setLineColor(m_color); + + double s = 0; + while (s <= length) { + double w = stroke->getParameterAtLength(s); + // if(w<0) {s+=0.1; continue;} // per tamponare il baco della + // getParameterAtLength() + TThickPoint pos = stroke->getThickPoint(w); + TPointD u = stroke->getSpeed(w); + double normu = norm2(u); + if (normu == 0) { + s += 0.1; + continue; + } // non dovrebbe succedere mai, ma per prudenza.... + u = normalize(u); + TPointD v = rotate90(u); + TPointD shift; + for (int i = 0; i < intensity; i++) { + double randomv = (0.5 - rnd.getFloat()) * pos.thick; + double randomu = (0.5 - rnd.getFloat()) * step; + shift = randomu * u + randomv * v; + pos1 = pos + shift + v * (pos.thick); + pos2 = pos + shift - v * (pos.thick); + segmentsArray.push_back(TSegment(pos1, pos2)); + } + s += step; + } + + flash.drawSegments(segmentsArray, false); } //============================================================================= -namespace -{ +namespace { double inline get_line_slope(double meter, double inmax, double linemax, - double outmax) -{ - if (meter <= inmax) - return meter / inmax; - else if (meter <= inmax + linemax) - return 1; - else if (meter <= inmax + linemax + outmax) - return (inmax + linemax - meter) / outmax + 1; - else - return 0; + double outmax) { + if (meter <= inmax) + return meter / inmax; + else if (meter <= inmax + linemax) + return 1; + else if (meter <= inmax + linemax + outmax) + return (inmax + linemax - meter) / outmax + 1; + else + return 0; } } //----------------------------------------------------------------------------- TDottedLineStrokeStyle::TDottedLineStrokeStyle() - : m_color(TPixel32::Black), m_in(10.0), m_line(50.0), m_out(10.0), m_blank(10.0) -{ -} + : m_color(TPixel32::Black) + , m_in(10.0) + , m_line(50.0) + , m_out(10.0) + , m_blank(10.0) {} //----------------------------------------------------------------------------- -TColorStyle *TDottedLineStrokeStyle::clone() const -{ - return new TDottedLineStrokeStyle(*this); +TColorStyle *TDottedLineStrokeStyle::clone() const { + return new TDottedLineStrokeStyle(*this); } //----------------------------------------------------------------------------- -int TDottedLineStrokeStyle::getParamCount() const -{ - return 4; +int TDottedLineStrokeStyle::getParamCount() const { return 4; } + +//----------------------------------------------------------------------------- + +TColorStyle::ParamType TDottedLineStrokeStyle::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -TColorStyle::ParamType TDottedLineStrokeStyle::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +QString TDottedLineStrokeStyle::getParamNames(int index) const { + assert(0 <= index && index < 4); + QString value; + switch (index) { + case 0: + value = QCoreApplication::translate("TDottedLineStrokeStyle", "Fade In"); + break; + case 1: + value = QCoreApplication::translate("TDottedLineStrokeStyle", "Dash"); + break; + case 2: + value = QCoreApplication::translate("TDottedLineStrokeStyle", "Fade Out"); + break; + case 3: + value = QCoreApplication::translate("TDottedLineStrokeStyle", "Gap"); + break; + } + return value; +} + +//----------------------------------------------------------------------------- + +void TDottedLineStrokeStyle::getParamRange(int index, double &min, + double &max) const { + assert(0 <= index && index < 4); + switch (index) { + case 0: + min = 1.0; + max = 100.0; + break; + case 1: + min = 1.0; + max = 100.0; + break; + case 2: + min = 1.; + max = 100.0; + break; + case 3: + min = 0.0; + max = 100.0; + break; + } } //----------------------------------------------------------------------------- -QString TDottedLineStrokeStyle::getParamNames(int index) const -{ - assert(0 <= index && index < 4); - QString value; - switch (index) { - case 0: - value = QCoreApplication::translate("TDottedLineStrokeStyle", "Fade In"); - break; - case 1: - value = QCoreApplication::translate("TDottedLineStrokeStyle", "Dash"); - break; - case 2: - value = QCoreApplication::translate("TDottedLineStrokeStyle", "Fade Out"); - break; - case 3: - value = QCoreApplication::translate("TDottedLineStrokeStyle", "Gap"); - break; - } - return value; -} - -//----------------------------------------------------------------------------- - -void TDottedLineStrokeStyle::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 4); - switch (index) { - case 0: - min = 1.0; - max = 100.0; - break; - case 1: - min = 1.0; - max = 100.0; - break; - case 2: - min = 1.; - max = 100.0; - break; - case 3: - min = 0.0; - max = 100.0; - break; - } -} - -//----------------------------------------------------------------------------- - -double TDottedLineStrokeStyle::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 4); - double value = 0; - switch (index) { - case 0: - value = m_in; - break; - case 1: - value = m_line; - break; - case 2: - value = m_out; - break; - case 3: - value = m_blank; - break; - } - return value; -} - -//----------------------------------------------------------------------------- - -void TDottedLineStrokeStyle::setParamValue(int index, double value) -{ - assert(0 <= index && index < 4); - switch (index) { - case 0: - m_in = value; - break; - case 1: - m_line = value; - break; - case 2: - m_out = value; - break; - case 3: - m_blank = value; - break; - } - updateVersionNumber(); +double TDottedLineStrokeStyle::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 4); + double value = 0; + switch (index) { + case 0: + value = m_in; + break; + case 1: + value = m_line; + break; + case 2: + value = m_out; + break; + case 3: + value = m_blank; + break; + } + return value; +} + +//----------------------------------------------------------------------------- + +void TDottedLineStrokeStyle::setParamValue(int index, double value) { + assert(0 <= index && index < 4); + switch (index) { + case 0: + m_in = value; + break; + case 1: + m_line = value; + break; + case 2: + m_out = value; + break; + case 3: + m_blank = value; + break; + } + updateVersionNumber(); } //----------------------------------------------------------------------------- void TDottedLineStrokeStyle::computeData(Points &positions, - const TStroke *stroke, - const TColorFunction *cf) const -{ - double length = stroke->getLength(); - - double step = 5.0; - double linemax = m_line; - double inmax = (m_in / 100); - double outmax = (m_out / 100); - double blankmax = m_blank; - double total = 0; - TRandom rnd; - - positions.clear(); - positions.reserve(tceil(length / step) + 1); - - TPointD oldPos1, oldPos2, oldPos3, oldPos4, pos1, pos2, pos3, pos4; - //bool firstRing = true; - double s = 0; - double meter = 0; - double center = 0; - double slopetmp = 0; - double minthickness = MINTHICK * sqrt(tglGetPixelSize2()); - double thickness = 0; - double line = 0, in = 0, out = 0, blank = 0; - while (s <= length) { - double w = stroke->getParameterAtLength(s); - if (w < 0) { - s += 0.1; - continue; - } // per tamponare il baco della getParameterAtLength() - TThickPoint pos = stroke->getThickPoint(w); - - if (pos.thick < MINTHICK) - thickness = minthickness; - else - thickness = pos.thick; - if (meter >= total) { - meter = 0; - - line = linemax * (1 + rnd.getFloat()) * thickness; - if (line > length - s) - line = length - s; - in = inmax * line; - out = outmax * line; - line = line - in - out; - blank = blankmax * (1 + rnd.getFloat()) * thickness; - if (in + out > length) { - in = rnd.getFloat() * (length / 2); - out = length - in; - line = 0; - } - total = in + line + out + blank; - } else if (meter > in + line + out + step) { - s += step; - meter += step; - continue; - } - TPointD u = stroke->getSpeed(w); - if (norm2(u) == 0) { - s += 0.1; - continue; - } // non dovrebbe succedere mai, ma per prudenza.... - u = normalize(u); - double slope = 0; - slope = get_line_slope(meter, in, line, out); - slopetmp = slope; - TPointD v = rotate90(u) * (thickness)*slope; - if (pos.thick * slope < 1) - center = 0.0; - else - center = 0.5; - pos1 = pos + v; - pos2 = pos + v * 0.5; - pos3 = pos - v * 0.5; - pos4 = pos - v; - - positions.push_back(pos1); - positions.push_back(pos2); - positions.push_back(pos3); - positions.push_back(pos4); - - s += step; - meter += step; - } -} - -//----------------------------------------------------------------------------- - -void TDottedLineStrokeStyle::drawStroke(const TColorFunction *cf, Points &positions, const TStroke *stroke) const -{ - TPixel32 color; - if (cf) - color = (*(cf))(m_color); - else - color = m_color; - - for (UINT i = 4; i < positions.size(); i += 4) { - glBegin(GL_QUAD_STRIP); - glColor4ub(color.r, color.g, color.b, 0); - tglVertex(positions[i - 4]); - tglVertex(positions[i]); - glColor4ub(color.r, color.g, color.b, color.m); - tglVertex(positions[i - 3]); - tglVertex(positions[i + 1]); - tglVertex(positions[i - 2]); - tglVertex(positions[i + 2]); - glColor4ub(color.r, color.g, color.b, 0); - tglVertex(positions[i - 1]); - tglVertex(positions[i + 3]); - glEnd(); - } -} - -//----------------------------------------------------------------------------- - -void TDottedLineStrokeStyle::drawStroke(TFlash &flash, const TStroke *stroke) const -{ - //TStroke *stroke = getStroke(); - double length = stroke->getLength(); - - double step = 5.0; - double linemax = m_line; - double inmax = m_in / 100; - double outmax = m_out / 100; - double blankmax = m_blank; - double total = 0; - TRandom rnd; - - TPixel32 color = m_color; - TPixel32 color_transp(color.r, color.g, color.b, 0); - - TPointD oldPos1, oldPos2, oldPos3, oldPos4, pos1, pos2, pos3, pos4; - bool firstRing = true; - double s = 0; - double meter = 0; - double center = 0; - double slopetmp = 0; - double minthickness = MINTHICK; - double thickness = 0; - SFlashUtils sfu; - flash.setThickness(0.0); - while (s <= length) { - double w = stroke->getParameterAtLength(s); - if (w < 0) { - s += 0.1; - continue; - } // per tamponare il baco della getParameterAtLength() - TThickPoint pos = stroke->getThickPoint(w); - double line = 0, in = 0, out = 0, blank = 0; - if (pos.thick < MINTHICK) - thickness = minthickness; - else - thickness = pos.thick; - - if (meter >= total) { - meter = 0; - - line = linemax * (1 + rnd.getFloat()) * thickness; - if (line > length - s) - line = length - s; - in = inmax * line; - out = outmax * line; - line = line - in - out; - blank = blankmax * (1 + rnd.getFloat()) * thickness; - /* --- OLD Version --- - line=linemax*(1+rnd.getFloat()); - in=inmax*(1+rnd.getFloat())*pos.thick; - out=outmax*(1+rnd.getFloat())*pos.thick; - blank=blankmax*(1+rnd.getFloat())*pos.thick; + const TStroke *stroke, + const TColorFunction *cf) const { + double length = stroke->getLength(); + + double step = 5.0; + double linemax = m_line; + double inmax = (m_in / 100); + double outmax = (m_out / 100); + double blankmax = m_blank; + double total = 0; + TRandom rnd; + + positions.clear(); + positions.reserve(tceil(length / step) + 1); + + TPointD oldPos1, oldPos2, oldPos3, oldPos4, pos1, pos2, pos3, pos4; + // bool firstRing = true; + double s = 0; + double meter = 0; + double center = 0; + double slopetmp = 0; + double minthickness = MINTHICK * sqrt(tglGetPixelSize2()); + double thickness = 0; + double line = 0, in = 0, out = 0, blank = 0; + while (s <= length) { + double w = stroke->getParameterAtLength(s); + if (w < 0) { + s += 0.1; + continue; + } // per tamponare il baco della getParameterAtLength() + TThickPoint pos = stroke->getThickPoint(w); + + if (pos.thick < MINTHICK) + thickness = minthickness; + else + thickness = pos.thick; + if (meter >= total) { + meter = 0; + + line = linemax * (1 + rnd.getFloat()) * thickness; + if (line > length - s) line = length - s; + in = inmax * line; + out = outmax * line; + line = line - in - out; + blank = blankmax * (1 + rnd.getFloat()) * thickness; + if (in + out > length) { + in = rnd.getFloat() * (length / 2); + out = length - in; + line = 0; + } + total = in + line + out + blank; + } else if (meter > in + line + out + step) { + s += step; + meter += step; + continue; + } + TPointD u = stroke->getSpeed(w); + if (norm2(u) == 0) { + s += 0.1; + continue; + } // non dovrebbe succedere mai, ma per prudenza.... + u = normalize(u); + double slope = 0; + slope = get_line_slope(meter, in, line, out); + slopetmp = slope; + TPointD v = rotate90(u) * (thickness)*slope; + if (pos.thick * slope < 1) + center = 0.0; + else + center = 0.5; + pos1 = pos + v; + pos2 = pos + v * 0.5; + pos3 = pos - v * 0.5; + pos4 = pos - v; + + positions.push_back(pos1); + positions.push_back(pos2); + positions.push_back(pos3); + positions.push_back(pos4); + + s += step; + meter += step; + } +} + +//----------------------------------------------------------------------------- + +void TDottedLineStrokeStyle::drawStroke(const TColorFunction *cf, + Points &positions, + const TStroke *stroke) const { + TPixel32 color; + if (cf) + color = (*(cf))(m_color); + else + color = m_color; + + for (UINT i = 4; i < positions.size(); i += 4) { + glBegin(GL_QUAD_STRIP); + glColor4ub(color.r, color.g, color.b, 0); + tglVertex(positions[i - 4]); + tglVertex(positions[i]); + glColor4ub(color.r, color.g, color.b, color.m); + tglVertex(positions[i - 3]); + tglVertex(positions[i + 1]); + tglVertex(positions[i - 2]); + tglVertex(positions[i + 2]); + glColor4ub(color.r, color.g, color.b, 0); + tglVertex(positions[i - 1]); + tglVertex(positions[i + 3]); + glEnd(); + } +} + +//----------------------------------------------------------------------------- + +void TDottedLineStrokeStyle::drawStroke(TFlash &flash, + const TStroke *stroke) const { + // TStroke *stroke = getStroke(); + double length = stroke->getLength(); + + double step = 5.0; + double linemax = m_line; + double inmax = m_in / 100; + double outmax = m_out / 100; + double blankmax = m_blank; + double total = 0; + TRandom rnd; + + TPixel32 color = m_color; + TPixel32 color_transp(color.r, color.g, color.b, 0); + + TPointD oldPos1, oldPos2, oldPos3, oldPos4, pos1, pos2, pos3, pos4; + bool firstRing = true; + double s = 0; + double meter = 0; + double center = 0; + double slopetmp = 0; + double minthickness = MINTHICK; + double thickness = 0; + SFlashUtils sfu; + flash.setThickness(0.0); + while (s <= length) { + double w = stroke->getParameterAtLength(s); + if (w < 0) { + s += 0.1; + continue; + } // per tamponare il baco della getParameterAtLength() + TThickPoint pos = stroke->getThickPoint(w); + double line = 0, in = 0, out = 0, blank = 0; + if (pos.thick < MINTHICK) + thickness = minthickness; + else + thickness = pos.thick; + + if (meter >= total) { + meter = 0; + + line = linemax * (1 + rnd.getFloat()) * thickness; + if (line > length - s) line = length - s; + in = inmax * line; + out = outmax * line; + line = line - in - out; + blank = blankmax * (1 + rnd.getFloat()) * thickness; + /* --- OLD Version --- +line=linemax*(1+rnd.getFloat()); +in=inmax*(1+rnd.getFloat())*pos.thick; +out=outmax*(1+rnd.getFloat())*pos.thick; +blank=blankmax*(1+rnd.getFloat())*pos.thick; */ - if (in + out > length) { - in = rnd.getFloat() * (length / 2); - out = length - in; - line = 0; - } - total = in + line + out + blank; - } else if (meter > in + line + out + step) { - s += step; - meter += step; - continue; - } - TPointD u = stroke->getSpeed(w); - if (norm2(u) == 0) { - s += 0.1; - continue; - } // non dovrebbe succedere mai, ma per prudenza.... - u = normalize(u); - double slope = 0; - if (s <= length - out) { - slope = get_line_slope(meter, in, line, out); - slopetmp = slope; - } else - slope = (length - s) * (slopetmp / out); - TPointD v = rotate90(u) * (pos.thick) * slope; - if (pos.thick * slope < 1) - center = 0.0; - else - center = 0.5; - pos1 = pos + v; - pos2 = pos + v * 0.5; - pos3 = pos - v * 0.5; - pos4 = pos - v; - if (firstRing) { - firstRing = false; - } else { - - vector pv; - pv.push_back(oldPos1); - pv.push_back(pos1); - pv.push_back(pos2); - pv.push_back(oldPos2); - sfu.drawGradedPolyline(flash, pv, color_transp, color); - - pv.clear(); - pv.push_back(oldPos2); - pv.push_back(pos2); - pv.push_back(pos3); - pv.push_back(oldPos3); - flash.setFillColor(color); - flash.drawPolyline(pv); - - pv.clear(); - pv.push_back(oldPos3); - pv.push_back(pos3); - pv.push_back(pos4); - pv.push_back(oldPos4); - sfu.drawGradedPolyline(flash, pv, color, color_transp); - } - oldPos1 = pos1; - oldPos2 = pos2; - oldPos3 = pos3; - oldPos4 = pos4; - s += step; - meter += step; - } + if (in + out > length) { + in = rnd.getFloat() * (length / 2); + out = length - in; + line = 0; + } + total = in + line + out + blank; + } else if (meter > in + line + out + step) { + s += step; + meter += step; + continue; + } + TPointD u = stroke->getSpeed(w); + if (norm2(u) == 0) { + s += 0.1; + continue; + } // non dovrebbe succedere mai, ma per prudenza.... + u = normalize(u); + double slope = 0; + if (s <= length - out) { + slope = get_line_slope(meter, in, line, out); + slopetmp = slope; + } else + slope = (length - s) * (slopetmp / out); + TPointD v = rotate90(u) * (pos.thick) * slope; + if (pos.thick * slope < 1) + center = 0.0; + else + center = 0.5; + pos1 = pos + v; + pos2 = pos + v * 0.5; + pos3 = pos - v * 0.5; + pos4 = pos - v; + if (firstRing) { + firstRing = false; + } else { + vector pv; + pv.push_back(oldPos1); + pv.push_back(pos1); + pv.push_back(pos2); + pv.push_back(oldPos2); + sfu.drawGradedPolyline(flash, pv, color_transp, color); + + pv.clear(); + pv.push_back(oldPos2); + pv.push_back(pos2); + pv.push_back(pos3); + pv.push_back(oldPos3); + flash.setFillColor(color); + flash.drawPolyline(pv); + + pv.clear(); + pv.push_back(oldPos3); + pv.push_back(pos3); + pv.push_back(pos4); + pv.push_back(oldPos4); + sfu.drawGradedPolyline(flash, pv, color, color_transp); + } + oldPos1 = pos1; + oldPos2 = pos2; + oldPos3 = pos3; + oldPos4 = pos4; + s += step; + meter += step; + } } //============================================================================= TRopeStrokeStyle::TRopeStrokeStyle() - : m_color(TPixel32(255, 135, 0)), m_bend(0.4) -{ -} + : m_color(TPixel32(255, 135, 0)), m_bend(0.4) {} //----------------------------------------------------------------------------- -TColorStyle *TRopeStrokeStyle::clone() const -{ - return new TRopeStrokeStyle(*this); +TColorStyle *TRopeStrokeStyle::clone() const { + return new TRopeStrokeStyle(*this); } //----------------------------------------------------------------------------- -int TRopeStrokeStyle::getParamCount() const -{ - return 1; -} +int TRopeStrokeStyle::getParamCount() const { return 1; } //----------------------------------------------------------------------------- -TColorStyle::ParamType TRopeStrokeStyle::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +TColorStyle::ParamType TRopeStrokeStyle::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -QString TRopeStrokeStyle::getParamNames(int index) const -{ - assert(0 <= index && index < 1); - return QCoreApplication::translate("TRopeStrokeStyle", "Tilt"); +QString TRopeStrokeStyle::getParamNames(int index) const { + assert(0 <= index && index < 1); + return QCoreApplication::translate("TRopeStrokeStyle", "Tilt"); } //----------------------------------------------------------------------------- -void TRopeStrokeStyle::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 1); - min = -1.0; - max = 1.0; +void TRopeStrokeStyle::getParamRange(int index, double &min, + double &max) const { + assert(0 <= index && index < 1); + min = -1.0; + max = 1.0; } //----------------------------------------------------------------------------- -double TRopeStrokeStyle::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 1); - return m_bend; +double TRopeStrokeStyle::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 1); + return m_bend; } //----------------------------------------------------------------------------- -void TRopeStrokeStyle::setParamValue(int index, double value) -{ - assert(0 <= index && index < 1); - m_bend = value; - updateVersionNumber(); +void TRopeStrokeStyle::setParamValue(int index, double value) { + assert(0 <= index && index < 1); + m_bend = value; + updateVersionNumber(); } //----------------------------------------------------------------------------- -void TRopeStrokeStyle::computeData(Points &positions, - const TStroke *stroke, - const TColorFunction *cf) const -{ - double length = stroke->getLength(); - // spessore della catena = spessore "medio" dello stroke - double step = 10.0; - double bend; - double bump; - double bump_max = step / 4; - - positions.clear(); - positions.reserve(tceil(length / step) + 1); - - TPointD oldPos1, oldPos2; - bool firstRing = true; - double s = 0; - while (s <= length) { - double w = stroke->getParameterAtLength(s); - if (w < 0) { - s += 0.1; - continue; - } // per tamponare il baco della getParameterAtLength() - TThickPoint pos = stroke->getThickPoint(w); - TPointD u = stroke->getSpeed(w); - if (norm2(u) == 0) { - s += 0.1; - continue; - } // non dovrebbe succedere mai, ma per prudenza.... - u = normalize(u); - bend = pos.thick * m_bend; - bump = pos.thick * 0.3; - if (bump >= bump_max) - bump = bump_max; - TPointD v = rotate90(u) * pos.thick; - TPointD v1 = v * 0.2; - if (firstRing) { - firstRing = false; - } else { - positions.push_back(pos + (bend + bump) * u + v - v1); - positions.push_back(pos + (bend)*u + v); - positions.push_back(oldPos1 + (bump)*u + v1); - positions.push_back(oldPos1); - positions.push_back(oldPos2); - positions.push_back(oldPos2 + bump * u - v1); - positions.push_back(pos + u * (-bend) - v); - positions.push_back(pos + u * (bump - bend) - v + v1); - } - oldPos1 = pos + (bend + bump) * u + v - v1; - oldPos2 = pos + u * (bump - bend) - v + v1; - s += step; - } - positions.push_back(oldPos1); - positions.push_back(oldPos2); -} - -//----------------------------------------------------------------------------- - -void TRopeStrokeStyle::drawStroke(const TColorFunction *cf, Points &positions, const TStroke *stroke) const -{ - if (positions.size() <= 1) - return; - TPixel32 color; - if (cf) - color = (*(cf))(m_color); - else - color = m_color; +void TRopeStrokeStyle::computeData(Points &positions, const TStroke *stroke, + const TColorFunction *cf) const { + double length = stroke->getLength(); + // spessore della catena = spessore "medio" dello stroke + double step = 10.0; + double bend; + double bump; + double bump_max = step / 4; - // GLuint rope_id; + positions.clear(); + positions.reserve(tceil(length / step) + 1); - TPixel32 blackcolor(TPixel32::Black); - if (cf) - blackcolor = (*(cf))(blackcolor); - else - blackcolor = blackcolor; + TPointD oldPos1, oldPos2; + bool firstRing = true; + double s = 0; + while (s <= length) { + double w = stroke->getParameterAtLength(s); + if (w < 0) { + s += 0.1; + continue; + } // per tamponare il baco della getParameterAtLength() + TThickPoint pos = stroke->getThickPoint(w); + TPointD u = stroke->getSpeed(w); + if (norm2(u) == 0) { + s += 0.1; + continue; + } // non dovrebbe succedere mai, ma per prudenza.... + u = normalize(u); + bend = pos.thick * m_bend; + bump = pos.thick * 0.3; + if (bump >= bump_max) bump = bump_max; + TPointD v = rotate90(u) * pos.thick; + TPointD v1 = v * 0.2; + if (firstRing) { + firstRing = false; + } else { + positions.push_back(pos + (bend + bump) * u + v - v1); + positions.push_back(pos + (bend)*u + v); + positions.push_back(oldPos1 + (bump)*u + v1); + positions.push_back(oldPos1); + positions.push_back(oldPos2); + positions.push_back(oldPos2 + bump * u - v1); + positions.push_back(pos + u * (-bend) - v); + positions.push_back(pos + u * (bump - bend) - v + v1); + } + oldPos1 = pos + (bend + bump) * u + v - v1; + oldPos2 = pos + u * (bump - bend) - v + v1; + s += step; + } + positions.push_back(oldPos1); + positions.push_back(oldPos2); +} + +//----------------------------------------------------------------------------- + +void TRopeStrokeStyle::drawStroke(const TColorFunction *cf, Points &positions, + const TStroke *stroke) const { + if (positions.size() <= 1) return; + TPixel32 color; + if (cf) + color = (*(cf))(m_color); + else + color = m_color; + + // GLuint rope_id; + + TPixel32 blackcolor(TPixel32::Black); + if (cf) + blackcolor = (*(cf))(blackcolor); + else + blackcolor = blackcolor; + + // rope_id = glGenLists(1); + + static const int stride = sizeof(TPointD); + glEnableClientState(GL_VERTEX_ARRAY); + + UINT i = 0; + for (; i < positions.size() - 2; i += 8) { + /* +glNewList(rope_id,GL_COMPILE); + tglVertex(positions[i]); + tglVertex(positions[i+1]); + tglVertex(positions[i+2]); + tglVertex(positions[i+3]); + tglVertex(positions[i+4]); + tglVertex(positions[i+5]); + tglVertex(positions[i+6]); + tglVertex(positions[i+7]); +glEndList(); +*/ + tglColor(color); + // glBegin(GL_POLYGON); - //rope_id = glGenLists(1); + glVertexPointer(2, GL_DOUBLE, stride, &positions[i]); + glDrawArrays(GL_POLYGON, 0, 8); - static const int stride = sizeof(TPointD); - glEnableClientState(GL_VERTEX_ARRAY); + // glCallList(rope_id); + // glEnd(); - UINT i = 0; - for (; i < positions.size() - 2; i += 8) { - /* - glNewList(rope_id,GL_COMPILE); - tglVertex(positions[i]); - tglVertex(positions[i+1]); - tglVertex(positions[i+2]); - tglVertex(positions[i+3]); - tglVertex(positions[i+4]); - tglVertex(positions[i+5]); - tglVertex(positions[i+6]); - tglVertex(positions[i+7]); - glEndList(); - */ - tglColor(color); - //glBegin(GL_POLYGON); + tglColor(blackcolor); - glVertexPointer(2, GL_DOUBLE, stride, &positions[i]); - glDrawArrays(GL_POLYGON, 0, 8); + // glBegin(GL_LINE_STRIP); + glVertexPointer(2, GL_DOUBLE, stride, &positions[i]); + glDrawArrays(GL_LINE_STRIP, 0, 8); - //glCallList(rope_id); - //glEnd(); + // glCallList(rope_id); + // glEnd(); + } - tglColor(blackcolor); + glDisableClientState(GL_VERTEX_ARRAY); - //glBegin(GL_LINE_STRIP); - glVertexPointer(2, GL_DOUBLE, stride, &positions[i]); - glDrawArrays(GL_LINE_STRIP, 0, 8); + glBegin(GL_LINE_STRIP); + tglVertex(positions[i]); + tglVertex(positions[i + 1]); + glEnd(); - //glCallList(rope_id); - //glEnd(); - } + // glDeleteLists(rope_id,1); +} + +//----------------------------------------------------------------------------- + +void TRopeStrokeStyle::drawStroke(TFlash &flash, const TStroke *stroke) const { + // TStroke *stroke = getStroke(); + double length = stroke->getLength(); + + // spessore della catena = spessore "medio" dello stroke + + double step = 10.0; + double bend; + double bump; + double bump_max = step / 4; + + TPixel32 color = m_color; + TPixel32 blackcolor(TPixel32::Black); + + TPointD oldPos1, oldPos2; + bool firstRing = true; + double s = 0; + while (s <= length) { + double w = stroke->getParameterAtLength(s); + if (w < 0) { + s += 0.1; + continue; + } // per tamponare il baco della getParameterAtLength() + TThickPoint pos = stroke->getThickPoint(w); + TPointD u = stroke->getSpeed(w); + if (norm2(u) == 0) { + s += 0.1; + continue; + } // non dovrebbe succedere mai, ma per prudenza.... + u = normalize(u); + bend = pos.thick * m_bend; + bump = pos.thick * 0.3; + if (bump >= bump_max) bump = bump_max; + TPointD v = rotate90(u) * pos.thick; + TPointD v1 = v * 0.2; + if (firstRing) { + firstRing = false; + } else { + const int nbpp = 8; + TPointD pp[nbpp]; + pp[0] = (pos + (bend + bump) * u + v - v1); + pp[1] = (pos + (bend)*u + v); + pp[2] = (oldPos1 + (bump)*u + v1); + pp[3] = (oldPos1); + pp[4] = (oldPos2); + pp[5] = (oldPos2 + bump * u - v1); + pp[6] = (pos + u * (-bend) - v); + pp[7] = (pos + u * (bump - bend) - v + v1); + + vector pv; + int i; + for (i = 0; i < nbpp; i++) pv.push_back(pp[i]); + + flash.setFillColor(color); + flash.drawPolyline(pv); + + vector sv; + for (i = 0; i < (nbpp - 1); i++) sv.push_back(TSegment(pp[i], pp[i + 1])); + flash.setThickness(1.0); + flash.setLineColor(blackcolor); + flash.drawSegments(sv, false); + } + oldPos1 = pos + (bend + bump) * u + v - v1; + oldPos2 = pos + u * (bump - bend) - v + v1; + s += step; + } - glDisableClientState(GL_VERTEX_ARRAY); + vector sv; + sv.push_back(TSegment(oldPos1, oldPos2)); + flash.setLineColor(blackcolor); + flash.drawSegments(sv, false); +} - glBegin(GL_LINE_STRIP); - tglVertex(positions[i]); - tglVertex(positions[i + 1]); - glEnd(); +//============================================================================= - //glDeleteLists(rope_id,1); -} +TCrystallizeStrokeStyle::TCrystallizeStrokeStyle() + : m_color(TPixel32(255, 150, 150, 255)), m_period(10.0), m_opacity(0.5) {} //----------------------------------------------------------------------------- -void TRopeStrokeStyle::drawStroke(TFlash &flash, const TStroke *stroke) const -{ - //TStroke *stroke = getStroke(); - double length = stroke->getLength(); - - // spessore della catena = spessore "medio" dello stroke - - double step = 10.0; - double bend; - double bump; - double bump_max = step / 4; - - TPixel32 color = m_color; - TPixel32 blackcolor(TPixel32::Black); - - TPointD oldPos1, oldPos2; - bool firstRing = true; - double s = 0; - while (s <= length) { - double w = stroke->getParameterAtLength(s); - if (w < 0) { - s += 0.1; - continue; - } // per tamponare il baco della getParameterAtLength() - TThickPoint pos = stroke->getThickPoint(w); - TPointD u = stroke->getSpeed(w); - if (norm2(u) == 0) { - s += 0.1; - continue; - } // non dovrebbe succedere mai, ma per prudenza.... - u = normalize(u); - bend = pos.thick * m_bend; - bump = pos.thick * 0.3; - if (bump >= bump_max) - bump = bump_max; - TPointD v = rotate90(u) * pos.thick; - TPointD v1 = v * 0.2; - if (firstRing) { - firstRing = false; - } else { - const int nbpp = 8; - TPointD pp[nbpp]; - pp[0] = (pos + (bend + bump) * u + v - v1); - pp[1] = (pos + (bend)*u + v); - pp[2] = (oldPos1 + (bump)*u + v1); - pp[3] = (oldPos1); - pp[4] = (oldPos2); - pp[5] = (oldPos2 + bump * u - v1); - pp[6] = (pos + u * (-bend) - v); - pp[7] = (pos + u * (bump - bend) - v + v1); - - vector pv; - int i; - for (i = 0; i < nbpp; i++) - pv.push_back(pp[i]); - - flash.setFillColor(color); - flash.drawPolyline(pv); - - vector sv; - for (i = 0; i < (nbpp - 1); i++) - sv.push_back(TSegment(pp[i], pp[i + 1])); - flash.setThickness(1.0); - flash.setLineColor(blackcolor); - flash.drawSegments(sv, false); - } - oldPos1 = pos + (bend + bump) * u + v - v1; - oldPos2 = pos + u * (bump - bend) - v + v1; - s += step; - } - - vector sv; - sv.push_back(TSegment(oldPos1, oldPos2)); - flash.setLineColor(blackcolor); - flash.drawSegments(sv, false); +TColorStyle *TCrystallizeStrokeStyle::clone() const { + return new TCrystallizeStrokeStyle(*this); } -//============================================================================= +//----------------------------------------------------------------------------- -TCrystallizeStrokeStyle::TCrystallizeStrokeStyle() - : m_color(TPixel32(255, 150, 150, 255)), m_period(10.0), m_opacity(0.5) -{ -} +int TCrystallizeStrokeStyle::getParamCount() const { return 2; } //----------------------------------------------------------------------------- -TColorStyle *TCrystallizeStrokeStyle::clone() const -{ - return new TCrystallizeStrokeStyle(*this); +TColorStyle::ParamType TCrystallizeStrokeStyle::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -int TCrystallizeStrokeStyle::getParamCount() const -{ - return 2; +QString TCrystallizeStrokeStyle::getParamNames(int index) const { + assert(0 <= index && index < 2); + return index == 0 + ? QCoreApplication::translate("TCrystallizeStrokeStyle", "Crease") + : QCoreApplication::translate("TCrystallizeStrokeStyle", + "Opacity"); } //----------------------------------------------------------------------------- -TColorStyle::ParamType TCrystallizeStrokeStyle::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +void TCrystallizeStrokeStyle::getParamRange(int index, double &min, + double &max) const { + assert(0 <= index && index < 2); + if (index == 0) { + min = 1.0; + max = 100.0; + } else { + min = 0.0; + max = 1.0; + } } //----------------------------------------------------------------------------- -QString TCrystallizeStrokeStyle::getParamNames(int index) const -{ - assert(0 <= index && index < 2); - return index == 0 ? QCoreApplication::translate("TCrystallizeStrokeStyle", "Crease") : QCoreApplication::translate("TCrystallizeStrokeStyle", "Opacity"); +double TCrystallizeStrokeStyle::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 2); + return index == 0 ? m_period : m_opacity; } //----------------------------------------------------------------------------- -void TCrystallizeStrokeStyle::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 2); - if (index == 0) { - min = 1.0; - max = 100.0; - } else { - min = 0.0; - max = 1.0; - } +void TCrystallizeStrokeStyle::setParamValue(int index, double value) { + assert(0 <= index && index < 2); + if (index == 0) + m_period = value; + else + m_opacity = value; + + // updateVersionNumber(); non serve perche' i parametri vengono sfrutttati + // direttamente nella draw } //----------------------------------------------------------------------------- -double TCrystallizeStrokeStyle::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 2); - return index == 0 ? m_period : m_opacity; +void TCrystallizeStrokeStyle::computeData(Points &positions, + const TStroke *stroke, + const TColorFunction *cf) const { + double length = stroke->getLength(); + double step = 10.0; + TRandom rnd; + positions.clear(); + positions.reserve(tceil((length + 1) / step)); + double s = 0; + while (s <= length) { + double w = stroke->getParameterAtLength(s); + if (w < 0) { + s += 0.1; + continue; + } // per tamponare il baco della getParameterAtLength() + TThickPoint pos = stroke->getThickPoint(w); + TPointD u = stroke->getSpeed(w); + if (norm2(u) == 0) { + s += 0.1; + continue; + } // non dovrebbe succedere mai, ma per prudenza.... + u = normalize(u); + TPointD v = rotate90(u) * (pos.thick / 2); + positions.push_back(pos + v * (1 + rnd.getFloat()) + + u * 2 * rnd.getFloat()); + positions.push_back(pos - v * (1 + rnd.getFloat()) - + u * 2 * rnd.getFloat()); + s += step; + } } //----------------------------------------------------------------------------- -void TCrystallizeStrokeStyle::setParamValue(int index, double value) -{ - assert(0 <= index && index < 2); - if (index == 0) - m_period = value; - else - m_opacity = value; +void TCrystallizeStrokeStyle::drawStroke(const TColorFunction *cf, + Points &positions, + const TStroke *stroke) const { + // double length = stroke->getLength(); + double step = 10.0; + double period = (101 - m_period) * step; + double counter = 0; + double opacity = m_opacity; + TRandom rnd; + + TPixel32 color; + if (cf) + color = (*(cf))(m_color); + else + color = m_color; - //updateVersionNumber(); non serve perche' i parametri vengono sfrutttati direttamente nella draw + TPixelD dcolor = toPixelD(color); + // double s = 0; + + glBegin(GL_QUAD_STRIP); + for (int i = 0; i < (int)positions.size() / 2; i++) { + if (counter > period) counter = 0; + glColor4d(dcolor.r, dcolor.g, dcolor.b, + (opacity + (counter / period) * rnd.getFloat()) * dcolor.m); + tglVertex(positions[i * 2]); + tglVertex(positions[i * 2 + 1]); + counter += step; + } + glEnd(); + counter = 0; + glColor4d(dcolor.r, dcolor.g, dcolor.b, dcolor.m); + for (int j = 1; j < (int)positions.size() / 2; j++) { + glBegin(GL_LINES); + tglVertex(positions[(j - 1) * 2]); + tglVertex(positions[j * 2]); + glEnd(); + glBegin(GL_LINES); + tglVertex(positions[(j - 1) * 2 + 1]); + tglVertex(positions[j * 2 + 1]); + glEnd(); + } } //----------------------------------------------------------------------------- -void TCrystallizeStrokeStyle::computeData(Points &positions, - const TStroke *stroke, - const TColorFunction *cf) const -{ - double length = stroke->getLength(); - double step = 10.0; - TRandom rnd; - positions.clear(); - positions.reserve(tceil((length + 1) / step)); - double s = 0; - while (s <= length) { - double w = stroke->getParameterAtLength(s); - if (w < 0) { - s += 0.1; - continue; - } // per tamponare il baco della getParameterAtLength() - TThickPoint pos = stroke->getThickPoint(w); - TPointD u = stroke->getSpeed(w); - if (norm2(u) == 0) { - s += 0.1; - continue; - } // non dovrebbe succedere mai, ma per prudenza.... - u = normalize(u); - TPointD v = rotate90(u) * (pos.thick / 2); - positions.push_back(pos + v * (1 + rnd.getFloat()) + u * 2 * rnd.getFloat()); - positions.push_back(pos - v * (1 + rnd.getFloat()) - u * 2 * rnd.getFloat()); - s += step; - } -} - -//----------------------------------------------------------------------------- - -void TCrystallizeStrokeStyle::drawStroke(const TColorFunction *cf, Points &positions, const TStroke *stroke) const -{ - //double length = stroke->getLength(); - double step = 10.0; - double period = (101 - m_period) * step; - double counter = 0; - double opacity = m_opacity; - TRandom rnd; - - TPixel32 color; - if (cf) - color = (*(cf))(m_color); - else - color = m_color; - - TPixelD dcolor = toPixelD(color); - //double s = 0; - - glBegin(GL_QUAD_STRIP); - for (int i = 0; i < (int)positions.size() / 2; i++) { - if (counter > period) - counter = 0; - glColor4d(dcolor.r, dcolor.g, dcolor.b, (opacity + (counter / period) * rnd.getFloat()) * dcolor.m); - tglVertex(positions[i * 2]); - tglVertex(positions[i * 2 + 1]); - counter += step; - } - glEnd(); - counter = 0; - glColor4d(dcolor.r, dcolor.g, dcolor.b, dcolor.m); - for (int j = 1; j < (int)positions.size() / 2; j++) { - glBegin(GL_LINES); - tglVertex(positions[(j - 1) * 2]); - tglVertex(positions[j * 2]); - glEnd(); - glBegin(GL_LINES); - tglVertex(positions[(j - 1) * 2 + 1]); - tglVertex(positions[j * 2 + 1]); - glEnd(); - } -} - -//----------------------------------------------------------------------------- - -void TCrystallizeStrokeStyle::drawStroke(TFlash &flash, const TStroke *stroke) const -{ - double length = stroke->getLength(); - double step = 10.0; - double period = m_period * step; - double counter = 0; - double opacity = m_opacity; - TRandom rnd; - // const double flashGrad=16384.0; - - TPixel32 color = m_color; - - TPixelD dcolor = toPixelD(color); - vector points1; - vector points2; - double s = 0; - while (s <= length) { - double w = stroke->getParameterAtLength(s); - if (w < 0) { - s += 0.1; - continue; - } // per tamponare il baco della getParameterAtLength() - TThickPoint pos = stroke->getThickPoint(w); - TPointD u = stroke->getSpeed(w); - if (norm2(u) == 0) { - s += 0.1; - continue; - } // non dovrebbe succedere mai, ma per prudenza.... - u = normalize(u); - TPointD v = rotate90(u) * (pos.thick / 2); - points1.push_back(pos + v * (1 + rnd.getFloat()) + u * 2 * rnd.getFloat()); - points2.push_back(pos - v * (1 + rnd.getFloat()) - u * 2 * rnd.getFloat()); - s += step; - } - - // Just for the polygon grading function - // SRegionDrawInFlash rdf; - SFlashUtils sfu; - TPixelD ldcolorPrev = dcolor; - ldcolorPrev.m = (opacity + (0.0 / period) * rnd.getFloat()) * dcolor.m; - flash.setThickness(0.0); - for (int i = 0; i < (int)(points1.size() - 1); i++) { - if (counter > period) - counter = 0; - TPixelD ldcolor = dcolor; - ldcolor.m = (opacity + (counter / period) * rnd.getFloat()) * dcolor.m; - - TPixel32 lcolorPrev; - lcolorPrev = toPixel32(ldcolorPrev); - TPixel32 lcolor; - lcolor = toPixel32(ldcolor); - - vector tpv; - tpv.push_back(points1[i]); - tpv.push_back(points2[i]); - tpv.push_back(points2[i + 1]); - tpv.push_back(points1[i + 1]); - - // Solid Color version - // flash.setFillColor(blend(lcolorPrev,lcolor,0.5)); - // flash.drawPolyline(tpv); - sfu.drawGradedPolyline(flash, tpv, lcolorPrev, lcolor); - - counter += step; - ldcolorPrev = ldcolor; - } - - counter = 0; - vector tsv1, tsv2; - for (int j = 1; j < (int)points1.size(); j++) { - tsv1.push_back(TSegment(points1[j - 1], points1[j])); - tsv2.push_back(TSegment(points2[j - 1], points2[j])); - } - flash.setThickness(1.0); - flash.setLineColor(color); - flash.drawSegments(tsv1, false); - flash.drawSegments(tsv2, false); +void TCrystallizeStrokeStyle::drawStroke(TFlash &flash, + const TStroke *stroke) const { + double length = stroke->getLength(); + double step = 10.0; + double period = m_period * step; + double counter = 0; + double opacity = m_opacity; + TRandom rnd; + // const double flashGrad=16384.0; + + TPixel32 color = m_color; + + TPixelD dcolor = toPixelD(color); + vector points1; + vector points2; + double s = 0; + while (s <= length) { + double w = stroke->getParameterAtLength(s); + if (w < 0) { + s += 0.1; + continue; + } // per tamponare il baco della getParameterAtLength() + TThickPoint pos = stroke->getThickPoint(w); + TPointD u = stroke->getSpeed(w); + if (norm2(u) == 0) { + s += 0.1; + continue; + } // non dovrebbe succedere mai, ma per prudenza.... + u = normalize(u); + TPointD v = rotate90(u) * (pos.thick / 2); + points1.push_back(pos + v * (1 + rnd.getFloat()) + u * 2 * rnd.getFloat()); + points2.push_back(pos - v * (1 + rnd.getFloat()) - u * 2 * rnd.getFloat()); + s += step; + } + + // Just for the polygon grading function + // SRegionDrawInFlash rdf; + SFlashUtils sfu; + TPixelD ldcolorPrev = dcolor; + ldcolorPrev.m = (opacity + (0.0 / period) * rnd.getFloat()) * dcolor.m; + flash.setThickness(0.0); + for (int i = 0; i < (int)(points1.size() - 1); i++) { + if (counter > period) counter = 0; + TPixelD ldcolor = dcolor; + ldcolor.m = (opacity + (counter / period) * rnd.getFloat()) * dcolor.m; + + TPixel32 lcolorPrev; + lcolorPrev = toPixel32(ldcolorPrev); + TPixel32 lcolor; + lcolor = toPixel32(ldcolor); + + vector tpv; + tpv.push_back(points1[i]); + tpv.push_back(points2[i]); + tpv.push_back(points2[i + 1]); + tpv.push_back(points1[i + 1]); + + // Solid Color version + // flash.setFillColor(blend(lcolorPrev,lcolor,0.5)); + // flash.drawPolyline(tpv); + sfu.drawGradedPolyline(flash, tpv, lcolorPrev, lcolor); + + counter += step; + ldcolorPrev = ldcolor; + } + + counter = 0; + vector tsv1, tsv2; + for (int j = 1; j < (int)points1.size(); j++) { + tsv1.push_back(TSegment(points1[j - 1], points1[j])); + tsv2.push_back(TSegment(points2[j - 1], points2[j])); + } + flash.setThickness(1.0); + flash.setLineColor(color); + flash.drawSegments(tsv1, false); + flash.drawSegments(tsv2, false); } //============================================================================= -namespace -{ +namespace { -class Stripe -{ +class Stripe { public: - TPointD oldpos1; - TPointD oldpos2; - TPointD pos1; - TPointD pos2; - int phase; - TPixel32 color; - Stripe(); - void drawpolygon(); - void drawpolygon(TFlash &flash); - void drawlines(TPixel32 blackcolor); - void addToSegment(vector *sv, vector &scontour, TPixel32 *colors); + TPointD oldpos1; + TPointD oldpos2; + TPointD pos1; + TPointD pos2; + int phase; + TPixel32 color; + Stripe(); + void drawpolygon(); + void drawpolygon(TFlash &flash); + void drawlines(TPixel32 blackcolor); + void addToSegment(vector *sv, vector &scontour, + TPixel32 *colors); }; -Stripe::Stripe() -{ - oldpos1 = TPointD(0, 0); - oldpos2 = TPointD(0, 0); - pos1 = TPointD(0, 0); - pos2 = TPointD(0, 0); - color = TPixel32(0, 0, 0); - phase = 0; -} - -void Stripe::drawpolygon() -{ - - tglColor(color); - glBegin(GL_POLYGON); - tglVertex(oldpos1); - tglVertex(pos1); - tglVertex(pos2); - tglVertex(oldpos2); - glEnd(); +Stripe::Stripe() { + oldpos1 = TPointD(0, 0); + oldpos2 = TPointD(0, 0); + pos1 = TPointD(0, 0); + pos2 = TPointD(0, 0); + color = TPixel32(0, 0, 0); + phase = 0; +} + +void Stripe::drawpolygon() { + tglColor(color); + glBegin(GL_POLYGON); + tglVertex(oldpos1); + tglVertex(pos1); + tglVertex(pos2); + tglVertex(oldpos2); + glEnd(); } -void Stripe::drawpolygon(TFlash &flash) -{ - vector pv; - pv.push_back(oldpos1); - pv.push_back(oldpos2); - pv.push_back(pos2); - pv.push_back(pos1); - flash.setThickness(0); - flash.setFillColor(color); - flash.drawPolyline(pv); - - // Draws the black contour - flash.setThickness(0.5); - flash.setLineColor(TPixel32::Black); - vector sv; - sv.push_back(TSegment(oldpos1, pos1)); - sv.push_back(TSegment(oldpos2, pos2)); - flash.drawSegments(sv, false); - - // It is better, but the flash.drawLine() is missing in my SDK - /* flash.setThickness(0.5); - flash.setLineColor(TPixel32::Black); - flash.drawLine(oldpos1,pos1); - flash.drawLine(oldpos2,pos2); +void Stripe::drawpolygon(TFlash &flash) { + vector pv; + pv.push_back(oldpos1); + pv.push_back(oldpos2); + pv.push_back(pos2); + pv.push_back(pos1); + flash.setThickness(0); + flash.setFillColor(color); + flash.drawPolyline(pv); + + // Draws the black contour + flash.setThickness(0.5); + flash.setLineColor(TPixel32::Black); + vector sv; + sv.push_back(TSegment(oldpos1, pos1)); + sv.push_back(TSegment(oldpos2, pos2)); + flash.drawSegments(sv, false); + + // It is better, but the flash.drawLine() is missing in my SDK + /* flash.setThickness(0.5); +flash.setLineColor(TPixel32::Black); + flash.drawLine(oldpos1,pos1); + flash.drawLine(oldpos2,pos2); */ } void Stripe::addToSegment(vector *sv, vector &scontour, - TPixel32 *colors) -{ - TPointD p0 = (oldpos1 + oldpos2) * 0.5; - TPointD p1 = (pos1 + pos2) * 0.5; - // TPointD p0=oldpos1; - // TPointD p1=pos1; - if (color == colors[0]) - sv[0].push_back(TSegment(p0, p1)); - if (color == colors[1]) - sv[1].push_back(TSegment(p0, p1)); - if (color == colors[2]) - sv[2].push_back(TSegment(p0, p1)); - - scontour.push_back(TSegment(oldpos1, pos1)); - scontour.push_back(TSegment(oldpos2, pos2)); -} - -void Stripe::drawlines(TPixel32 blackcolor) -{ - tglColor(blackcolor); - glBegin(GL_LINE_STRIP); - tglVertex(oldpos1); - tglVertex(pos1); - glEnd(); - glBegin(GL_LINE_STRIP); - tglVertex(pos2); - tglVertex(oldpos2); - glEnd(); + TPixel32 *colors) { + TPointD p0 = (oldpos1 + oldpos2) * 0.5; + TPointD p1 = (pos1 + pos2) * 0.5; + // TPointD p0=oldpos1; + // TPointD p1=pos1; + if (color == colors[0]) sv[0].push_back(TSegment(p0, p1)); + if (color == colors[1]) sv[1].push_back(TSegment(p0, p1)); + if (color == colors[2]) sv[2].push_back(TSegment(p0, p1)); + + scontour.push_back(TSegment(oldpos1, pos1)); + scontour.push_back(TSegment(oldpos2, pos2)); +} + +void Stripe::drawlines(TPixel32 blackcolor) { + tglColor(blackcolor); + glBegin(GL_LINE_STRIP); + tglVertex(oldpos1); + tglVertex(pos1); + glEnd(); + glBegin(GL_LINE_STRIP); + tglVertex(pos2); + tglVertex(oldpos2); + glEnd(); } } //----------------------------------------------------------------------------- TBraidStrokeStyle::TBraidStrokeStyle() - : m_period(80.0) + : m_period(80.0) { - m_colors[0] = TPixel32::Red; - m_colors[1] = TPixel32::Green; - m_colors[2] = TPixel32::Blue; + m_colors[0] = TPixel32::Red; + m_colors[1] = TPixel32::Green; + m_colors[2] = TPixel32::Blue; } //----------------------------------------------------------------------------- -TColorStyle *TBraidStrokeStyle::clone() const -{ - return new TBraidStrokeStyle(*this); +TColorStyle *TBraidStrokeStyle::clone() const { + return new TBraidStrokeStyle(*this); } //----------------------------------------------------------------------------- -int TBraidStrokeStyle::getParamCount() const -{ - return 1; -} +int TBraidStrokeStyle::getParamCount() const { return 1; } //----------------------------------------------------------------------------- -TColorStyle::ParamType TBraidStrokeStyle::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +TColorStyle::ParamType TBraidStrokeStyle::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -QString TBraidStrokeStyle::getParamNames(int index) const -{ - assert(0 <= index && index < 1); +QString TBraidStrokeStyle::getParamNames(int index) const { + assert(0 <= index && index < 1); - return QCoreApplication::translate("TBraidStrokeStyle", "Twirl"); + return QCoreApplication::translate("TBraidStrokeStyle", "Twirl"); } //----------------------------------------------------------------------------- -void TBraidStrokeStyle::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 1); - min = 1.0; - max = 100.0; +void TBraidStrokeStyle::getParamRange(int index, double &min, + double &max) const { + assert(0 <= index && index < 1); + min = 1.0; + max = 100.0; } //----------------------------------------------------------------------------- -double TBraidStrokeStyle::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 1); - return m_period; +double TBraidStrokeStyle::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 1); + return m_period; } //----------------------------------------------------------------------------- -void TBraidStrokeStyle::setParamValue(int index, double value) -{ - assert(0 <= index && index < 1); - m_period = value; +void TBraidStrokeStyle::setParamValue(int index, double value) { + assert(0 <= index && index < 1); + m_period = value; - updateVersionNumber(); + updateVersionNumber(); } //----------------------------------------------------------------------------- -TPixel32 TBraidStrokeStyle::getColorParamValue(int index) const -{ - TPixel32 tmp; - switch (index) { - case (0): - tmp = m_colors[0]; - break; - case (1): - tmp = m_colors[1]; - break; - case (2): - tmp = m_colors[2]; - break; - } - return tmp; +TPixel32 TBraidStrokeStyle::getColorParamValue(int index) const { + TPixel32 tmp; + switch (index) { + case (0): + tmp = m_colors[0]; + break; + case (1): + tmp = m_colors[1]; + break; + case (2): + tmp = m_colors[2]; + break; + } + return tmp; } //----------------------------------------------------------------------------- -void TBraidStrokeStyle::setColorParamValue(int index, const TPixel32 &color) -{ - switch (index) { - case (0): - m_colors[0] = color; - break; - case (1): - m_colors[1] = color; - break; - case (2): - m_colors[2] = color; - break; - } +void TBraidStrokeStyle::setColorParamValue(int index, const TPixel32 &color) { + switch (index) { + case (0): + m_colors[0] = color; + break; + case (1): + m_colors[1] = color; + break; + case (2): + m_colors[2] = color; + break; + } } //----------------------------------------------------------------------------- -void TBraidStrokeStyle::loadData(int ids, TInputStreamInterface &is) -{ - if (ids != 112) - throw TException("Braid stroke style: unknown obsolete format"); +void TBraidStrokeStyle::loadData(int ids, TInputStreamInterface &is) { + if (ids != 112) + throw TException("Braid stroke style: unknown obsolete format"); - is >> m_colors[0] >> m_period; + is >> m_colors[0] >> m_period; - m_period /= 10.0; - m_colors[0] = TPixel32::Red; - m_colors[1] = TPixel32::Green; - m_colors[2] = TPixel32::Blue; + m_period /= 10.0; + m_colors[0] = TPixel32::Red; + m_colors[1] = TPixel32::Green; + m_colors[2] = TPixel32::Blue; } //----------------------------------------------------------------------------- -void TBraidStrokeStyle::drawStroke(const TColorFunction *cf, const TStroke *stroke) const -{ - double length = stroke->getLength(); - const int ntick = 81; - const double stripethickness = 0.3; - int period = (int)(101 - m_period) * 20; - double step = period / (double)ntick; - double freq = 2 * TConsts::pi / ntick; - int swapcount = 0; - int count = 0; - bool firstRing = true; - double s = 0; - double swap; - vector braid; - vector ssin; - int k = 0; - TPixel32 colors[3]; - for (k = 0; k < 3; k++) { - if (cf) - colors[k] = (*(cf))(m_colors[k]); - else - colors[k] = m_colors[k]; - } - TPixel32 blackcolor = TPixel32::Black; - if (cf) - blackcolor = (*(cf))(blackcolor); - - for (k = 0; k < 3; k++) { - Stripe tmp; - tmp.phase = (ntick * k) / 3; - tmp.color = colors[k]; - braid.push_back(tmp); - } - - for (int z = 0; z < ntick; z++) { - double tmpsin = sin(z * freq); - ssin.push_back(tmpsin); - } - while (s <= length) { - count++; - double w = stroke->getParameterAtLength(s); - if (w < 0) { - s += 0.1; - continue; - } // per tamponare il baco della getParameterAtLength() - TThickPoint pos = stroke->getThickPoint(w); - TPointD u = stroke->getSpeed(w); - if (norm2(u) == 0) { - s += 0.1; - continue; - } // non dovrebbe succedere mai, ma per prudenza.... - u = normalize(u); - TPointD v = rotate90(u) * pos.thick; - TPointD v1 = v * stripethickness; - v = v * 0.5; - //int modper=(int)s%(int)period; - if (firstRing) { - firstRing = false; - swap = 0; - for (int j = 0; j < (int)braid.size(); j++) { - int tmp = (count + braid[j].phase) % ntick; - braid[j].oldpos1 = pos + v * ssin[tmp]; - braid[j].oldpos2 = pos + v * ssin[tmp] + v1; - } - } else { - for (int i = 0; i < (int)braid.size(); i++) { - int tmp = (count + braid[i].phase) % ntick; - braid[i].pos1 = pos + v * ssin[tmp]; - braid[i].pos2 = pos + v * ssin[tmp] + v1; - braid[i].drawpolygon(); - braid[i].drawlines(blackcolor); - braid[i].oldpos1 = pos + v * ssin[tmp]; - braid[i].oldpos2 = pos + v * ssin[tmp] + v1; - } - } - s += step; - swap += step; - if (swap > (period / 3.0)) { - swapcount++; - tswap(braid[0], braid[1 + (swapcount & 1)]); - swap -= period / 3.0; - } - } -} - -//----------------------------------------------------------------------------- - -void TBraidStrokeStyle::drawStroke(TFlash &flash, const TStroke *stroke) const -{ - double length = stroke->getLength(); - const int ntick = 162; - const double stripethickness = 0.3; - int period = (int)(101 - m_period) * 20; - double step = period / (double)ntick; - double freq = 2 * TConsts::pi / ntick; - int swapcount = 0; - int count = 0; - bool firstRing = true; - double s = 0; - double swap; - vector braid; - vector ssin; - int k = 0; - TPixel32 colors[3]; - - for (k = 0; k < 3; k++) - colors[k] = m_colors[k]; - - TPixel32 blackcolor = TPixel32::Black; - - for (k = 0; k < 3; k++) { - Stripe tmp; - tmp.phase = (ntick * k) / 3; - tmp.color = colors[k]; - braid.push_back(tmp); - } - - for (int z = 0; z < ntick; z++) { - double tmpsin = sin(z * freq); - ssin.push_back(tmpsin); - } - - while (s <= length) { - count++; - double w = stroke->getParameterAtLength(s); - if (w < 0) { - s += 0.1; - continue; - } // per tamponare il baco della getParameterAtLength() - TThickPoint pos = stroke->getThickPoint(w); - TPointD u = stroke->getSpeed(w); - if (norm2(u) == 0) { - s += 0.1; - continue; - } // non dovrebbe succedere mai, ma per prudenza.... - u = normalize(u); - TPointD v = rotate90(u) * pos.thick; - TPointD v1 = v * stripethickness; - v = v * 0.5; - //int modper=(int)s%(int)period; - if (firstRing) { - firstRing = false; - swap = 0; - for (int j = 0; j < (int)braid.size(); j++) { - int tmp = (count + braid[j].phase) % ntick; - braid[j].oldpos1 = pos + v * ssin[tmp]; - braid[j].oldpos2 = pos + v * ssin[tmp] + v1; - } - } else { - for (int i = 0; i < (int)braid.size(); i++) { - int tmp = (count + braid[i].phase) % ntick; - braid[i].pos1 = pos + v * ssin[tmp]; - braid[i].pos2 = pos + v * ssin[tmp] + v1; - - braid[i].drawpolygon(flash); - - braid[i].oldpos1 = pos + v * ssin[tmp]; - braid[i].oldpos2 = pos + v * ssin[tmp] + v1; - } - } - s += step; - swap += step; - if (swap > (period / 3.0)) { - swapcount++; - tswap(braid[0], braid[1 + (swapcount & 1)]); - swap -= period / 3.0; - } - } +void TBraidStrokeStyle::drawStroke(const TColorFunction *cf, + const TStroke *stroke) const { + double length = stroke->getLength(); + const int ntick = 81; + const double stripethickness = 0.3; + int period = (int)(101 - m_period) * 20; + double step = period / (double)ntick; + double freq = M_2PI / ntick; + int swapcount = 0; + int count = 0; + bool firstRing = true; + double s = 0; + double swap; + vector braid; + vector ssin; + int k = 0; + TPixel32 colors[3]; + for (k = 0; k < 3; k++) { + if (cf) + colors[k] = (*(cf))(m_colors[k]); + else + colors[k] = m_colors[k]; + } + TPixel32 blackcolor = TPixel32::Black; + if (cf) blackcolor = (*(cf))(blackcolor); + + for (k = 0; k < 3; k++) { + Stripe tmp; + tmp.phase = (ntick * k) / 3; + tmp.color = colors[k]; + braid.push_back(tmp); + } + + for (int z = 0; z < ntick; z++) { + double tmpsin = sin(z * freq); + ssin.push_back(tmpsin); + } + while (s <= length) { + count++; + double w = stroke->getParameterAtLength(s); + if (w < 0) { + s += 0.1; + continue; + } // per tamponare il baco della getParameterAtLength() + TThickPoint pos = stroke->getThickPoint(w); + TPointD u = stroke->getSpeed(w); + if (norm2(u) == 0) { + s += 0.1; + continue; + } // non dovrebbe succedere mai, ma per prudenza.... + u = normalize(u); + TPointD v = rotate90(u) * pos.thick; + TPointD v1 = v * stripethickness; + v = v * 0.5; + // int modper=(int)s%(int)period; + if (firstRing) { + firstRing = false; + swap = 0; + for (int j = 0; j < (int)braid.size(); j++) { + int tmp = (count + braid[j].phase) % ntick; + braid[j].oldpos1 = pos + v * ssin[tmp]; + braid[j].oldpos2 = pos + v * ssin[tmp] + v1; + } + } else { + for (int i = 0; i < (int)braid.size(); i++) { + int tmp = (count + braid[i].phase) % ntick; + braid[i].pos1 = pos + v * ssin[tmp]; + braid[i].pos2 = pos + v * ssin[tmp] + v1; + braid[i].drawpolygon(); + braid[i].drawlines(blackcolor); + braid[i].oldpos1 = pos + v * ssin[tmp]; + braid[i].oldpos2 = pos + v * ssin[tmp] + v1; + } + } + s += step; + swap += step; + if (swap > (period / 3.0)) { + swapcount++; + tswap(braid[0], braid[1 + (swapcount & 1)]); + swap -= period / 3.0; + } + } +} + +//----------------------------------------------------------------------------- + +void TBraidStrokeStyle::drawStroke(TFlash &flash, const TStroke *stroke) const { + double length = stroke->getLength(); + const int ntick = 162; + const double stripethickness = 0.3; + int period = (int)(101 - m_period) * 20; + double step = period / (double)ntick; + double freq = M_2PI / ntick; + int swapcount = 0; + int count = 0; + bool firstRing = true; + double s = 0; + double swap; + vector braid; + vector ssin; + int k = 0; + TPixel32 colors[3]; + + for (k = 0; k < 3; k++) colors[k] = m_colors[k]; + + TPixel32 blackcolor = TPixel32::Black; + + for (k = 0; k < 3; k++) { + Stripe tmp; + tmp.phase = (ntick * k) / 3; + tmp.color = colors[k]; + braid.push_back(tmp); + } + + for (int z = 0; z < ntick; z++) { + double tmpsin = sin(z * freq); + ssin.push_back(tmpsin); + } + + while (s <= length) { + count++; + double w = stroke->getParameterAtLength(s); + if (w < 0) { + s += 0.1; + continue; + } // per tamponare il baco della getParameterAtLength() + TThickPoint pos = stroke->getThickPoint(w); + TPointD u = stroke->getSpeed(w); + if (norm2(u) == 0) { + s += 0.1; + continue; + } // non dovrebbe succedere mai, ma per prudenza.... + u = normalize(u); + TPointD v = rotate90(u) * pos.thick; + TPointD v1 = v * stripethickness; + v = v * 0.5; + // int modper=(int)s%(int)period; + if (firstRing) { + firstRing = false; + swap = 0; + for (int j = 0; j < (int)braid.size(); j++) { + int tmp = (count + braid[j].phase) % ntick; + braid[j].oldpos1 = pos + v * ssin[tmp]; + braid[j].oldpos2 = pos + v * ssin[tmp] + v1; + } + } else { + for (int i = 0; i < (int)braid.size(); i++) { + int tmp = (count + braid[i].phase) % ntick; + braid[i].pos1 = pos + v * ssin[tmp]; + braid[i].pos2 = pos + v * ssin[tmp] + v1; + + braid[i].drawpolygon(flash); + + braid[i].oldpos1 = pos + v * ssin[tmp]; + braid[i].oldpos2 = pos + v * ssin[tmp] + v1; + } + } + s += step; + swap += step; + if (swap > (period / 3.0)) { + swapcount++; + tswap(braid[0], braid[1 + (swapcount & 1)]); + swap -= period / 3.0; + } + } } //============================================================================= TSketchStrokeStyle::TSketchStrokeStyle() - : m_color(TPixel32(100, 100, 150, 127)), m_density(0.4) -{ -} + : m_color(TPixel32(100, 100, 150, 127)), m_density(0.4) {} //----------------------------------------------------------------------------- -TColorStyle *TSketchStrokeStyle::clone() const -{ - return new TSketchStrokeStyle(*this); +TColorStyle *TSketchStrokeStyle::clone() const { + return new TSketchStrokeStyle(*this); } //----------------------------------------------------------------------------- -int TSketchStrokeStyle::getParamCount() const -{ - return 1; -} +int TSketchStrokeStyle::getParamCount() const { return 1; } //----------------------------------------------------------------------------- -TColorStyle::ParamType TSketchStrokeStyle::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +TColorStyle::ParamType TSketchStrokeStyle::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -QString TSketchStrokeStyle::getParamNames(int index) const -{ - assert(0 <= index && index < 1); +QString TSketchStrokeStyle::getParamNames(int index) const { + assert(0 <= index && index < 1); - return QCoreApplication::translate("TSketchStrokeStyle", "Density"); + return QCoreApplication::translate("TSketchStrokeStyle", "Density"); } //----------------------------------------------------------------------------- -void TSketchStrokeStyle::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 1); - min = 0.0; - max = 1.0; +void TSketchStrokeStyle::getParamRange(int index, double &min, + double &max) const { + assert(0 <= index && index < 1); + min = 0.0; + max = 1.0; } //----------------------------------------------------------------------------- -double TSketchStrokeStyle::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 1); - return m_density; +double TSketchStrokeStyle::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 1); + return m_density; } //----------------------------------------------------------------------------- -void TSketchStrokeStyle::setParamValue(int index, double value) -{ - assert(0 <= index && index < 1); - m_density = value; +void TSketchStrokeStyle::setParamValue(int index, double value) { + assert(0 <= index && index < 1); + m_density = value; - updateVersionNumber(); + updateVersionNumber(); } //----------------------------------------------------------------------------- -void TSketchStrokeStyle::drawStroke(const TColorFunction *cf, const TStroke *stroke) const -{ - double length = stroke->getLength(); - if (length <= 0) - return; - - int count = (int)(length * m_density); - - double maxDw = std::min(1.0, 20.0 / length); - double minDw = 1.0 / length; - - TPixel32 color; - if (cf) - color = (*(cf))(m_color); - else - color = m_color; - - tglColor(color); - - TRandom rnd; - - for (int i = 0; i < count; i++) { - double r = rnd.getFloat(); - double dw = (1 - r) * minDw + r * maxDw; - double wmin = dw, wmax = 1 - dw; - if (wmin >= wmax) - continue; - r = rnd.getFloat(); - double w = (1 - r) * wmin + r * wmax; - - double w0 = w - dw; - double w1 = w + dw; - - TThickPoint p0 = stroke->getThickPoint(w0); - TThickPoint p1 = stroke->getThickPoint(w1); - double d01 = tdistance(p0, p1); - if (d01 == 0) - continue; - - int count = (int)(d01); - - TPointD v0 = stroke->getSpeed(w0); - TPointD v1 = stroke->getSpeed(w1); - - if (norm2(v0) == 0 || norm2(v1) == 0) - continue; // non dovrebbe succedere mai, ma.... - v0 = rotate90(normalize(v0)); - v1 = rotate90(normalize(v1)); - - double delta = 0.5 * (rnd.getFloat() - 0.5) * (p0.thick + p1.thick); - double d = 0.1 * d01; - double delta0 = delta - d; - double delta1 = delta + d; - - glBegin(GL_LINE_STRIP); - tglVertex(p0 + v0 * delta0); - for (int j = 1; j < count; j++) { - double t = j / (double)count; - w = (1 - t) * w0 + t * w1; - TPointD v = rotate90(normalize(stroke->getSpeed(w))); - assert(0 <= w && w <= 1); - TPointD p = stroke->getPoint(w); - double delta_t = (1 - t) * delta0 + t * delta1; - tglVertex(p + v * delta_t); - } - tglVertex(p1 + v1 * delta1); - glEnd(); - } - glColor4d(0, 0, 0, 1); -} - -//----------------------------------------------------------------------------- - -void TSketchStrokeStyle::drawStroke(TFlash &flash, const TStroke *stroke) const -{ - double length = stroke->getLength(); - if (length <= 0) - return; - vector quadsArray; - - int count = (int)(length * m_density); - - double maxDw = std::min(1.0, 20.0 / length); - double minDw = 1.0 / length; - TPixel color(m_color.r, m_color.g, m_color.b, m_color.m); - flash.setLineColor(color); - - TRandom rnd; - - for (int i = 0; i < count; i++) { - double r = rnd.getFloat(); - double dw = (1 - r) * minDw + r * maxDw; - double wmin = dw, wmax = 1 - dw; - if (wmin >= wmax) - continue; - r = rnd.getFloat(); - double w = (1 - r) * wmin + r * wmax; - - double w0 = w - dw; - double w1 = w + dw; - - TThickPoint p0 = stroke->getThickPoint(w0); - TThickPoint p1 = stroke->getThickPoint(w1); - double d01 = tdistance(p0, p1); - if (d01 == 0) - continue; - - //int count = (int)(d01); - - TPointD v0 = stroke->getSpeed(w0); - TPointD v1 = stroke->getSpeed(w1); - - if (norm2(v0) == 0 || norm2(v1) == 0) - continue; // non dovrebbe succedere mai, ma.... - v0 = rotate90(normalize(v0)); - v1 = rotate90(normalize(v1)); - - double delta = 0.5 * (rnd.getFloat() - 0.5) * (p0.thick + p1.thick); - double d = 0.1 * d01; - double delta0 = delta - d; - double delta1 = delta + d; - - TPointD v = rotate90(normalize(stroke->getSpeed(0.5 * (w0 + w1)))); - TPointD p = stroke->getPoint(0.5 * (w0 + w1)); - double delta_t = 0.5 * (delta0 + delta1); - //quadsArray.push_back(TSegment(p0 + v0*delta0, p1 + v1*delta1)); - TPointD pp0 = p0 + v0 * delta0; - TPointD pp2 = p1 + v1 * delta1; - TPointD pp1 = 2 * (p + v * delta_t) - 0.5 * (pp0 + pp2); //punto p1 ottenuto imponendo che la quad passi per il punto p in t=.5 - quadsArray.push_back(TQuadratic(pp0, pp1, pp2)); - } - flash.drawquads(quadsArray); -} +void TSketchStrokeStyle::drawStroke(const TColorFunction *cf, + const TStroke *stroke) const { + double length = stroke->getLength(); + if (length <= 0) return; -//============================================================================= + int count = (int)(length * m_density); -TBubbleStrokeStyle::TBubbleStrokeStyle() - : m_color0(TPixel32::Red), m_color1(TPixel32::Green) -{ -} + double maxDw = std::min(1.0, 20.0 / length); + double minDw = 1.0 / length; -//----------------------------------------------------------------------------- + TPixel32 color; + if (cf) + color = (*(cf))(m_color); + else + color = m_color; -TColorStyle *TBubbleStrokeStyle::clone() const -{ - return new TBubbleStrokeStyle(*this); -} + tglColor(color); -//----------------------------------------------------------------------------- + TRandom rnd; -void TBubbleStrokeStyle::loadData(int ids, TInputStreamInterface &is) -{ - if (ids != 114) - throw TException("Bubble stroke style: unknown obsolete format"); + for (int i = 0; i < count; i++) { + double r = rnd.getFloat(); + double dw = (1 - r) * minDw + r * maxDw; + double wmin = dw, wmax = 1 - dw; + if (wmin >= wmax) continue; + r = rnd.getFloat(); + double w = (1 - r) * wmin + r * wmax; - m_color0 = TPixel32::Red; - m_color1 = TPixel32::Green; -} + double w0 = w - dw; + double w1 = w + dw; + + TThickPoint p0 = stroke->getThickPoint(w0); + TThickPoint p1 = stroke->getThickPoint(w1); + double d01 = tdistance(p0, p1); + if (d01 == 0) continue; + + int count = (int)(d01); + + TPointD v0 = stroke->getSpeed(w0); + TPointD v1 = stroke->getSpeed(w1); + + if (norm2(v0) == 0 || norm2(v1) == 0) + continue; // non dovrebbe succedere mai, ma.... + v0 = rotate90(normalize(v0)); + v1 = rotate90(normalize(v1)); + + double delta = 0.5 * (rnd.getFloat() - 0.5) * (p0.thick + p1.thick); + double d = 0.1 * d01; + double delta0 = delta - d; + double delta1 = delta + d; + + glBegin(GL_LINE_STRIP); + tglVertex(p0 + v0 * delta0); + for (int j = 1; j < count; j++) { + double t = j / (double)count; + w = (1 - t) * w0 + t * w1; + TPointD v = rotate90(normalize(stroke->getSpeed(w))); + assert(0 <= w && w <= 1); + TPointD p = stroke->getPoint(w); + double delta_t = (1 - t) * delta0 + t * delta1; + tglVertex(p + v * delta_t); + } + tglVertex(p1 + v1 * delta1); + glEnd(); + } + glColor4d(0, 0, 0, 1); +} //----------------------------------------------------------------------------- -void TBubbleStrokeStyle::drawStroke(const TColorFunction *cf, const TStroke *stroke) const -{ - double length = stroke->getLength(); - if (length <= 0) - return; - - TRandom rnd(0); - - TPixel32 color0, color1; - if (cf) { - color0 = (*(cf))(m_color0); - color1 = (*(cf))(m_color1); - } else { - color0 = m_color0; - color1 = m_color1; - } - - double minthickness = MINTHICK * sqrt(tglGetPixelSize2()); - double thickness = 0; - for (double s = 0; s < length; s += 5) { - TPointD p = stroke->getPointAtLength(s); - double w = stroke->getParameterAtLength(s); - if (w < 0) { - s += 0.1; - continue; - } // per tamponare il baco della getParameterAtLength() - TThickPoint pos = stroke->getThickPoint(w); - int toff = rnd.getInt(0, 999); - int t = (m_currentFrame + toff) % 1000; - TRandom rnd2(t >> 2); - p += 2 * TPointD(-0.5 + rnd2.getFloat(), -0.5 + rnd2.getFloat()); - if (pos.thick < MINTHICK) - thickness = minthickness; - else - thickness = pos.thick; - tglColor(blend(color0, color1, rnd.getFloat())); - double radius = (t & ((int)(thickness))); - tglDrawCircle(p, radius); - } -} - -//----------------------------------------------------------------------------- - -void TBubbleStrokeStyle::drawStroke(TFlash &flash, const TStroke *stroke) const -{ - double length = stroke->getLength(); - if (length <= 0) - return; - - TRandom rnd(0); - static int count = 0; - count++; - - TPixel32 color0 = m_color0; - TPixel32 color1 = m_color1; - - for (double s = 0; s < length; s += 5) { - TPointD p = stroke->getPointAtLength(s); - double w = stroke->getParameterAtLength(s); - if (w < 0) { - s += 0.1; - continue; - } // per tamponare il baco della getParameterAtLength() - TThickPoint pos = stroke->getThickPoint(w); - int toff = rnd.getInt(0, 999); - int t = (count + toff) % 1000; - TRandom rnd2(t >> 2); - p += 2 * TPointD(-0.5 + rnd2.getFloat(), -0.5 + rnd2.getFloat()); - double r = (t & ((int)(pos.thick))); - flash.setThickness(0.5); - flash.setLineColor(blend(color0, color1, rnd.getFloat())); - flash.setFillColor(TPixel32(0, 0, 0, 0)); - flash.drawEllipse(p, r, r); - } +void TSketchStrokeStyle::drawStroke(TFlash &flash, + const TStroke *stroke) const { + double length = stroke->getLength(); + if (length <= 0) return; + vector quadsArray; + + int count = (int)(length * m_density); + + double maxDw = std::min(1.0, 20.0 / length); + double minDw = 1.0 / length; + TPixel color(m_color.r, m_color.g, m_color.b, m_color.m); + flash.setLineColor(color); + + TRandom rnd; + + for (int i = 0; i < count; i++) { + double r = rnd.getFloat(); + double dw = (1 - r) * minDw + r * maxDw; + double wmin = dw, wmax = 1 - dw; + if (wmin >= wmax) continue; + r = rnd.getFloat(); + double w = (1 - r) * wmin + r * wmax; + + double w0 = w - dw; + double w1 = w + dw; + + TThickPoint p0 = stroke->getThickPoint(w0); + TThickPoint p1 = stroke->getThickPoint(w1); + double d01 = tdistance(p0, p1); + if (d01 == 0) continue; + + // int count = (int)(d01); + + TPointD v0 = stroke->getSpeed(w0); + TPointD v1 = stroke->getSpeed(w1); + + if (norm2(v0) == 0 || norm2(v1) == 0) + continue; // non dovrebbe succedere mai, ma.... + v0 = rotate90(normalize(v0)); + v1 = rotate90(normalize(v1)); + + double delta = 0.5 * (rnd.getFloat() - 0.5) * (p0.thick + p1.thick); + double d = 0.1 * d01; + double delta0 = delta - d; + double delta1 = delta + d; + + TPointD v = rotate90(normalize(stroke->getSpeed(0.5 * (w0 + w1)))); + TPointD p = stroke->getPoint(0.5 * (w0 + w1)); + double delta_t = 0.5 * (delta0 + delta1); + // quadsArray.push_back(TSegment(p0 + v0*delta0, p1 + v1*delta1)); + TPointD pp0 = p0 + v0 * delta0; + TPointD pp2 = p1 + v1 * delta1; + TPointD pp1 = 2 * (p + v * delta_t) - + 0.5 * (pp0 + pp2); // punto p1 ottenuto imponendo che la quad + // passi per il punto p in t=.5 + quadsArray.push_back(TQuadratic(pp0, pp1, pp2)); + } + flash.drawquads(quadsArray); } //============================================================================= -TTissueStrokeStyle::TTissueStrokeStyle() - : m_color(TPixel32::Black), m_density(3.0), m_border(1.0) -{ +TBubbleStrokeStyle::TBubbleStrokeStyle() + : m_color0(TPixel32::Red), m_color1(TPixel32::Green) {} + +//----------------------------------------------------------------------------- + +TColorStyle *TBubbleStrokeStyle::clone() const { + return new TBubbleStrokeStyle(*this); } //----------------------------------------------------------------------------- -TColorStyle *TTissueStrokeStyle::clone() const -{ - return new TTissueStrokeStyle(*this); +void TBubbleStrokeStyle::loadData(int ids, TInputStreamInterface &is) { + if (ids != 114) + throw TException("Bubble stroke style: unknown obsolete format"); + + m_color0 = TPixel32::Red; + m_color1 = TPixel32::Green; } //----------------------------------------------------------------------------- -int TTissueStrokeStyle::getParamCount() const -{ - return 2; +void TBubbleStrokeStyle::drawStroke(const TColorFunction *cf, + const TStroke *stroke) const { + double length = stroke->getLength(); + if (length <= 0) return; + + TRandom rnd(0); + + TPixel32 color0, color1; + if (cf) { + color0 = (*(cf))(m_color0); + color1 = (*(cf))(m_color1); + } else { + color0 = m_color0; + color1 = m_color1; + } + + double minthickness = MINTHICK * sqrt(tglGetPixelSize2()); + double thickness = 0; + for (double s = 0; s < length; s += 5) { + TPointD p = stroke->getPointAtLength(s); + double w = stroke->getParameterAtLength(s); + if (w < 0) { + s += 0.1; + continue; + } // per tamponare il baco della getParameterAtLength() + TThickPoint pos = stroke->getThickPoint(w); + int toff = rnd.getInt(0, 999); + int t = (m_currentFrame + toff) % 1000; + TRandom rnd2(t >> 2); + p += 2 * TPointD(-0.5 + rnd2.getFloat(), -0.5 + rnd2.getFloat()); + if (pos.thick < MINTHICK) + thickness = minthickness; + else + thickness = pos.thick; + tglColor(blend(color0, color1, rnd.getFloat())); + double radius = (t & ((int)(thickness))); + tglDrawCircle(p, radius); + } } //----------------------------------------------------------------------------- -TColorStyle::ParamType TTissueStrokeStyle::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +void TBubbleStrokeStyle::drawStroke(TFlash &flash, + const TStroke *stroke) const { + double length = stroke->getLength(); + if (length <= 0) return; + + TRandom rnd(0); + static int count = 0; + count++; + + TPixel32 color0 = m_color0; + TPixel32 color1 = m_color1; + + for (double s = 0; s < length; s += 5) { + TPointD p = stroke->getPointAtLength(s); + double w = stroke->getParameterAtLength(s); + if (w < 0) { + s += 0.1; + continue; + } // per tamponare il baco della getParameterAtLength() + TThickPoint pos = stroke->getThickPoint(w); + int toff = rnd.getInt(0, 999); + int t = (count + toff) % 1000; + TRandom rnd2(t >> 2); + p += 2 * TPointD(-0.5 + rnd2.getFloat(), -0.5 + rnd2.getFloat()); + double r = (t & ((int)(pos.thick))); + flash.setThickness(0.5); + flash.setLineColor(blend(color0, color1, rnd.getFloat())); + flash.setFillColor(TPixel32(0, 0, 0, 0)); + flash.drawEllipse(p, r, r); + } } +//============================================================================= + +TTissueStrokeStyle::TTissueStrokeStyle() + : m_color(TPixel32::Black), m_density(3.0), m_border(1.0) {} + //----------------------------------------------------------------------------- -QString TTissueStrokeStyle::getParamNames(int index) const -{ - assert(0 <= index && index < 2); - return index == 0 ? QCoreApplication::translate("TTissueStrokeStyle", "Density") : QCoreApplication::translate("TTissueStrokeStyle", "Border Size"); +TColorStyle *TTissueStrokeStyle::clone() const { + return new TTissueStrokeStyle(*this); } //----------------------------------------------------------------------------- -void TTissueStrokeStyle::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 2); - if (index == 0) { - min = 2.0; - max = 10.0; - } else { - min = 0.0; - max = 1.0; - } +int TTissueStrokeStyle::getParamCount() const { return 2; } + +//----------------------------------------------------------------------------- + +TColorStyle::ParamType TTissueStrokeStyle::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -double TTissueStrokeStyle::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 2); - return index == 0 ? m_density : m_border; +QString TTissueStrokeStyle::getParamNames(int index) const { + assert(0 <= index && index < 2); + return index == 0 + ? QCoreApplication::translate("TTissueStrokeStyle", "Density") + : QCoreApplication::translate("TTissueStrokeStyle", "Border Size"); } //----------------------------------------------------------------------------- -void TTissueStrokeStyle::setParamValue(int index, double value) -{ - assert(0 <= index && index < 2); - if (index == 0) - m_density = value; - else - m_border = value; +void TTissueStrokeStyle::getParamRange(int index, double &min, + double &max) const { + assert(0 <= index && index < 2); + if (index == 0) { + min = 2.0; + max = 10.0; + } else { + min = 0.0; + max = 1.0; + } +} + +//----------------------------------------------------------------------------- - updateVersionNumber(); +double TTissueStrokeStyle::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 2); + return index == 0 ? m_density : m_border; +} + +//----------------------------------------------------------------------------- + +void TTissueStrokeStyle::setParamValue(int index, double value) { + assert(0 <= index && index < 2); + if (index == 0) + m_density = value; + else + m_border = value; + + updateVersionNumber(); +} +//----------------------------------------------------------------------------- + +void TTissueStrokeStyle::computeData(PointMatrix &data, const TStroke *stroke, + const TColorFunction *cf) const { + data.clear(); + double length = stroke->getLength(); + double step = 5.0; + double border = m_border; + TPointD pos1, oldPos1; + TRandom rnd; + double increment = 0.0; + int intensity = (int)m_density + 2; + vector points; + vector oldpoints; + double s = 0; + bool firstRing = true; + while (s <= length) { + double w = stroke->getParameterAtLength(s); + if (w < 0) { + s += 0.1; + continue; + } // per tamponare il baco della getParameterAtLength() + TThickPoint pos = stroke->getThickPoint(w); + TPointD u = stroke->getSpeed(w); + if (norm2(u) == 0) { + s += 0.1; + continue; + } // non dovrebbe succedere mai, ma per prudenza.... + u = normalize(u); + TPointD v = rotate90(u); + increment = (2 * pos.thick) / (intensity - 1); + for (int i = 1; i < intensity - 1; i++) { + pos1 = pos + v * (-pos.thick + i * increment); + points.push_back(pos1); + } + if (firstRing) { + firstRing = false; + } else { + Points tmpPoints1; + tmpPoints1.clear(); + tmpPoints1.reserve(intensity); + + for (int i = 1; i < intensity - 1; i++) { + pos1 = points[i - 1]; + oldPos1 = oldpoints[i - 1]; + tmpPoints1.push_back(oldPos1); + tmpPoints1.push_back(pos1); + } + data.push_back(tmpPoints1); + if (increment > 1) { + int count = tceil(step / increment + 1); + Points tmpPoints2; + tmpPoints2.clear(); + tmpPoints2.reserve(count); + double startpoint = -step - increment / 2.0; + for (int j = 1; j < step / increment + 1; j++) { + tmpPoints2.push_back(points[0] - + v * border * increment * rnd.getFloat() + + u * (startpoint + j * (increment))); + tmpPoints2.push_back(points[intensity - 3] + + v * border * increment * rnd.getFloat() + + u * (startpoint + j * (increment))); + } + data.push_back(tmpPoints2); + } + } + oldpoints = points; + points.clear(); + s += step; + } } + //----------------------------------------------------------------------------- -void TTissueStrokeStyle::computeData(PointMatrix &data, - const TStroke *stroke, - const TColorFunction *cf) const -{ - data.clear(); - double length = stroke->getLength(); - double step = 5.0; - double border = m_border; - TPointD pos1, oldPos1; - TRandom rnd; - double increment = 0.0; - int intensity = (int)m_density + 2; - vector points; - vector oldpoints; - double s = 0; - bool firstRing = true; - while (s <= length) { - double w = stroke->getParameterAtLength(s); - if (w < 0) { - s += 0.1; - continue; - } // per tamponare il baco della getParameterAtLength() - TThickPoint pos = stroke->getThickPoint(w); - TPointD u = stroke->getSpeed(w); - if (norm2(u) == 0) { - s += 0.1; - continue; - } // non dovrebbe succedere mai, ma per prudenza.... - u = normalize(u); - TPointD v = rotate90(u); - increment = (2 * pos.thick) / (intensity - 1); - for (int i = 1; i < intensity - 1; i++) { - pos1 = pos + v * (-pos.thick + i * increment); - points.push_back(pos1); - } - if (firstRing) { - firstRing = false; - } else { - Points tmpPoints1; - tmpPoints1.clear(); - tmpPoints1.reserve(intensity); - - for (int i = 1; i < intensity - 1; i++) { - pos1 = points[i - 1]; - oldPos1 = oldpoints[i - 1]; - tmpPoints1.push_back(oldPos1); - tmpPoints1.push_back(pos1); - } - data.push_back(tmpPoints1); - if (increment > 1) { - int count = tceil(step / increment + 1); - Points tmpPoints2; - tmpPoints2.clear(); - tmpPoints2.reserve(count); - double startpoint = -step - increment / 2.0; - for (int j = 1; j < step / increment + 1; j++) { - tmpPoints2.push_back(points[0] - v * border * increment * rnd.getFloat() + u * (startpoint + j * (increment))); - tmpPoints2.push_back(points[intensity - 3] + v * border * increment * rnd.getFloat() + u * (startpoint + j * (increment))); - } - data.push_back(tmpPoints2); - } - } - oldpoints = points; - points.clear(); - s += step; - } -} - -//----------------------------------------------------------------------------- - -void TTissueStrokeStyle::drawStroke(const TColorFunction *cf, - PointMatrix &data, - const TStroke *stroke) const -{ - TPixel32 color; - if (cf) - color = (*(cf))(m_color); - else - color = m_color; +void TTissueStrokeStyle::drawStroke(const TColorFunction *cf, PointMatrix &data, + const TStroke *stroke) const { + TPixel32 color; + if (cf) + color = (*(cf))(m_color); + else + color = m_color; - tglColor(color); + tglColor(color); - PointMatrix::iterator it1 = data.begin(); - for (; it1 != data.end(); ++it1) { - glBegin(GL_LINES); - Points::iterator it2 = (*it1).begin(); - for (; it2 != (*it1).end(); ++it2) { - tglVertex(*it2); - } - glEnd(); - } + PointMatrix::iterator it1 = data.begin(); + for (; it1 != data.end(); ++it1) { + glBegin(GL_LINES); + Points::iterator it2 = (*it1).begin(); + for (; it2 != (*it1).end(); ++it2) { + tglVertex(*it2); + } + glEnd(); + } } //----------------------------------------------------------------------------- -void TTissueStrokeStyle::drawStroke(TFlash &flash, const TStroke *stroke) const -{ +void TTissueStrokeStyle::drawStroke(TFlash &flash, + const TStroke *stroke) const { + double length = stroke->getLength(); + double step = 5.0; + double border = m_border; + TPointD pos1, oldPos1; + TRandom rnd; + double increment = 0.0; + int intensity = (int)m_density + 2; + vector points; + vector oldpoints; + TPixel32 color = m_color; - double length = stroke->getLength(); - double step = 5.0; - double border = m_border; - TPointD pos1, oldPos1; - TRandom rnd; - double increment = 0.0; - int intensity = (int)m_density + 2; - vector points; - vector oldpoints; - TPixel32 color = m_color; - - flash.setLineColor(m_color); - flash.setThickness(1.0); - double s = 0; - bool firstRing = true; - while (s <= length) { - double w = stroke->getParameterAtLength(s); - if (w < 0) { - s += 0.1; - continue; - } // per tamponare il baco della getParameterAtLength() - TThickPoint pos = stroke->getThickPoint(w); - TPointD u = stroke->getSpeed(w); - if (norm2(u) == 0) { - s += 0.1; - continue; - } // non dovrebbe succedere mai, ma per prudenza.... - u = normalize(u); - TPointD v = rotate90(u); - increment = (2 * pos.thick) / (intensity - 1); - for (int i = 1; i < intensity - 1; i++) { - pos1 = pos + v * (-pos.thick + i * increment); - points.push_back(pos1); - } - if (firstRing) { - firstRing = false; - } else { - flash.setThickness(1.5); - vector sv; - for (int i = 1; i < intensity - 1; i++) { - pos1 = points[i - 1]; - oldPos1 = oldpoints[i - 1]; - sv.push_back(TSegment(oldPos1, pos1)); - } - flash.drawSegments(sv, false); - - if (increment > 1) { - sv.clear(); - double startpoint = -step - increment / 2.0; - for (int j = 1; j < step / increment + 1; j++) { - TPointD p0 = points[0] - v * border * increment * rnd.getFloat() + u * (startpoint + j * (increment)); - TPointD p1 = points[intensity - 3] + v * border * increment * rnd.getFloat() + u * (startpoint + j * (increment)); - // vector sv; - sv.push_back(TSegment(p0, p1)); - } - flash.drawSegments(sv, false); - } - } - oldpoints = points; - points.clear(); - s += step; - } + flash.setLineColor(m_color); + flash.setThickness(1.0); + double s = 0; + bool firstRing = true; + while (s <= length) { + double w = stroke->getParameterAtLength(s); + if (w < 0) { + s += 0.1; + continue; + } // per tamponare il baco della getParameterAtLength() + TThickPoint pos = stroke->getThickPoint(w); + TPointD u = stroke->getSpeed(w); + if (norm2(u) == 0) { + s += 0.1; + continue; + } // non dovrebbe succedere mai, ma per prudenza.... + u = normalize(u); + TPointD v = rotate90(u); + increment = (2 * pos.thick) / (intensity - 1); + for (int i = 1; i < intensity - 1; i++) { + pos1 = pos + v * (-pos.thick + i * increment); + points.push_back(pos1); + } + if (firstRing) { + firstRing = false; + } else { + flash.setThickness(1.5); + vector sv; + for (int i = 1; i < intensity - 1; i++) { + pos1 = points[i - 1]; + oldPos1 = oldpoints[i - 1]; + sv.push_back(TSegment(oldPos1, pos1)); + } + flash.drawSegments(sv, false); + + if (increment > 1) { + sv.clear(); + double startpoint = -step - increment / 2.0; + for (int j = 1; j < step / increment + 1; j++) { + TPointD p0 = points[0] - v * border * increment * rnd.getFloat() + + u * (startpoint + j * (increment)); + TPointD p1 = points[intensity - 3] + + v * border * increment * rnd.getFloat() + + u * (startpoint + j * (increment)); + // vector sv; + sv.push_back(TSegment(p0, p1)); + } + flash.drawSegments(sv, false); + } + } + oldpoints = points; + points.clear(); + s += step; + } } //============================================================================= TBiColorStrokeStyle::TBiColorStrokeStyle() - : m_color0(TPixel32::Red), m_color1(TPixel32::Black) -{ -} + : m_color0(TPixel32::Red), m_color1(TPixel32::Black) {} //----------------------------------------------------------------------------- -TColorStyle *TBiColorStrokeStyle::clone() const -{ - return new TBiColorStrokeStyle(*this); +TColorStyle *TBiColorStrokeStyle::clone() const { + return new TBiColorStrokeStyle(*this); } //----------------------------------------------------------------------------- -void TBiColorStrokeStyle::loadData(TInputStreamInterface &is) -{ - is >> m_color0 >> m_color1 >> m_parameter; +void TBiColorStrokeStyle::loadData(TInputStreamInterface &is) { + is >> m_color0 >> m_color1 >> m_parameter; } //----------------------------------------------------------------------------- -void TBiColorStrokeStyle::saveData(TOutputStreamInterface &os) const -{ - os << m_color0 << m_color1 << m_parameter; +void TBiColorStrokeStyle::saveData(TOutputStreamInterface &os) const { + os << m_color0 << m_color1 << m_parameter; } //----------------------------------------------------------------------------- -void TBiColorStrokeStyle::drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const -{ -} +void TBiColorStrokeStyle::drawRegion(const TColorFunction *cf, + const bool antiAliasing, + TRegionOutline &boundary) const {} //----------------------------------------------------------------------------- -void TBiColorStrokeStyle::loadData(int ids, TInputStreamInterface &is) -{ - if (ids != 115 && ids != 119) - throw TException("Bicolor stroke style: unknown obsolete format"); +void TBiColorStrokeStyle::loadData(int ids, TInputStreamInterface &is) { + if (ids != 115 && ids != 119) + throw TException("Bicolor stroke style: unknown obsolete format"); - is >> m_color0 >> m_parameter; + is >> m_color0 >> m_parameter; - m_color1 = TPixel32::Black; + m_color1 = TPixel32::Black; } //----------------------------------------------------------------------------- -void TBiColorStrokeStyle::drawStroke(const TColorFunction *cf, TStrokeOutline *outline, - const TStroke *stroke) const -{ - TPixel32 color0 = m_color0; - TPixel32 color1 = m_color1; +void TBiColorStrokeStyle::drawStroke(const TColorFunction *cf, + TStrokeOutline *outline, + const TStroke *stroke) const { + TPixel32 color0 = m_color0; + TPixel32 color1 = m_color1; - if (cf) { - color0 = (*(cf))(m_color0); - color1 = (*(cf))(m_color1); - } else { - color0 = m_color0; - color1 = m_color1; - } - - UINT i; + if (cf) { + color0 = (*(cf))(m_color0); + color1 = (*(cf))(m_color1); + } else { + color0 = m_color0; + color1 = m_color1; + } - const std::vector &v = outline->getArray(); + UINT i; - if (v.empty()) - return; + const std::vector &v = outline->getArray(); - // outline with antialiasing - glBegin(GL_LINE_STRIP); - tglColor(color0); - for (i = 0; i < v.size(); i += 2) - glVertex2dv(&v[i].x); - glEnd(); + if (v.empty()) return; - glBegin(GL_LINE_STRIP); - tglColor(color1); - for (i = 1; i < v.size(); i += 2) - glVertex2dv(&v[i].x); - glEnd(); + // outline with antialiasing + glBegin(GL_LINE_STRIP); + tglColor(color0); + for (i = 0; i < v.size(); i += 2) glVertex2dv(&v[i].x); + glEnd(); - glBegin(GL_QUAD_STRIP); - for (i = 0; i < v.size(); i += 2) { + glBegin(GL_LINE_STRIP); + tglColor(color1); + for (i = 1; i < v.size(); i += 2) glVertex2dv(&v[i].x); + glEnd(); - tglColor(color0); - glVertex2dv(&v[i].x); - tglColor(color1); - glVertex2dv(&v[i + 1].x); - } - glEnd(); + glBegin(GL_QUAD_STRIP); + for (i = 0; i < v.size(); i += 2) { + tglColor(color0); + glVertex2dv(&v[i].x); + tglColor(color1); + glVertex2dv(&v[i + 1].x); + } + glEnd(); } //----------------------------------------------------------------------------- -void TBiColorStrokeStyle::drawStroke(TFlash &flash, const TStroke *stroke) const -{ - TOutlineUtil::OutlineParameter param; - param.m_lengthStep = std::max(10.0, m_parameter); - TStrokeOutline outline; - TOutlineStyle::computeOutline(stroke, outline, param); - const std::vector &v = outline.getArray(); - if (v.empty()) - return; - - TPixel32 color0 = m_color0; - TPixel32 color1 = m_color1; - flash.setThickness(0.0); - // Just for the polygon grading function - SFlashUtils sfu; - for (UINT i = 0; i < (v.size() - 3); i += 2) { - vector plv; - plv.push_back(TPointD(v[i].x, v[i].y)); - plv.push_back(TPointD(v[i + 2].x, v[i + 2].y)); - plv.push_back(TPointD(v[i + 3].x, v[i + 3].y)); - plv.push_back(TPointD(v[i + 1].x, v[i + 1].y)); - // flash.setFillColor(blend(color0,color1,0.5)); - // flash.drawPolyline(plv); - // graded multipolygons - sfu.drawGradedPolyline(flash, plv, color0, color1); - } +void TBiColorStrokeStyle::drawStroke(TFlash &flash, + const TStroke *stroke) const { + TOutlineUtil::OutlineParameter param; + param.m_lengthStep = std::max(10.0, m_parameter); + TStrokeOutline outline; + TOutlineStyle::computeOutline(stroke, outline, param); + const std::vector &v = outline.getArray(); + if (v.empty()) return; + + TPixel32 color0 = m_color0; + TPixel32 color1 = m_color1; + flash.setThickness(0.0); + // Just for the polygon grading function + SFlashUtils sfu; + for (UINT i = 0; i < (v.size() - 3); i += 2) { + vector plv; + plv.push_back(TPointD(v[i].x, v[i].y)); + plv.push_back(TPointD(v[i + 2].x, v[i + 2].y)); + plv.push_back(TPointD(v[i + 3].x, v[i + 3].y)); + plv.push_back(TPointD(v[i + 1].x, v[i + 1].y)); + // flash.setFillColor(blend(color0,color1,0.5)); + // flash.drawPolyline(plv); + // graded multipolygons + sfu.drawGradedPolyline(flash, plv, color0, color1); + } } //============================================================================= TNormal2StrokeStyle::TNormal2StrokeStyle() - : m_color(TPixel32::Yellow), m_lightx(45.0), m_lighty(200.0), m_shininess(50.0), m_metal(0.5), m_bend(1.0) -{ -} + : m_color(TPixel32::Yellow) + , m_lightx(45.0) + , m_lighty(200.0) + , m_shininess(50.0) + , m_metal(0.5) + , m_bend(1.0) {} //----------------------------------------------------------------------------- -TColorStyle *TNormal2StrokeStyle::clone() const -{ - return new TNormal2StrokeStyle(*this); +TColorStyle *TNormal2StrokeStyle::clone() const { + return new TNormal2StrokeStyle(*this); } //----------------------------------------------------------------------------- -int TNormal2StrokeStyle::getParamCount() const -{ - return 5; +int TNormal2StrokeStyle::getParamCount() const { return 5; } + +//----------------------------------------------------------------------------- + +TColorStyle::ParamType TNormal2StrokeStyle::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -TColorStyle::ParamType TNormal2StrokeStyle::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +QString TNormal2StrokeStyle::getParamNames(int index) const { + assert(0 <= index && index < 5); + QString value; + switch (index) { + case 0: + value = QCoreApplication::translate("TNormal2StrokeStyle", "Light X Pos"); + break; + case 1: + value = QCoreApplication::translate("TNormal2StrokeStyle", "Light Y Pos"); + break; + case 2: + value = QCoreApplication::translate("TNormal2StrokeStyle", "Shininess"); + break; + case 3: + value = QCoreApplication::translate("TNormal2StrokeStyle", "Plastic"); + break; + case 4: + value = QCoreApplication::translate("TNormal2StrokeStyle", "Bump"); + break; + } + return value; +} + +//----------------------------------------------------------------------------- + +void TNormal2StrokeStyle::getParamRange(int index, double &min, + double &max) const { + assert(0 <= index && index < 5); + switch (index) { + case 0: + min = -100.0; + max = 100.0; + break; + case 1: + min = -100.0; + max = 100.0; + break; + case 2: + min = 0.1; + max = 128.0; + break; + case 3: + min = 0.0; + max = 1.0; + break; + case 4: + min = 0.0; + max = 1.0; + break; + } } //----------------------------------------------------------------------------- -QString TNormal2StrokeStyle::getParamNames(int index) const -{ - assert(0 <= index && index < 5); - QString value; - switch (index) { - case 0: - value = QCoreApplication::translate("TNormal2StrokeStyle", "Light X Pos"); - break; - case 1: - value = QCoreApplication::translate("TNormal2StrokeStyle", "Light Y Pos"); - break; - case 2: - value = QCoreApplication::translate("TNormal2StrokeStyle", "Shininess"); - break; - case 3: - value = QCoreApplication::translate("TNormal2StrokeStyle", "Plastic"); - break; - case 4: - value = QCoreApplication::translate("TNormal2StrokeStyle", "Bump"); - break; - } - return value; -} - -//----------------------------------------------------------------------------- - -void TNormal2StrokeStyle::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 5); - switch (index) { - case 0: - min = -100.0; - max = 100.0; - break; - case 1: - min = -100.0; - max = 100.0; - break; - case 2: - min = 0.1; - max = 128.0; - break; - case 3: - min = 0.0; - max = 1.0; - break; - case 4: - min = 0.0; - max = 1.0; - break; - } -} - -//----------------------------------------------------------------------------- - -double TNormal2StrokeStyle::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 5); - double value; - switch (index) { - case 0: - value = m_lightx; - break; - case 1: - value = m_lighty; - break; - case 2: - value = m_shininess; - break; - case 3: - value = m_metal; - break; - case 4: - value = m_bend; - break; - } - return value; -} - -//----------------------------------------------------------------------------- - -void TNormal2StrokeStyle::setParamValue(int index, double value) -{ - assert(0 <= index && index < 5); - switch (index) { - case 0: - m_lightx = value; - break; - case 1: - m_lighty = value; - break; - case 2: - m_shininess = value; - break; - case 3: - m_metal = value; - break; - case 4: - m_bend = value; - break; - } - - updateVersionNumber(); -} - -//----------------------------------------------------------------------------- - -void TNormal2StrokeStyle::loadData(int ids, TInputStreamInterface &is) -{ - if (ids != 121) - throw TException("Normal stroke style: unknown obsolete format"); +double TNormal2StrokeStyle::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 5); + double value; + switch (index) { + case 0: + value = m_lightx; + break; + case 1: + value = m_lighty; + break; + case 2: + value = m_shininess; + break; + case 3: + value = m_metal; + break; + case 4: + value = m_bend; + break; + } + return value; +} + +//----------------------------------------------------------------------------- + +void TNormal2StrokeStyle::setParamValue(int index, double value) { + assert(0 <= index && index < 5); + switch (index) { + case 0: + m_lightx = value; + break; + case 1: + m_lighty = value; + break; + case 2: + m_shininess = value; + break; + case 3: + m_metal = value; + break; + case 4: + m_bend = value; + break; + } - is >> m_color >> m_lightx >> m_lighty >> m_shininess >> m_metal; - m_bend = 1.0; + updateVersionNumber(); } //----------------------------------------------------------------------------- -void TNormal2StrokeStyle::drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const -{ +void TNormal2StrokeStyle::loadData(int ids, TInputStreamInterface &is) { + if (ids != 121) + throw TException("Normal stroke style: unknown obsolete format"); + + is >> m_color >> m_lightx >> m_lighty >> m_shininess >> m_metal; + m_bend = 1.0; } //----------------------------------------------------------------------------- -void TNormal2StrokeStyle::drawStroke(const TColorFunction *cf, TStrokeOutline *outline, - const TStroke *stroke) const -{ +void TNormal2StrokeStyle::drawRegion(const TColorFunction *cf, + const bool antiAliasing, + TRegionOutline &boundary) const {} - TPixel32 color; - if (cf) - color = (*(cf))(m_color); - else - color = m_color; - TPixelD dcolor; - dcolor = toPixelD(color); - UINT i; - double bend = 2 * m_bend; - const std::vector &v = outline->getArray(); - if (v.empty()) - return; - vector normal; - - GLfloat light_position[] = {(float)(m_lightx), (float)(m_lighty), 100.0, 0.0}; - glLightfv(GL_LIGHT0, GL_POSITION, light_position); - glEnable(GL_LIGHTING); - glEnable(GL_LIGHT0); - glEnable(GL_NORMALIZE); - GLfloat mat_ambient[] = {(float)dcolor.r, (float)dcolor.g, (float)dcolor.b, 1.0}; - GLfloat mat_specular[] = {(float)(m_metal * (1 - dcolor.r) + dcolor.r), - (float)(m_metal * (1 - dcolor.g) + dcolor.g), - (float)(m_metal * (1 - dcolor.b) + dcolor.b), 1.0}; - GLfloat mat_shininess[] = {(float)m_shininess}; - - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular); - glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess); - glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_ambient); - - // glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); - - // outline with antialiasing - glBegin(GL_LINE_STRIP); - for (i = 0; i < v.size(); i += 2) { - T3DPointD pointa(v[i].x, v[i].y, 0); - T3DPointD pointb(v[i + 1].x, v[i + 1].y, 0); - T3DPointD d = pointb - pointa; - if (norm2(d) > 0.0) - d = normalize(d); - normal.push_back(d); - T3DPointD pointaNormal = T3DPointD(0, 0, 1) - bend * d; - tglNormal(pointaNormal); - tglVertex(pointa); - } - glEnd(); - - int normalcounter = 0; - glBegin(GL_LINE_STRIP); - for (i = 1; i < v.size(); i += 2) { - T3DPointD pointa(v[i].x, v[i].y, 0); - T3DPointD pointaNormal = T3DPointD(0, 0, 1) + bend * normal[normalcounter++]; - tglNormal(pointaNormal); - tglVertex(pointa); - } - glEnd(); - - normalcounter = 0; - for (i = 0; i <= v.size() - 4; i += 2) { - glBegin(GL_QUAD_STRIP); - T3DPointD olda(v[i].x, v[i].y, 0); - T3DPointD oldb(v[i + 1].x, v[i + 1].y, 0); - T3DPointD oldcenter = 0.5 * (olda + oldb); - T3DPointD oldcenterNormal(0, 0, 1); - T3DPointD oldaNormal = T3DPointD(0, 0, 1) - bend * normal[normalcounter]; - T3DPointD oldbNormal = T3DPointD(0, 0, 1) + bend * normal[normalcounter]; - T3DPointD a(v[i + 2].x, v[i + 2].y, 0); - T3DPointD b(v[i + 3].x, v[i + 3].y, 0); - T3DPointD center = 0.5 * (a + b); - T3DPointD centerNormal(0, 0, 1); - T3DPointD aNormal = T3DPointD(0, 0, 1) - bend * normal[normalcounter++]; - T3DPointD bNormal = T3DPointD(0, 0, 1) + bend * normal[normalcounter]; - tglNormal(oldaNormal); - tglVertex(olda); - tglNormal(aNormal); - tglVertex(a); - tglNormal(oldcenterNormal); - tglVertex(oldcenter); - tglNormal(centerNormal); - tglVertex(center); - tglNormal(oldbNormal); - tglVertex(oldb); - tglNormal(bNormal); - tglVertex(b); - glEnd(); - } - - glDisable(GL_NORMALIZE); - glDisable(GL_LIGHTING); - glDisable(GL_LIGHT0); -} - -//----------------------------------------------------------------------------- - -void TNormal2StrokeStyle::drawStroke(TFlash &flash, const TStroke *stroke) const -{ - //TStroke *stroke = getStroke(); - //double length = stroke->getLength(); - //double step=10.0; - TPointD pos1, pos2, pos3, pos4, oldPos1, oldPos2, oldPos3, oldPos4; - - TOutlineUtil::OutlineParameter param; - param.m_lengthStep = 10.0; - TStrokeOutline outline; - TOutlineStyle::computeOutline(stroke, outline, param); - const std::vector &v = outline.getArray(); - - TPixel32 color = m_color; - TPixelD dcolor; - dcolor = toPixelD(color); - - TPixel32 color1; - TPixelD dcolor1(0.5 * dcolor.r, 0.5 * dcolor.g, 0.5 * dcolor.b, 1.0); - color1 = toPixel32(dcolor1); - - dcolor = TPixelD(dcolor.r + (1.0 - dcolor.r) * m_metal, - dcolor.g + (1.0 - dcolor.g) * m_metal, - dcolor.b + (1.0 - dcolor.b) * m_metal, dcolor.m); - color = toPixel32(dcolor); - flash.setThickness(0.0); - - SFlashUtils sfu; - for (int i = 0; i <= (int)(v.size() - 4); i += 2) { - TPointD olda(v[i].x, v[i].y); - TPointD oldb(v[i + 1].x, v[i + 1].y); - TPointD oldcenter = 0.5 * (olda + oldb); - TPointD a(v[i + 2].x, v[i + 2].y); - TPointD b(v[i + 3].x, v[i + 3].y); - TPointD center = 0.5 * (a + b); - - vector vpl; - vpl.push_back(olda); - vpl.push_back(a); - vpl.push_back(center); - vpl.push_back(oldcenter); - sfu.drawGradedPolyline(flash, vpl, color1, color); - - vpl.clear(); - vpl.push_back(oldb); - vpl.push_back(b); - vpl.push_back(center); - vpl.push_back(oldcenter); - sfu.drawGradedPolyline(flash, vpl, color1, color); - } +//----------------------------------------------------------------------------- + +void TNormal2StrokeStyle::drawStroke(const TColorFunction *cf, + TStrokeOutline *outline, + const TStroke *stroke) const { + TPixel32 color; + if (cf) + color = (*(cf))(m_color); + else + color = m_color; + TPixelD dcolor; + dcolor = toPixelD(color); + UINT i; + double bend = 2 * m_bend; + const std::vector &v = outline->getArray(); + if (v.empty()) return; + vector normal; + + GLfloat light_position[] = {(float)(m_lightx), (float)(m_lighty), 100.0, 0.0}; + glLightfv(GL_LIGHT0, GL_POSITION, light_position); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_NORMALIZE); + GLfloat mat_ambient[] = {(float)dcolor.r, (float)dcolor.g, (float)dcolor.b, + 1.0}; + GLfloat mat_specular[] = {(float)(m_metal * (1 - dcolor.r) + dcolor.r), + (float)(m_metal * (1 - dcolor.g) + dcolor.g), + (float)(m_metal * (1 - dcolor.b) + dcolor.b), 1.0}; + GLfloat mat_shininess[] = {(float)m_shininess}; + + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular); + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess); + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat_ambient); + + // glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); + + // outline with antialiasing + glBegin(GL_LINE_STRIP); + for (i = 0; i < v.size(); i += 2) { + T3DPointD pointa(v[i].x, v[i].y, 0); + T3DPointD pointb(v[i + 1].x, v[i + 1].y, 0); + T3DPointD d = pointb - pointa; + if (norm2(d) > 0.0) d = normalize(d); + normal.push_back(d); + T3DPointD pointaNormal = T3DPointD(0, 0, 1) - bend * d; + tglNormal(pointaNormal); + tglVertex(pointa); + } + glEnd(); + + int normalcounter = 0; + glBegin(GL_LINE_STRIP); + for (i = 1; i < v.size(); i += 2) { + T3DPointD pointa(v[i].x, v[i].y, 0); + T3DPointD pointaNormal = + T3DPointD(0, 0, 1) + bend * normal[normalcounter++]; + tglNormal(pointaNormal); + tglVertex(pointa); + } + glEnd(); + + normalcounter = 0; + for (i = 0; i <= v.size() - 4; i += 2) { + glBegin(GL_QUAD_STRIP); + T3DPointD olda(v[i].x, v[i].y, 0); + T3DPointD oldb(v[i + 1].x, v[i + 1].y, 0); + T3DPointD oldcenter = 0.5 * (olda + oldb); + T3DPointD oldcenterNormal(0, 0, 1); + T3DPointD oldaNormal = T3DPointD(0, 0, 1) - bend * normal[normalcounter]; + T3DPointD oldbNormal = T3DPointD(0, 0, 1) + bend * normal[normalcounter]; + T3DPointD a(v[i + 2].x, v[i + 2].y, 0); + T3DPointD b(v[i + 3].x, v[i + 3].y, 0); + T3DPointD center = 0.5 * (a + b); + T3DPointD centerNormal(0, 0, 1); + T3DPointD aNormal = T3DPointD(0, 0, 1) - bend * normal[normalcounter++]; + T3DPointD bNormal = T3DPointD(0, 0, 1) + bend * normal[normalcounter]; + tglNormal(oldaNormal); + tglVertex(olda); + tglNormal(aNormal); + tglVertex(a); + tglNormal(oldcenterNormal); + tglVertex(oldcenter); + tglNormal(centerNormal); + tglVertex(center); + tglNormal(oldbNormal); + tglVertex(oldb); + tglNormal(bNormal); + tglVertex(b); + glEnd(); + } + + glDisable(GL_NORMALIZE); + glDisable(GL_LIGHTING); + glDisable(GL_LIGHT0); +} + +//----------------------------------------------------------------------------- + +void TNormal2StrokeStyle::drawStroke(TFlash &flash, + const TStroke *stroke) const { + // TStroke *stroke = getStroke(); + // double length = stroke->getLength(); + // double step=10.0; + TPointD pos1, pos2, pos3, pos4, oldPos1, oldPos2, oldPos3, oldPos4; + + TOutlineUtil::OutlineParameter param; + param.m_lengthStep = 10.0; + TStrokeOutline outline; + TOutlineStyle::computeOutline(stroke, outline, param); + const std::vector &v = outline.getArray(); + + TPixel32 color = m_color; + TPixelD dcolor; + dcolor = toPixelD(color); + + TPixel32 color1; + TPixelD dcolor1(0.5 * dcolor.r, 0.5 * dcolor.g, 0.5 * dcolor.b, 1.0); + color1 = toPixel32(dcolor1); + + dcolor = TPixelD(dcolor.r + (1.0 - dcolor.r) * m_metal, + dcolor.g + (1.0 - dcolor.g) * m_metal, + dcolor.b + (1.0 - dcolor.b) * m_metal, dcolor.m); + color = toPixel32(dcolor); + flash.setThickness(0.0); + + SFlashUtils sfu; + for (int i = 0; i <= (int)(v.size() - 4); i += 2) { + TPointD olda(v[i].x, v[i].y); + TPointD oldb(v[i + 1].x, v[i + 1].y); + TPointD oldcenter = 0.5 * (olda + oldb); + TPointD a(v[i + 2].x, v[i + 2].y); + TPointD b(v[i + 3].x, v[i + 3].y); + TPointD center = 0.5 * (a + b); + + vector vpl; + vpl.push_back(olda); + vpl.push_back(a); + vpl.push_back(center); + vpl.push_back(oldcenter); + sfu.drawGradedPolyline(flash, vpl, color1, color); + + vpl.clear(); + vpl.push_back(oldb); + vpl.push_back(b); + vpl.push_back(center); + vpl.push_back(oldcenter); + sfu.drawGradedPolyline(flash, vpl, color1, color); + } } //============================================================================= -namespace -{ -double get_inout_intensityslope(double in, double out, double t) -{ - if (out < in) - out = in; - if (t < in) - return t / in; - else if (t > out) - return (t - 1) / (out - 1); - else - return 1; +namespace { +double get_inout_intensityslope(double in, double out, double t) { + if (out < in) out = in; + if (t < in) + return t / in; + else if (t > out) + return (t - 1) / (out - 1); + else + return 1; } } //----------------------------------------------------------------------------- TChalkStrokeStyle2::TChalkStrokeStyle2() - : m_color(TPixel32::Black), m_blend(1.0), m_intensity(50.0), m_in(0.25), m_out(0.25), m_noise(0.0) -{ + : m_color(TPixel32::Black) + , m_blend(1.0) + , m_intensity(50.0) + , m_in(0.25) + , m_out(0.25) + , m_noise(0.0) {} + +//----------------------------------------------------------------------------- + +TColorStyle *TChalkStrokeStyle2::clone() const { + return new TChalkStrokeStyle2(*this); } //----------------------------------------------------------------------------- -TColorStyle *TChalkStrokeStyle2::clone() const -{ - return new TChalkStrokeStyle2(*this); +int TChalkStrokeStyle2::getParamCount() const { return 5; } + +//----------------------------------------------------------------------------- + +TColorStyle::ParamType TChalkStrokeStyle2::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -int TChalkStrokeStyle2::getParamCount() const -{ - return 5; +QString TChalkStrokeStyle2::getParamNames(int index) const { + assert(0 <= index && index < 5); + QString value; + switch (index) { + case 0: + value = QCoreApplication::translate("TChalkStrokeStyle2", "Border Fade"); + break; + case 1: + value = QCoreApplication::translate("TChalkStrokeStyle2", "Density"); + break; + case 2: + value = QCoreApplication::translate("TChalkStrokeStyle2", "Fade In"); + break; + case 3: + value = QCoreApplication::translate("TChalkStrokeStyle2", "Fade Out"); + break; + case 4: + value = QCoreApplication::translate("TChalkStrokeStyle2", "Noise"); + break; + } + return value; +} + +//----------------------------------------------------------------------------- + +void TChalkStrokeStyle2::getParamRange(int index, double &min, + double &max) const { + assert(0 <= index && index < 5); + switch (index) { + case 0: + min = 0.0; + max = 1.0; + break; + case 1: + min = 0.0; + max = 100.0; + break; + case 2: + min = 0.0; + max = 1.0; + break; + case 3: + min = 0.0; + max = 1.0; + break; + case 4: + min = 0.0; + max = 1.0; + break; + } } //----------------------------------------------------------------------------- -TColorStyle::ParamType TChalkStrokeStyle2::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +double TChalkStrokeStyle2::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 5); + double value = 0; + switch (index) { + case 0: + value = m_blend; + break; + case 1: + value = m_intensity; + break; + case 2: + value = m_in; + break; + case 3: + value = m_out; + break; + case 4: + value = m_noise; + break; + } + return value; +} + +//----------------------------------------------------------------------------- + +void TChalkStrokeStyle2::setParamValue(int index, double value) { + assert(0 <= index && index < 5); + switch (index) { + case 0: + m_blend = value; + break; + case 1: + m_intensity = value; + break; + case 2: + m_in = value; + break; + case 3: + m_out = value; + break; + case 4: + m_noise = value; + break; + } + + // updateVersionNumber(); non serve perche' i parametri vengono sfrutttati + // direttamente nella draw } //----------------------------------------------------------------------------- -QString TChalkStrokeStyle2::getParamNames(int index) const -{ - assert(0 <= index && index < 5); - QString value; - switch (index) { - case 0: - value = QCoreApplication::translate("TChalkStrokeStyle2", "Border Fade"); - break; - case 1: - value = QCoreApplication::translate("TChalkStrokeStyle2", "Density"); - break; - case 2: - value = QCoreApplication::translate("TChalkStrokeStyle2", "Fade In"); - break; - case 3: - value = QCoreApplication::translate("TChalkStrokeStyle2", "Fade Out"); - break; - case 4: - value = QCoreApplication::translate("TChalkStrokeStyle2", "Noise"); - break; - } - return value; -} - -//----------------------------------------------------------------------------- - -void TChalkStrokeStyle2::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 5); - switch (index) { - case 0: - min = 0.0; - max = 1.0; - break; - case 1: - min = 0.0; - max = 100.0; - break; - case 2: - min = 0.0; - max = 1.0; - break; - case 3: - min = 0.0; - max = 1.0; - break; - case 4: - min = 0.0; - max = 1.0; - break; - } -} - -//----------------------------------------------------------------------------- - -double TChalkStrokeStyle2::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 5); - double value = 0; - switch (index) { - case 0: - value = m_blend; - break; - case 1: - value = m_intensity; - break; - case 2: - value = m_in; - break; - case 3: - value = m_out; - break; - case 4: - value = m_noise; - break; - } - return value; -} - -//----------------------------------------------------------------------------- - -void TChalkStrokeStyle2::setParamValue(int index, double value) -{ - assert(0 <= index && index < 5); - switch (index) { - case 0: - m_blend = value; - break; - case 1: - m_intensity = value; - break; - case 2: - m_in = value; - break; - case 3: - m_out = value; - break; - case 4: - m_noise = value; - break; - } - - //updateVersionNumber(); non serve perche' i parametri vengono sfrutttati direttamente nella draw -} - -//----------------------------------------------------------------------------- - -void TChalkStrokeStyle2::loadData(int ids, TInputStreamInterface &is) -{ - if (ids != 105) - throw TException("chalk stroke style: unknown obsolete format"); - m_in = 0.0, m_out = 0.0, m_noise = 0.0; +void TChalkStrokeStyle2::loadData(int ids, TInputStreamInterface &is) { + if (ids != 105) + throw TException("chalk stroke style: unknown obsolete format"); + m_in = 0.0, m_out = 0.0, m_noise = 0.0; - is >> m_color >> m_blend >> m_intensity; - m_blend = 1 - m_blend; + is >> m_color >> m_blend >> m_intensity; + m_blend = 1 - m_blend; } //----------------------------------------------------------------------------- -void TChalkStrokeStyle2::computeData(Doubles &data, const TStroke *stroke, const TColorFunction *cf) const -{ - double length = stroke->getLength(); - double step = 4; - double s = 0; +void TChalkStrokeStyle2::computeData(Doubles &data, const TStroke *stroke, + const TColorFunction *cf) const { + double length = stroke->getLength(); + double step = 4; + double s = 0; - data.clear(); - data.reserve(tceil(length / step) * 6 + 6); + data.clear(); + data.reserve(tceil(length / step) * 6 + 6); - while (s <= length) { - double w = stroke->getParameterAtLength(s); - //if(w<0) {s+=0.1; continue;} // per tamponare il baco della getParameterAtLength() - TThickPoint pos = stroke->getThickPoint(w); - TPointD u = stroke->getSpeed(w); - double normu = norm2(u); - if (normu == 0) { - s += 0.1; - continue; - } // non dovrebbe succedere mai, ma per prudenza.... - u = normalize(u); + while (s <= length) { + double w = stroke->getParameterAtLength(s); + // if(w<0) {s+=0.1; continue;} // per tamponare il baco della + // getParameterAtLength() + TThickPoint pos = stroke->getThickPoint(w); + TPointD u = stroke->getSpeed(w); + double normu = norm2(u); + if (normu == 0) { + s += 0.1; + continue; + } // non dovrebbe succedere mai, ma per prudenza.... + u = normalize(u); - data.push_back(pos.x); - data.push_back(pos.y); - data.push_back(pos.thick); - data.push_back(u.x); - data.push_back(u.y); - data.push_back(s / length); + data.push_back(pos.x); + data.push_back(pos.y); + data.push_back(pos.thick); + data.push_back(u.x); + data.push_back(u.y); + data.push_back(s / length); - s += step; - } + s += step; + } } //----------------------------------------------------------------------------- -void TChalkStrokeStyle2::drawStroke(const TColorFunction *cf, Doubles &data, const TStroke *stroke) const -{ - double step = 4; - - double blend = m_blend; //distanza che controlla da dove il gessetto comincia il fade out (0, 1) - double intensitymax = m_intensity; //quanti punti vengono disegnati ad ogni step - - TRandom rnd; - TRandom rnd_noise; - TPixel32 color; - if (cf) - color = (*(cf))(m_color); - else - color = m_color; - TPixelD dcolor; - dcolor = toPixelD(color); - double mattedcolor = 0.5 * dcolor.m; - - double noise = 0; - double noiseslope = 0; - double tmpnoise = 0; - - GLuint chalkId; - chalkId = glGenLists(1); - glNewList(chalkId, GL_COMPILE); - glBegin(GL_QUADS); - glVertex2d(1, 1); - glVertex2d(-1, 1); - glVertex2d(-1, -1); - glVertex2d(1, -1); - glEnd(); - glEndList(); - - for (UINT i = 0; i < data.size(); i += 6) { - TThickPoint pos; - pos.x = data[i]; - pos.y = data[i + 1]; - pos.thick = data[i + 2]; - TPointD u; - u.x = data[i + 3]; - u.y = data[i + 4]; - TPointD v = rotate90(u); - - TPointD shift; - double intslope = get_inout_intensityslope(m_in, 1 - m_out, data[i + 5]); - double transpslope = (intslope / blend) * dcolor.m; - if (m_noise) { - if (tmpnoise <= 0) { - noise = (100 / m_noise) * rnd_noise.getFloat(); - tmpnoise = noise; - } - noiseslope = get_inout_intensityslope(0.5, 0.5, tmpnoise / noise); - tmpnoise -= step; - } else - noiseslope = 1; - - for (int i = 0; i < intensitymax * intslope * noiseslope; i++) { - double vrandnorm = rnd.getFloat(-1.0, 1.0); - double randomv = vrandnorm * pos.thick * noiseslope; - double randomu = (0.5 - rnd.getFloat()) * step; - shift = pos + u * randomu + v * randomv; - double mod = fabs(vrandnorm); - if (mod > 1 - blend) - glColor4d(dcolor.r, dcolor.g, dcolor.b, (double)rnd.getFloat() * ((1 - mod) * transpslope)); - else - glColor4d(dcolor.r, dcolor.g, dcolor.b, mattedcolor); - glPushMatrix(); - glTranslated(shift.x, shift.y, 0.0); - glCallList(chalkId); - glPopMatrix(); - } - } - - glDeleteLists(chalkId, 1); +void TChalkStrokeStyle2::drawStroke(const TColorFunction *cf, Doubles &data, + const TStroke *stroke) const { + double step = 4; + + double blend = m_blend; // distanza che controlla da dove il gessetto + // comincia il fade out (0, 1) + double intensitymax = + m_intensity; // quanti punti vengono disegnati ad ogni step + + TRandom rnd; + TRandom rnd_noise; + TPixel32 color; + if (cf) + color = (*(cf))(m_color); + else + color = m_color; + TPixelD dcolor; + dcolor = toPixelD(color); + double mattedcolor = 0.5 * dcolor.m; + + double noise = 0; + double noiseslope = 0; + double tmpnoise = 0; + + GLuint chalkId; + chalkId = glGenLists(1); + glNewList(chalkId, GL_COMPILE); + glBegin(GL_QUADS); + glVertex2d(1, 1); + glVertex2d(-1, 1); + glVertex2d(-1, -1); + glVertex2d(1, -1); + glEnd(); + glEndList(); + + for (UINT i = 0; i < data.size(); i += 6) { + TThickPoint pos; + pos.x = data[i]; + pos.y = data[i + 1]; + pos.thick = data[i + 2]; + TPointD u; + u.x = data[i + 3]; + u.y = data[i + 4]; + TPointD v = rotate90(u); + + TPointD shift; + double intslope = get_inout_intensityslope(m_in, 1 - m_out, data[i + 5]); + double transpslope = (intslope / blend) * dcolor.m; + if (m_noise) { + if (tmpnoise <= 0) { + noise = (100 / m_noise) * rnd_noise.getFloat(); + tmpnoise = noise; + } + noiseslope = get_inout_intensityslope(0.5, 0.5, tmpnoise / noise); + tmpnoise -= step; + } else + noiseslope = 1; + + for (int i = 0; i < intensitymax * intslope * noiseslope; i++) { + double vrandnorm = rnd.getFloat(-1.0, 1.0); + double randomv = vrandnorm * pos.thick * noiseslope; + double randomu = (0.5 - rnd.getFloat()) * step; + shift = pos + u * randomu + v * randomv; + double mod = fabs(vrandnorm); + if (mod > 1 - blend) + glColor4d(dcolor.r, dcolor.g, dcolor.b, + (double)rnd.getFloat() * ((1 - mod) * transpslope)); + else + glColor4d(dcolor.r, dcolor.g, dcolor.b, mattedcolor); + glPushMatrix(); + glTranslated(shift.x, shift.y, 0.0); + glCallList(chalkId); + glPopMatrix(); + } + } + + glDeleteLists(chalkId, 1); } //============================================================================= TBlendStrokeStyle2::TBlendStrokeStyle2() - : m_color(TPixel32::Red), m_blend(1.0), m_in(0.25), m_out(0.25) -{ -} + : m_color(TPixel32::Red), m_blend(1.0), m_in(0.25), m_out(0.25) {} //----------------------------------------------------------------------------- -TColorStyle *TBlendStrokeStyle2::clone() const -{ - return new TBlendStrokeStyle2(*this); +TColorStyle *TBlendStrokeStyle2::clone() const { + return new TBlendStrokeStyle2(*this); } //----------------------------------------------------------------------------- -int TBlendStrokeStyle2::getParamCount() const -{ - return 3; -} +int TBlendStrokeStyle2::getParamCount() const { return 3; } //----------------------------------------------------------------------------- -TColorStyle::ParamType TBlendStrokeStyle2::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +TColorStyle::ParamType TBlendStrokeStyle2::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -QString TBlendStrokeStyle2::getParamNames(int index) const -{ - assert(0 <= index && index < 3); - QString value; - switch (index) { - case 0: - value = QCoreApplication::translate("TBlendStrokeStyle2", "Border Fade"); - break; - case 1: - value = QCoreApplication::translate("TBlendStrokeStyle2", "Fade In"); - break; - case 2: - value = QCoreApplication::translate("TBlendStrokeStyle2", "Fade Out"); - break; - } - return value; +QString TBlendStrokeStyle2::getParamNames(int index) const { + assert(0 <= index && index < 3); + QString value; + switch (index) { + case 0: + value = QCoreApplication::translate("TBlendStrokeStyle2", "Border Fade"); + break; + case 1: + value = QCoreApplication::translate("TBlendStrokeStyle2", "Fade In"); + break; + case 2: + value = QCoreApplication::translate("TBlendStrokeStyle2", "Fade Out"); + break; + } + return value; } //----------------------------------------------------------------------------- -void TBlendStrokeStyle2::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 3); - min = 0.0; - max = 1.0; +void TBlendStrokeStyle2::getParamRange(int index, double &min, + double &max) const { + assert(0 <= index && index < 3); + min = 0.0; + max = 1.0; } //----------------------------------------------------------------------------- -double TBlendStrokeStyle2::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 3); - double value = 0; - switch (index) { - case 0: - value = m_blend; - break; - case 1: - value = m_in; - break; - case 2: - value = m_out; - break; - } - return value; +double TBlendStrokeStyle2::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 3); + double value = 0; + switch (index) { + case 0: + value = m_blend; + break; + case 1: + value = m_in; + break; + case 2: + value = m_out; + break; + } + return value; } //----------------------------------------------------------------------------- -void TBlendStrokeStyle2::setParamValue(int index, double value) -{ - assert(0 <= index && index < 3); - switch (index) { - case 0: - m_blend = value; - break; - case 1: - m_in = value; - break; - case 2: - m_out = value; - break; - } +void TBlendStrokeStyle2::setParamValue(int index, double value) { + assert(0 <= index && index < 3); + switch (index) { + case 0: + m_blend = value; + break; + case 1: + m_in = value; + break; + case 2: + m_out = value; + break; + } - updateVersionNumber(); + updateVersionNumber(); } //----------------------------------------------------------------------------- -void TBlendStrokeStyle2::loadData(int ids, TInputStreamInterface &is) -{ - if (ids != 110) - throw TException("Blend stroke style: unknown obsolete format"); - m_in = 0.0, m_out = 0.0; - is >> m_color >> m_blend; - m_blend = 1 - m_blend; +void TBlendStrokeStyle2::loadData(int ids, TInputStreamInterface &is) { + if (ids != 110) + throw TException("Blend stroke style: unknown obsolete format"); + m_in = 0.0, m_out = 0.0; + is >> m_color >> m_blend; + m_blend = 1 - m_blend; } //----------------------------------------------------------------------------- void TBlendStrokeStyle2::computeData(PointsAndDoubles &data, - const TStroke *stroke, - const TColorFunction *cf) const -{ - data.clear(); - //TStroke *stroke = getStroke(); - double length = stroke->getLength(); - double step = 10.0; - TPointD pos1, pos2, pos3, pos4, oldPos1, oldPos2, oldPos3, oldPos4; - double oldintslope; - TPixel32 color; - if (cf) - color = (*(cf))(m_color); - else - color = m_color; - TPixelD dcolor; - dcolor = toPixelD(color); - bool firstRing = true; - double s = 0; - double maxfactor = 2 * m_blend / step; //max definisce il numero di intervalli in cui la regione viene divisa - //per evitare il problema del blend poco efficiente sui triangoli - double minthickness = MINTHICK * sqrt(tglGetPixelSize2()); - double thickness = 0; - while (s <= length) { - double w = stroke->getParameterAtLength(s); - if (w < 0) { - s += 0.1; - continue; - } // per tamponare il baco della getParameterAtLength() - TThickPoint pos = stroke->getThickPoint(w); - TPointD u = stroke->getSpeed(w); - if (norm2(u) == 0) { - s += 0.1; - continue; - } // non dovrebbe succedere mai, ma per prudenza.... - u = normalize(u); - if (pos.thick < MINTHICK) - thickness = minthickness; - else - thickness = pos.thick; - TPointD v = rotate90(u) * thickness; - - TPointD v1 = v * (1 - m_blend); - pos1 = pos + v; - pos2 = pos + v1; - pos3 = pos - v1; - pos4 = pos - v; - double intslope = get_inout_intensityslope(m_in, 1 - m_out, s / length) * dcolor.m; - if (firstRing) { - firstRing = false; - } else { - int max = (int)(maxfactor * thickness); - double invmax = 1.0 / max; - data.push_back(make_pair(oldPos1, 0.0)); - data.push_back(make_pair(pos1, 0.0)); - int i; - for (i = 1; i < max; i++) { - data.push_back(make_pair(i * (oldPos2 - oldPos1) * invmax + oldPos1, (i * oldintslope) * invmax)); - data.push_back(make_pair(i * (pos2 - pos1) * invmax + pos1, (i * intslope) * invmax)); - } - - data.push_back(make_pair(oldPos2, oldintslope)); - data.push_back(make_pair(pos2, intslope)); - data.push_back(make_pair(oldPos3, oldintslope)); - data.push_back(make_pair(pos3, intslope)); - - for (i = 0; i < max; i++) { - data.push_back(make_pair(i * (oldPos4 - oldPos3) * invmax + oldPos3, (oldintslope * invmax) * (max - i))); - data.push_back(make_pair(i * (pos4 - pos3) * invmax + pos3, (intslope * invmax) * (max - i))); - } - - data.push_back(make_pair(oldPos4, 0.0)); - data.push_back(make_pair(pos4, 0.0)); - } - oldPos1 = pos1; - oldPos2 = pos2; - oldPos3 = pos3; - oldPos4 = pos4; - oldintslope = intslope; - s += step; - } + const TStroke *stroke, + const TColorFunction *cf) const { + data.clear(); + // TStroke *stroke = getStroke(); + double length = stroke->getLength(); + double step = 10.0; + TPointD pos1, pos2, pos3, pos4, oldPos1, oldPos2, oldPos3, oldPos4; + double oldintslope; + TPixel32 color; + if (cf) + color = (*(cf))(m_color); + else + color = m_color; + TPixelD dcolor; + dcolor = toPixelD(color); + bool firstRing = true; + double s = 0; + double maxfactor = 2 * m_blend / step; // max definisce il numero di + // intervalli in cui la regione viene + // divisa + // per evitare il problema del blend poco efficiente sui triangoli + double minthickness = MINTHICK * sqrt(tglGetPixelSize2()); + double thickness = 0; + while (s <= length) { + double w = stroke->getParameterAtLength(s); + if (w < 0) { + s += 0.1; + continue; + } // per tamponare il baco della getParameterAtLength() + TThickPoint pos = stroke->getThickPoint(w); + TPointD u = stroke->getSpeed(w); + if (norm2(u) == 0) { + s += 0.1; + continue; + } // non dovrebbe succedere mai, ma per prudenza.... + u = normalize(u); + if (pos.thick < MINTHICK) + thickness = minthickness; + else + thickness = pos.thick; + TPointD v = rotate90(u) * thickness; + + TPointD v1 = v * (1 - m_blend); + pos1 = pos + v; + pos2 = pos + v1; + pos3 = pos - v1; + pos4 = pos - v; + double intslope = + get_inout_intensityslope(m_in, 1 - m_out, s / length) * dcolor.m; + if (firstRing) { + firstRing = false; + } else { + int max = (int)(maxfactor * thickness); + double invmax = 1.0 / max; + data.push_back(make_pair(oldPos1, 0.0)); + data.push_back(make_pair(pos1, 0.0)); + int i; + for (i = 1; i < max; i++) { + data.push_back(make_pair(i * (oldPos2 - oldPos1) * invmax + oldPos1, + (i * oldintslope) * invmax)); + data.push_back(make_pair(i * (pos2 - pos1) * invmax + pos1, + (i * intslope) * invmax)); + } + + data.push_back(make_pair(oldPos2, oldintslope)); + data.push_back(make_pair(pos2, intslope)); + data.push_back(make_pair(oldPos3, oldintslope)); + data.push_back(make_pair(pos3, intslope)); + + for (i = 0; i < max; i++) { + data.push_back(make_pair(i * (oldPos4 - oldPos3) * invmax + oldPos3, + (oldintslope * invmax) * (max - i))); + data.push_back(make_pair(i * (pos4 - pos3) * invmax + pos3, + (intslope * invmax) * (max - i))); + } + + data.push_back(make_pair(oldPos4, 0.0)); + data.push_back(make_pair(pos4, 0.0)); + } + oldPos1 = pos1; + oldPos2 = pos2; + oldPos3 = pos3; + oldPos4 = pos4; + oldintslope = intslope; + s += step; + } } //----------------------------------------------------------------------------- void TBlendStrokeStyle2::drawStroke(const TColorFunction *cf, - PointsAndDoubles &data, - const TStroke *stroke) const -{ - TPixel32 color; - if (cf) - color = (*(cf))(m_color); - else - color = m_color; - TPixelD dcolor; - dcolor = toPixelD(color); - - PointsAndDoubles::iterator it = data.begin(); - glBegin(GL_QUAD_STRIP); - for (; it != data.end(); ++it) { - glColor4d(dcolor.r, dcolor.g, dcolor.b, it->second); - tglVertex(it->first); - } - glEnd(); + PointsAndDoubles &data, + const TStroke *stroke) const { + TPixel32 color; + if (cf) + color = (*(cf))(m_color); + else + color = m_color; + TPixelD dcolor; + dcolor = toPixelD(color); + + PointsAndDoubles::iterator it = data.begin(); + glBegin(GL_QUAD_STRIP); + for (; it != data.end(); ++it) { + glColor4d(dcolor.r, dcolor.g, dcolor.b, it->second); + tglVertex(it->first); + } + glEnd(); } //----------------------------------------------------------------------------- -void TBlendStrokeStyle2::drawStroke(TFlash &flash, const TStroke *stroke) const -{ - //TStroke *stroke = getStroke(); - double length = stroke->getLength(); - double step = 10.0; - TPointD pos1, pos2, pos3, pos4, oldPos1, oldPos2, oldPos3, oldPos4; - double oldintslope; - TPixel32 color = m_color; - - double lblend = m_blend; - // For the Flash version, to simplify the grading. - lblend = 1.0; - - TPixelD dcolor; - dcolor = toPixelD(color); - bool firstRing = true; - double s = 0; - //double maxfactor=2*lblend/step; //max definisce il numero di intervalli in cui la regione viene divisa - //per evitare il problema del blend poco efficiente sui triangoli - - vector vp1, vp2; - vector vdc1, vdc2; - - flash.setThickness(0); - SFlashUtils sfu; - while (s <= length) { - double w = stroke->getParameterAtLength(s); - if (w < 0) { - s += 0.1; - continue; - } // per tamponare il baco della getParameterAtLength() - TThickPoint pos = stroke->getThickPoint(w); - TPointD u = stroke->getSpeed(w); - if (norm2(u) == 0) { - s += 0.1; - continue; - } // non dovrebbe succedere mai, ma per prudenza.... - u = normalize(u); - TPointD v = rotate90(u) * pos.thick; - TPointD v1 = v * (1 - lblend); - pos1 = pos + v; - pos2 = pos + v1; - pos3 = pos - v1; - pos4 = pos - v; - double intslope = get_inout_intensityslope(m_in, 1 - m_out, s / length) * dcolor.m; - if (firstRing) { - firstRing = false; - } else { - vp1.clear(); - vp2.clear(); - vdc1.clear(); - vdc2.clear(); - - // The Flash version has been simplified. Only one direction grading! - - vdc1.push_back(TPixelD(dcolor.r, dcolor.g, dcolor.b, 0)); - vp1.push_back(oldPos1); - vdc2.push_back(TPixelD(dcolor.r, dcolor.g, dcolor.b, 0)); - vp2.push_back(pos1); - vdc1.push_back(TPixelD(dcolor.r, dcolor.g, dcolor.b, oldintslope)); - vp1.push_back(oldPos2); - vdc2.push_back(TPixelD(dcolor.r, dcolor.g, dcolor.b, intslope)); - vp2.push_back(pos2); - vdc1.push_back(TPixelD(dcolor.r, dcolor.g, dcolor.b, oldintslope)); - vp1.push_back(oldPos3); - vdc2.push_back(TPixelD(dcolor.r, dcolor.g, dcolor.b, intslope)); - vp2.push_back(pos3); - vdc1.push_back(TPixelD(dcolor.r, dcolor.g, dcolor.b, 0)); - vp1.push_back(oldPos4); - vdc2.push_back(TPixelD(dcolor.r, dcolor.g, dcolor.b, 0)); - vp2.push_back(pos4); - - vector vpl; - vpl.push_back(vp1[0]); - vpl.push_back(vp1[3]); - vpl.push_back(vp2[3]); - vpl.push_back(vp2[0]); - - TPixel32 col[4]; - col[0] = toPixel32(vdc1[1]); - col[1] = toPixel32(vdc1[2]); - col[2] = toPixel32(vdc2[2]); - col[3] = toPixel32(vdc2[1]); - - sfu.drawGradedPolyline(flash, vpl, blend(col[0], col[1], 0.5), blend(col[2], col[3], 0.5)); - } - oldPos1 = pos1; - oldPos2 = pos2; - oldPos3 = pos3; - oldPos4 = pos4; - oldintslope = intslope; - s += step; - } +void TBlendStrokeStyle2::drawStroke(TFlash &flash, + const TStroke *stroke) const { + // TStroke *stroke = getStroke(); + double length = stroke->getLength(); + double step = 10.0; + TPointD pos1, pos2, pos3, pos4, oldPos1, oldPos2, oldPos3, oldPos4; + double oldintslope; + TPixel32 color = m_color; + + double lblend = m_blend; + // For the Flash version, to simplify the grading. + lblend = 1.0; + + TPixelD dcolor; + dcolor = toPixelD(color); + bool firstRing = true; + double s = 0; + // double maxfactor=2*lblend/step; //max definisce il numero di intervalli in + // cui la regione viene divisa + // per evitare il problema del blend poco efficiente sui triangoli + + vector vp1, vp2; + vector vdc1, vdc2; + + flash.setThickness(0); + SFlashUtils sfu; + while (s <= length) { + double w = stroke->getParameterAtLength(s); + if (w < 0) { + s += 0.1; + continue; + } // per tamponare il baco della getParameterAtLength() + TThickPoint pos = stroke->getThickPoint(w); + TPointD u = stroke->getSpeed(w); + if (norm2(u) == 0) { + s += 0.1; + continue; + } // non dovrebbe succedere mai, ma per prudenza.... + u = normalize(u); + TPointD v = rotate90(u) * pos.thick; + TPointD v1 = v * (1 - lblend); + pos1 = pos + v; + pos2 = pos + v1; + pos3 = pos - v1; + pos4 = pos - v; + double intslope = + get_inout_intensityslope(m_in, 1 - m_out, s / length) * dcolor.m; + if (firstRing) { + firstRing = false; + } else { + vp1.clear(); + vp2.clear(); + vdc1.clear(); + vdc2.clear(); + + // The Flash version has been simplified. Only one direction grading! + + vdc1.push_back(TPixelD(dcolor.r, dcolor.g, dcolor.b, 0)); + vp1.push_back(oldPos1); + vdc2.push_back(TPixelD(dcolor.r, dcolor.g, dcolor.b, 0)); + vp2.push_back(pos1); + vdc1.push_back(TPixelD(dcolor.r, dcolor.g, dcolor.b, oldintslope)); + vp1.push_back(oldPos2); + vdc2.push_back(TPixelD(dcolor.r, dcolor.g, dcolor.b, intslope)); + vp2.push_back(pos2); + vdc1.push_back(TPixelD(dcolor.r, dcolor.g, dcolor.b, oldintslope)); + vp1.push_back(oldPos3); + vdc2.push_back(TPixelD(dcolor.r, dcolor.g, dcolor.b, intslope)); + vp2.push_back(pos3); + vdc1.push_back(TPixelD(dcolor.r, dcolor.g, dcolor.b, 0)); + vp1.push_back(oldPos4); + vdc2.push_back(TPixelD(dcolor.r, dcolor.g, dcolor.b, 0)); + vp2.push_back(pos4); + + vector vpl; + vpl.push_back(vp1[0]); + vpl.push_back(vp1[3]); + vpl.push_back(vp2[3]); + vpl.push_back(vp2[0]); + + TPixel32 col[4]; + col[0] = toPixel32(vdc1[1]); + col[1] = toPixel32(vdc1[2]); + col[2] = toPixel32(vdc2[2]); + col[3] = toPixel32(vdc2[1]); + + sfu.drawGradedPolyline(flash, vpl, blend(col[0], col[1], 0.5), + blend(col[2], col[3], 0.5)); + } + oldPos1 = pos1; + oldPos2 = pos2; + oldPos3 = pos3; + oldPos4 = pos4; + oldintslope = intslope; + s += step; + } } //============================================================================= TTwirlStrokeStyle::TTwirlStrokeStyle() - : m_color(TPixel32::Green), m_period(30.0), m_blend(0.5) -{ + : m_color(TPixel32::Green), m_period(30.0), m_blend(0.5) {} + +//----------------------------------------------------------------------------- + +TColorStyle *TTwirlStrokeStyle::clone() const { + return new TTwirlStrokeStyle(*this); } //----------------------------------------------------------------------------- -TColorStyle *TTwirlStrokeStyle::clone() const -{ - return new TTwirlStrokeStyle(*this); +int TTwirlStrokeStyle::getParamCount() const { return 2; } + +//----------------------------------------------------------------------------- + +TColorStyle::ParamType TTwirlStrokeStyle::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -int TTwirlStrokeStyle::getParamCount() const -{ - return 2; +QString TTwirlStrokeStyle::getParamNames(int index) const { + assert(0 <= index && index < 2); + return index == 0 ? QCoreApplication::translate("TTwirlStrokeStyle", "Twirl") + : QCoreApplication::translate("TTwirlStrokeStyle", "Shade"); } //----------------------------------------------------------------------------- -TColorStyle::ParamType TTwirlStrokeStyle::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +void TTwirlStrokeStyle::getParamRange(int index, double &min, + double &max) const { + assert(0 <= index && index < 2); + if (index == 0) { + min = 1.0; + max = 100.0; + } else { + min = 0.0; + max = 1.0; + } } //----------------------------------------------------------------------------- -QString TTwirlStrokeStyle::getParamNames(int index) const -{ - assert(0 <= index && index < 2); - return index == 0 ? QCoreApplication::translate("TTwirlStrokeStyle", "Twirl") : QCoreApplication::translate("TTwirlStrokeStyle", "Shade"); +double TTwirlStrokeStyle::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 2); + return index == 0 ? m_period : m_blend; } //----------------------------------------------------------------------------- -void TTwirlStrokeStyle::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 2); - if (index == 0) { - min = 1.0; - max = 100.0; - } else { - min = 0.0; - max = 1.0; - } +void TTwirlStrokeStyle::setParamValue(int index, double value) { + assert(0 <= index && index < 2); + if (index == 0) + m_period = value; + else + m_blend = value; + + updateVersionNumber(); } //----------------------------------------------------------------------------- -double TTwirlStrokeStyle::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 2); - return index == 0 ? m_period : m_blend; +void TTwirlStrokeStyle::computeData(Doubles &data, const TStroke *stroke, + const TColorFunction *cf) const { + double length = stroke->getLength(); + double step = 5.0; + double period = 10 * (102 - m_period); + double hperiod = period / 2; + double blendval = 0; + TRandom rnd; + + data.clear(); + data.reserve(tceil(length / step) + 1); + + double s = 0; + TPointD app; + while (s <= length) { + double w = stroke->getParameterAtLength(s); + if (w < 0) { + s += 0.1; + continue; + } // per tamponare il baco della getParameterAtLength() + TThickPoint pos = stroke->getThickPoint(w); + TPointD u = stroke->getSpeed(w); + if (norm2(u) == 0) { + s += 0.1; + continue; + } // non dovrebbe succedere mai, ma per prudenza.... + u = normalize(u); + TPointD v = rotate90(u) * (pos.thick); + double shift = sin((M_PI / hperiod) * s); + + app = pos + v * shift; + data.push_back(app.x); + data.push_back(app.y); + app = pos - v * shift; + data.push_back(app.x); + data.push_back(app.y); + + blendval = get_inout_intensityslope( + m_blend, 1.0 - m_blend, (s - ((int)(s / hperiod) * hperiod)) / hperiod); + data.push_back(blendval); + s += step; + } } //----------------------------------------------------------------------------- -void TTwirlStrokeStyle::setParamValue(int index, double value) -{ - assert(0 <= index && index < 2); - if (index == 0) - m_period = value; - else - m_blend = value; +void TTwirlStrokeStyle::drawStroke(const TColorFunction *cf, Doubles &data, + const TStroke *stroke) const { + TPixel32 blackcolor = TPixel32::Black; + + TPixel32 color; + if (cf) { + color = (*(cf))(m_color); + blackcolor = (*(cf))(blackcolor); + } else { + color = m_color; + } + blackcolor.m = m_color.m; + + TPointD app; + UINT i = 0; + + glBegin(GL_QUAD_STRIP); + for (; i < data.size(); i += 5) { + tglColor(blend(blackcolor, color, data[i + 4])); + app.x = data[i]; + app.y = data[i + 1]; + tglVertex(app); + app.x = data[i + 2]; + app.y = data[i + 3]; + tglVertex(app); + } + glEnd(); - updateVersionNumber(); + for (i = 5; i < data.size(); i += 5) { + tglColor(blend(color, blackcolor, data[i + 4])); + glBegin(GL_LINES); + app.x = data[i - 5]; + app.y = data[i - 4]; + tglVertex(app); + app.x = data[i]; + app.y = data[i + 1]; + tglVertex(app); + glEnd(); + glBegin(GL_LINES); + app.x = data[i - 3]; + app.y = data[i - 2]; + tglVertex(app); + app.x = data[i + 2]; + app.y = data[i + 3]; + tglVertex(app); + glEnd(); + } } //----------------------------------------------------------------------------- -void TTwirlStrokeStyle::computeData(Doubles &data, const TStroke *stroke, const TColorFunction *cf) const -{ - double length = stroke->getLength(); - double step = 5.0; - double period = 10 * (102 - m_period); - double hperiod = period / 2; - double blendval = 0; - TRandom rnd; - - data.clear(); - data.reserve(tceil(length / step) + 1); - - double s = 0; - TPointD app; - while (s <= length) { - double w = stroke->getParameterAtLength(s); - if (w < 0) { - s += 0.1; - continue; - } // per tamponare il baco della getParameterAtLength() - TThickPoint pos = stroke->getThickPoint(w); - TPointD u = stroke->getSpeed(w); - if (norm2(u) == 0) { - s += 0.1; - continue; - } // non dovrebbe succedere mai, ma per prudenza.... - u = normalize(u); - TPointD v = rotate90(u) * (pos.thick); - double shift = sin((TConsts::pi / hperiod) * s); - - app = pos + v * shift; - data.push_back(app.x); - data.push_back(app.y); - app = pos - v * shift; - data.push_back(app.x); - data.push_back(app.y); - - blendval = get_inout_intensityslope(m_blend, 1.0 - m_blend, (s - ((int)(s / hperiod) * hperiod)) / hperiod); - data.push_back(blendval); - s += step; - } -} - -//----------------------------------------------------------------------------- - -void TTwirlStrokeStyle::drawStroke(const TColorFunction *cf, Doubles &data, const TStroke *stroke) const -{ - TPixel32 blackcolor = TPixel32::Black; - - TPixel32 color; - if (cf) { - color = (*(cf))(m_color); - blackcolor = (*(cf))(blackcolor); - } else { - color = m_color; - } - blackcolor.m = m_color.m; - - TPointD app; - UINT i = 0; - - glBegin(GL_QUAD_STRIP); - for (; i < data.size(); i += 5) { - tglColor(blend(blackcolor, color, data[i + 4])); - app.x = data[i]; - app.y = data[i + 1]; - tglVertex(app); - app.x = data[i + 2]; - app.y = data[i + 3]; - tglVertex(app); - } - glEnd(); - - for (i = 5; i < data.size(); i += 5) { - tglColor(blend(color, blackcolor, data[i + 4])); - glBegin(GL_LINES); - app.x = data[i - 5]; - app.y = data[i - 4]; - tglVertex(app); - app.x = data[i]; - app.y = data[i + 1]; - tglVertex(app); - glEnd(); - glBegin(GL_LINES); - app.x = data[i - 3]; - app.y = data[i - 2]; - tglVertex(app); - app.x = data[i + 2]; - app.y = data[i + 3]; - tglVertex(app); - glEnd(); - } -} - -//----------------------------------------------------------------------------- - -void TTwirlStrokeStyle::drawStroke(TFlash &flash, const TStroke *stroke) const -{ +void TTwirlStrokeStyle::drawStroke(TFlash &flash, const TStroke *stroke) const { + double length = stroke->getLength(); + double step = 5.0; + double period = 10 * (102 - m_period); + double hperiod = period / 2; + double blendval = 0; + TRandom rnd; + TPixel32 blackcolor = TPixel32::Black; + TPixel32 color = m_color; + blackcolor.m = m_color.m; + + vector points1; + vector points2; + vector vblend; + double s = 0; + while (s <= length) { + double w = stroke->getParameterAtLength(s); + if (w < 0) { + s += 0.1; + continue; + } // per tamponare il baco della getParameterAtLength() + TThickPoint pos = stroke->getThickPoint(w); + TPointD u = stroke->getSpeed(w); + if (norm2(u) == 0) { + s += 0.1; + continue; + } // non dovrebbe succedere mai, ma per prudenza.... + u = normalize(u); + TPointD v = rotate90(u) * (pos.thick); + double shift = sin((M_PI / hperiod) * s); + points1.push_back(pos + v * shift); + points2.push_back(pos - v * shift); + blendval = get_inout_intensityslope( + m_blend, 1.0 - m_blend, (s - ((int)(s / hperiod) * hperiod)) / hperiod); + vblend.push_back(blendval); + s += step; + } - double length = stroke->getLength(); - double step = 5.0; - double period = 10 * (102 - m_period); - double hperiod = period / 2; - double blendval = 0; - TRandom rnd; - TPixel32 blackcolor = TPixel32::Black; - TPixel32 color = m_color; - blackcolor.m = m_color.m; - - vector points1; - vector points2; - vector vblend; - double s = 0; - while (s <= length) { - double w = stroke->getParameterAtLength(s); - if (w < 0) { - s += 0.1; - continue; - } // per tamponare il baco della getParameterAtLength() - TThickPoint pos = stroke->getThickPoint(w); - TPointD u = stroke->getSpeed(w); - if (norm2(u) == 0) { - s += 0.1; - continue; - } // non dovrebbe succedere mai, ma per prudenza.... - u = normalize(u); - TPointD v = rotate90(u) * (pos.thick); - double shift = sin((TConsts::pi / hperiod) * s); - points1.push_back(pos + v * shift); - points2.push_back(pos - v * shift); - blendval = get_inout_intensityslope(m_blend, 1.0 - m_blend, (s - ((int)(s / hperiod) * hperiod)) / hperiod); - vblend.push_back(blendval); - s += step; - } - - SFlashUtils sfu; - for (int i = 1; i < (int)points1.size(); i++) { - vector vp; - vp.push_back(points1[i - 1]); - vp.push_back(points2[i - 1]); - vp.push_back(points2[i]); - vp.push_back(points1[i]); - flash.setThickness(0.0); - sfu.drawGradedPolyline(flash, vp, blend(blackcolor, color, vblend[i - 1]), - blend(blackcolor, color, vblend[i])); - // flash.setFillColor(blend(blackcolor, color , vblend[i-1])); - // flash.drawPolyline(vp); - - vector sv; - sv.push_back(TSegment(points1[i - 1], points1[i])); - sv.push_back(TSegment(points2[i - 1], points2[i])); - flash.setThickness(1.0); - flash.setLineColor(blend(color, blackcolor, vblend[i - 1])); - flash.drawSegments(sv, false); - } + SFlashUtils sfu; + for (int i = 1; i < (int)points1.size(); i++) { + vector vp; + vp.push_back(points1[i - 1]); + vp.push_back(points2[i - 1]); + vp.push_back(points2[i]); + vp.push_back(points1[i]); + flash.setThickness(0.0); + sfu.drawGradedPolyline(flash, vp, blend(blackcolor, color, vblend[i - 1]), + blend(blackcolor, color, vblend[i])); + // flash.setFillColor(blend(blackcolor, color , vblend[i-1])); + // flash.drawPolyline(vp); + + vector sv; + sv.push_back(TSegment(points1[i - 1], points1[i])); + sv.push_back(TSegment(points2[i - 1], points2[i])); + flash.setThickness(1.0); + flash.setLineColor(blend(color, blackcolor, vblend[i - 1])); + flash.drawSegments(sv, false); + } } //============================================================================= TSawToothStrokeStyle::TSawToothStrokeStyle(TPixel32 color, double parameter) - : m_color(color), m_parameter(parameter) -{ + : m_color(color), m_parameter(parameter) {} + +//----------------------------------------------------------------------------- + +TColorStyle *TSawToothStrokeStyle::clone() const { + return new TSawToothStrokeStyle(*this); } //----------------------------------------------------------------------------- -TColorStyle *TSawToothStrokeStyle::clone() const -{ - return new TSawToothStrokeStyle(*this); +void TSawToothStrokeStyle::computeOutline( + const TStroke *stroke, TStrokeOutline &outline, + TOutlineUtil::OutlineParameter param) const { + param.m_lengthStep = m_parameter; + TOutlineStyle::computeOutline(stroke, outline, param); } //----------------------------------------------------------------------------- -void TSawToothStrokeStyle::computeOutline(const TStroke *stroke, - TStrokeOutline &outline, - TOutlineUtil::OutlineParameter param) const -{ - param.m_lengthStep = m_parameter; - TOutlineStyle::computeOutline(stroke, outline, param); +void TSawToothStrokeStyle::drawStroke(TFlash &flash, + const TStroke *stroke) const { + TOutlineUtil::OutlineParameter param; + param.m_lengthStep = std::max(20.0, m_parameter); + TStrokeOutline outline; + TOutlineStyle::computeOutline(stroke, outline, param); + const std::vector &v = outline.getArray(); + if (v.empty()) return; + + TPixel32 color = m_color; + flash.setThickness(0.0); + flash.setFillColor(color); + + if (v.empty()) return; + double old[2]; + int counter = 0; + for (UINT i = 0; i < v.size() - 2; i += 2) { + if (0 != v[i].stepCount) { + if (counter) { + vector plv; + // flash.setFillColor(color); + + plv.push_back(TPointD(old[0], old[1])); + plv.push_back(TPointD(v[i].x, v[i].y)); + plv.push_back(TPointD(v[i + 1].x, v[i + 1].y)); + flash.drawPolyline(plv); + } + old[0] = v[i].x; + old[1] = v[i].y; + counter++; + } + } } //----------------------------------------------------------------------------- -void TSawToothStrokeStyle::drawStroke(TFlash &flash, const TStroke *stroke) const -{ - TOutlineUtil::OutlineParameter param; - param.m_lengthStep = std::max(20.0, m_parameter); - TStrokeOutline outline; - TOutlineStyle::computeOutline(stroke, outline, param); - const std::vector &v = outline.getArray(); - if (v.empty()) - return; - - TPixel32 color = m_color; - flash.setThickness(0.0); - flash.setFillColor(color); - - if (v.empty()) - return; - double old[2]; - int counter = 0; - for (UINT i = 0; i < v.size() - 2; i += 2) { - if (0 != v[i].stepCount) { - if (counter) { - vector plv; - // flash.setFillColor(color); - - plv.push_back(TPointD(old[0], old[1])); - plv.push_back(TPointD(v[i].x, v[i].y)); - plv.push_back(TPointD(v[i + 1].x, v[i + 1].y)); - flash.drawPolyline(plv); - } - old[0] = v[i].x; - old[1] = v[i].y; - counter++; - } - } -} - -//----------------------------------------------------------------------------- - -void TSawToothStrokeStyle::drawStroke(const TColorFunction *cf, TStrokeOutline *outline, - const TStroke *stroke) const -{ - UINT i; - int counter = 0; - TPixel32 color; - if (cf) - color = (*(cf))(m_color); - else - color = m_color; - tglColor(color); - const std::vector &v = outline->getArray(); - if (v.empty()) - return; - double old[2]; - // outline with antialiasing - glBegin(GL_LINE_STRIP); - for (i = 0; i < v.size() - 2; i += 2) { - if (0 != v[i].stepCount) { - if (counter) { - glVertex2dv(old); - glVertex2dv(&v[i].x); - glVertex2dv(&v[i + 1].x); - glVertex2dv(old); - } - old[0] = v[i].x; - old[1] = v[i].y; - counter++; - } - } - glEnd(); - counter = 0; - glBegin(GL_TRIANGLES); - for (i = 0; i < v.size() - 2; i += 2) { - if (0 != v[i].stepCount) { - if (counter) { - glVertex2dv(old); - glVertex2dv(&v[i].x); - glVertex2dv(&v[i + 1].x); - } - old[0] = v[i].x; - old[1] = v[i].y; - counter++; - } - } - glEnd(); -} - -//----------------------------------------------------------------------------- - -int TSawToothStrokeStyle::getParamCount() const -{ - return 1; +void TSawToothStrokeStyle::drawStroke(const TColorFunction *cf, + TStrokeOutline *outline, + const TStroke *stroke) const { + UINT i; + int counter = 0; + TPixel32 color; + if (cf) + color = (*(cf))(m_color); + else + color = m_color; + tglColor(color); + const std::vector &v = outline->getArray(); + if (v.empty()) return; + double old[2]; + // outline with antialiasing + glBegin(GL_LINE_STRIP); + for (i = 0; i < v.size() - 2; i += 2) { + if (0 != v[i].stepCount) { + if (counter) { + glVertex2dv(old); + glVertex2dv(&v[i].x); + glVertex2dv(&v[i + 1].x); + glVertex2dv(old); + } + old[0] = v[i].x; + old[1] = v[i].y; + counter++; + } + } + glEnd(); + counter = 0; + glBegin(GL_TRIANGLES); + for (i = 0; i < v.size() - 2; i += 2) { + if (0 != v[i].stepCount) { + if (counter) { + glVertex2dv(old); + glVertex2dv(&v[i].x); + glVertex2dv(&v[i + 1].x); + } + old[0] = v[i].x; + old[1] = v[i].y; + counter++; + } + } + glEnd(); } //----------------------------------------------------------------------------- -TColorStyle::ParamType TSawToothStrokeStyle::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +int TSawToothStrokeStyle::getParamCount() const { return 1; } + +//----------------------------------------------------------------------------- + +TColorStyle::ParamType TSawToothStrokeStyle::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -QString TSawToothStrokeStyle::getParamNames(int index) const -{ - assert(0 <= index && index < 1); +QString TSawToothStrokeStyle::getParamNames(int index) const { + assert(0 <= index && index < 1); - return QCoreApplication::translate("TSawToothStrokeStyle", "Distance"); + return QCoreApplication::translate("TSawToothStrokeStyle", "Distance"); } //----------------------------------------------------------------------------- -void TSawToothStrokeStyle::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 1); - min = 0.1; - max = 100.0; +void TSawToothStrokeStyle::getParamRange(int index, double &min, + double &max) const { + assert(0 <= index && index < 1); + min = 0.1; + max = 100.0; } //----------------------------------------------------------------------------- -double TSawToothStrokeStyle::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 1); - return m_parameter; +double TSawToothStrokeStyle::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 1); + return m_parameter; } //----------------------------------------------------------------------------- -void TSawToothStrokeStyle::setParamValue(int index, double value) -{ - assert(0 <= index && index < 1); - m_parameter = value; - updateVersionNumber(); //questo si chiama per ogno cambiamento di parametro per cui di deve ricalcolare l'outline +void TSawToothStrokeStyle::setParamValue(int index, double value) { + assert(0 <= index && index < 1); + m_parameter = value; + updateVersionNumber(); // questo si chiama per ogno cambiamento di parametro + // per cui di deve ricalcolare l'outline } //============================================================================= TMultiLineStrokeStyle2::TMultiLineStrokeStyle2() - : m_color0(TPixel32(0, 255, 0)), m_color1(TPixel32(0, 0, 0)), m_intensity(0.2), m_length(20.0), m_thick(0.3), m_noise(0.5) -{ -} + : m_color0(TPixel32(0, 255, 0)) + , m_color1(TPixel32(0, 0, 0)) + , m_intensity(0.2) + , m_length(20.0) + , m_thick(0.3) + , m_noise(0.5) {} //----------------------------------------------------------------------------- -TColorStyle *TMultiLineStrokeStyle2::clone() const -{ - return new TMultiLineStrokeStyle2(*this); +TColorStyle *TMultiLineStrokeStyle2::clone() const { + return new TMultiLineStrokeStyle2(*this); } //----------------------------------------------------------------------------- -namespace -{ +namespace { typedef struct { - TPointD u, v; - TThickPoint p; + TPointD u, v; + TThickPoint p; } myLineData; } //----------------------------------------------------------------------------- -int TMultiLineStrokeStyle2::getParamCount() const -{ - return 4; -} +int TMultiLineStrokeStyle2::getParamCount() const { return 4; } //----------------------------------------------------------------------------- -TColorStyle::ParamType TMultiLineStrokeStyle2::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +TColorStyle::ParamType TMultiLineStrokeStyle2::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -QString TMultiLineStrokeStyle2::getParamNames(int index) const -{ - assert(0 <= index && index < 4); - QString value; - switch (index) { - case 0: - value = QCoreApplication::translate("TMultiLineStrokeStyle2", "Density"); - break; - case 1: - value = QCoreApplication::translate("TMultiLineStrokeStyle2", "Size"); - break; - case 2: - value = QCoreApplication::translate("TMultiLineStrokeStyle2", "Thickness"); - break; - case 3: - value = QCoreApplication::translate("TMultiLineStrokeStyle2", "Noise"); - break; - } - return value; -} - -//----------------------------------------------------------------------------- - -void TMultiLineStrokeStyle2::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 4); - switch (index) { - case 0: - min = 0.0; - max = 1.0; - break; - case 1: - min = 0.0; - max = 100.0; - break; - case 2: - min = 0.0; - max = 1.0; - break; - case 3: - min = 0.0; - max = 1.0; - break; - } -} -//----------------------------------------------------------------------------- - -double TMultiLineStrokeStyle2::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 4); - double value = 0; - switch (index) { - case 0: - value = m_intensity; - break; - case 1: - value = m_length; - break; - case 2: - value = m_thick; - break; - case 3: - value = m_noise; - break; - } - return value; -} - -//----------------------------------------------------------------------------- - -void TMultiLineStrokeStyle2::setParamValue(int index, double value) -{ - assert(0 <= index && index < 4); - switch (index) { - case 0: - m_intensity = value; - break; - case 1: - m_length = value; - break; - case 2: - m_thick = value; - break; - case 3: - m_noise = value; - break; - } +QString TMultiLineStrokeStyle2::getParamNames(int index) const { + assert(0 <= index && index < 4); + QString value; + switch (index) { + case 0: + value = QCoreApplication::translate("TMultiLineStrokeStyle2", "Density"); + break; + case 1: + value = QCoreApplication::translate("TMultiLineStrokeStyle2", "Size"); + break; + case 2: + value = QCoreApplication::translate("TMultiLineStrokeStyle2", "Thickness"); + break; + case 3: + value = QCoreApplication::translate("TMultiLineStrokeStyle2", "Noise"); + break; + } + return value; +} + +//----------------------------------------------------------------------------- + +void TMultiLineStrokeStyle2::getParamRange(int index, double &min, + double &max) const { + assert(0 <= index && index < 4); + switch (index) { + case 0: + min = 0.0; + max = 1.0; + break; + case 1: + min = 0.0; + max = 100.0; + break; + case 2: + min = 0.0; + max = 1.0; + break; + case 3: + min = 0.0; + max = 1.0; + break; + } +} +//----------------------------------------------------------------------------- + +double TMultiLineStrokeStyle2::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 4); + double value = 0; + switch (index) { + case 0: + value = m_intensity; + break; + case 1: + value = m_length; + break; + case 2: + value = m_thick; + break; + case 3: + value = m_noise; + break; + } + return value; +} + +//----------------------------------------------------------------------------- + +void TMultiLineStrokeStyle2::setParamValue(int index, double value) { + assert(0 <= index && index < 4); + switch (index) { + case 0: + m_intensity = value; + break; + case 1: + m_length = value; + break; + case 2: + m_thick = value; + break; + case 3: + m_noise = value; + break; + } - updateVersionNumber(); + updateVersionNumber(); } //----------------------------------------------------------------------------- -void TMultiLineStrokeStyle2::loadData(int ids, TInputStreamInterface &is) -{ - if (ids != 118 && ids != 128) - throw TException("Multi Line stroke style: unknown obsolete format"); - if (ids == 118) { - m_length = 20.0, m_thick = 0.3, m_noise = 0.0; - is >> m_color0 >> m_intensity; - m_color1 = TPixel32::Black; - } else { - is >> m_color0 >> m_intensity >> m_length >> m_thick >> m_noise; - m_color1 = TPixel32::Black; - } +void TMultiLineStrokeStyle2::loadData(int ids, TInputStreamInterface &is) { + if (ids != 118 && ids != 128) + throw TException("Multi Line stroke style: unknown obsolete format"); + if (ids == 118) { + m_length = 20.0, m_thick = 0.3, m_noise = 0.0; + is >> m_color0 >> m_intensity; + m_color1 = TPixel32::Black; + } else { + is >> m_color0 >> m_intensity >> m_length >> m_thick >> m_noise; + m_color1 = TPixel32::Black; + } } //----------------------------------------------------------------------------- -void TMultiLineStrokeStyle2::computeData(BlendAndPoints &data, const TStroke *stroke, const TColorFunction *cf) const -{ - //TStroke *stroke = getStroke(); - double length = stroke->getLength(); - double step = 4.0; - int maxlength = (int)m_length; - double factor = 0; - TRandom rnd; - - vector LineData; - myLineData Data; - double s = 0; - - double minthickness = MINTHICK * sqrt(tglGetPixelSize2()); - double thickness = 0; - double strokethick = m_thick; - while (s <= length) { - double w = stroke->getParameterAtLength(s); - if (w < 0) { - s += 0.1; - continue; - } // per tamponare il baco della getParameterAtLength() - Data.p = stroke->getThickPoint(w); - Data.u = stroke->getSpeed(w); - if (norm2(Data.u) == 0) { - s += 0.1; - continue; - } // non dovrebbe succedere mai, ma per prudenza.... - Data.u = normalize(Data.u); - if (Data.p.thick < MINTHICK) - thickness = minthickness; - else - thickness = Data.p.thick; - Data.v = rotate90(Data.u) * thickness; - - LineData.push_back(Data); - s += step; - } - - BlendAndPoint appData; - - data.clear(); - data.reserve(LineData.size()); - - for (int i = 0; i < m_intensity * LineData.size(); i++) { - appData.points.clear(); - int start = rnd.getInt(0, LineData.size()); - int end = start + maxlength + rnd.getInt(0, maxlength); - if (end > (int)LineData.size()) - end = LineData.size(); - double halfcount = (end - start) / 2.0; - double vshift = (0.5 - rnd.getFloat()); - - appData.blend = rnd.getFloat(); - - for (int j = 0; j < (end - start); j++) { - if (j < halfcount) - factor = j / halfcount; - else - factor = 1 - (j - halfcount) / halfcount; - appData.points.push_back(LineData[j + start].p + LineData[j + start].v * (vshift - strokethick * factor * (1 - m_noise * (1 - rnd.getFloat())))); - appData.points.push_back(LineData[j + start].p + LineData[j + start].v * (vshift + strokethick * factor * (1 - m_noise * (1 - rnd.getFloat())))); - } - data.push_back(appData); - } -} - -//----------------------------------------------------------------------------- - -void TMultiLineStrokeStyle2::drawStroke(const TColorFunction *cf, BlendAndPoints &data, const TStroke *stroke) const -{ - TPixel32 color0, color1; - if (cf) { - color0 = (*(cf))(m_color0); - color1 = (*(cf))(m_color1); - } else { - color0 = m_color0; - color1 = m_color1; - } +void TMultiLineStrokeStyle2::computeData(BlendAndPoints &data, + const TStroke *stroke, + const TColorFunction *cf) const { + // TStroke *stroke = getStroke(); + double length = stroke->getLength(); + double step = 4.0; + int maxlength = (int)m_length; + double factor = 0; + TRandom rnd; + + vector LineData; + myLineData Data; + double s = 0; + + double minthickness = MINTHICK * sqrt(tglGetPixelSize2()); + double thickness = 0; + double strokethick = m_thick; + while (s <= length) { + double w = stroke->getParameterAtLength(s); + if (w < 0) { + s += 0.1; + continue; + } // per tamponare il baco della getParameterAtLength() + Data.p = stroke->getThickPoint(w); + Data.u = stroke->getSpeed(w); + if (norm2(Data.u) == 0) { + s += 0.1; + continue; + } // non dovrebbe succedere mai, ma per prudenza.... + Data.u = normalize(Data.u); + if (Data.p.thick < MINTHICK) + thickness = minthickness; + else + thickness = Data.p.thick; + Data.v = rotate90(Data.u) * thickness; + + LineData.push_back(Data); + s += step; + } - glEnable(GL_POLYGON_SMOOTH); + BlendAndPoint appData; + + data.clear(); + data.reserve(LineData.size()); + + for (int i = 0; i < m_intensity * LineData.size(); i++) { + appData.points.clear(); + int start = rnd.getInt(0, LineData.size()); + int end = start + maxlength + rnd.getInt(0, maxlength); + if (end > (int)LineData.size()) end = LineData.size(); + double halfcount = (end - start) / 2.0; + double vshift = (0.5 - rnd.getFloat()); + + appData.blend = rnd.getFloat(); + + for (int j = 0; j < (end - start); j++) { + if (j < halfcount) + factor = j / halfcount; + else + factor = 1 - (j - halfcount) / halfcount; + appData.points.push_back( + LineData[j + start].p + + LineData[j + start].v * + (vshift - + strokethick * factor * (1 - m_noise * (1 - rnd.getFloat())))); + appData.points.push_back( + LineData[j + start].p + + LineData[j + start].v * + (vshift + + strokethick * factor * (1 - m_noise * (1 - rnd.getFloat())))); + } + data.push_back(appData); + } +} - for (UINT i = 0; i < data.size(); i++) { - tglColor(blend(color0, color1, data[i].blend)); +//----------------------------------------------------------------------------- - glBegin(GL_QUAD_STRIP); - for (UINT j = 0; j < data[i].points.size(); j++) - tglVertex(data[i].points[j]); +void TMultiLineStrokeStyle2::drawStroke(const TColorFunction *cf, + BlendAndPoints &data, + const TStroke *stroke) const { + TPixel32 color0, color1; + if (cf) { + color0 = (*(cf))(m_color0); + color1 = (*(cf))(m_color1); + } else { + color0 = m_color0; + color1 = m_color1; + } - glEnd(); - } - glDisable(GL_POLYGON_SMOOTH); -} + glEnable(GL_POLYGON_SMOOTH); -//----------------------------------------------------------------------------- + for (UINT i = 0; i < data.size(); i++) { + tglColor(blend(color0, color1, data[i].blend)); -void TMultiLineStrokeStyle2::drawStroke(TFlash &flash, const TStroke *stroke) const -{ - //TStroke *stroke = getStroke(); - double length = stroke->getLength(); - double step = 4.0; - int maxlength = (int)m_length; - double factor = 0; - TRandom rnd; - TPixel32 color0, color1; - color0 = m_color0; - color1 = m_color1; - - vector LineData; - myLineData Data; - double s = 0; - double strokethick = m_thick; - while (s <= length) { - double w = stroke->getParameterAtLength(s); - if (w < 0) { - s += 0.1; - continue; - } // per tamponare il baco della getParameterAtLength() - Data.p = stroke->getThickPoint(w); - Data.u = stroke->getSpeed(w); - if (norm2(Data.u) == 0) { - s += 0.1; - continue; - } // non dovrebbe succedere mai, ma per prudenza.... - Data.u = normalize(Data.u); - Data.v = rotate90(Data.u) * Data.p.thick; - LineData.push_back(Data); - s += step; - } - - for (int i = 0; i < m_intensity * LineData.size(); i++) { - int start = rnd.getInt(0, LineData.size()); - int end = start + maxlength + rnd.getInt(0, maxlength); - if (end > (int)LineData.size()) - end = LineData.size(); - double halfcount = (end - start) / 2.0; - double vshift = (0.5 - rnd.getFloat()); - flash.setThickness(0.0); - flash.setFillColor(blend(color0, color1, rnd.getFloat())); - vector sv; - int j; - for (j = 0; j < (end - start); j++) { - if (j < halfcount) - factor = j / halfcount; - else - factor = 1 - (j - halfcount) / halfcount; - float rand = rnd.getFloat(); - TPointD p0 = (LineData[j + start].p + LineData[j + start].v * (vshift - strokethick * factor * (1 - m_noise * (1 - rand)))); - TPointD p1 = (LineData[j + start].p + LineData[j + start].v * (vshift + strokethick * factor * (1 - m_noise * (1 - rand)))); - sv.push_back(TSegment(p0, p1)); - } - for (j = 0; j < ((int)sv.size() - 1); j++) { - vector pv; - pv.push_back(sv[j].getP0()); - pv.push_back(sv[j].getP1()); - pv.push_back(sv[j + 1].getP1()); - pv.push_back(sv[j + 1].getP0()); - flash.drawPolyline(pv); - } - } + glBegin(GL_QUAD_STRIP); + for (UINT j = 0; j < data[i].points.size(); j++) + tglVertex(data[i].points[j]); + + glEnd(); + } + glDisable(GL_POLYGON_SMOOTH); +} + +//----------------------------------------------------------------------------- + +void TMultiLineStrokeStyle2::drawStroke(TFlash &flash, + const TStroke *stroke) const { + // TStroke *stroke = getStroke(); + double length = stroke->getLength(); + double step = 4.0; + int maxlength = (int)m_length; + double factor = 0; + TRandom rnd; + TPixel32 color0, color1; + color0 = m_color0; + color1 = m_color1; + + vector LineData; + myLineData Data; + double s = 0; + double strokethick = m_thick; + while (s <= length) { + double w = stroke->getParameterAtLength(s); + if (w < 0) { + s += 0.1; + continue; + } // per tamponare il baco della getParameterAtLength() + Data.p = stroke->getThickPoint(w); + Data.u = stroke->getSpeed(w); + if (norm2(Data.u) == 0) { + s += 0.1; + continue; + } // non dovrebbe succedere mai, ma per prudenza.... + Data.u = normalize(Data.u); + Data.v = rotate90(Data.u) * Data.p.thick; + LineData.push_back(Data); + s += step; + } + + for (int i = 0; i < m_intensity * LineData.size(); i++) { + int start = rnd.getInt(0, LineData.size()); + int end = start + maxlength + rnd.getInt(0, maxlength); + if (end > (int)LineData.size()) end = LineData.size(); + double halfcount = (end - start) / 2.0; + double vshift = (0.5 - rnd.getFloat()); + flash.setThickness(0.0); + flash.setFillColor(blend(color0, color1, rnd.getFloat())); + vector sv; + int j; + for (j = 0; j < (end - start); j++) { + if (j < halfcount) + factor = j / halfcount; + else + factor = 1 - (j - halfcount) / halfcount; + float rand = rnd.getFloat(); + TPointD p0 = + (LineData[j + start].p + + LineData[j + start].v * + (vshift - strokethick * factor * (1 - m_noise * (1 - rand)))); + TPointD p1 = + (LineData[j + start].p + + LineData[j + start].v * + (vshift + strokethick * factor * (1 - m_noise * (1 - rand)))); + sv.push_back(TSegment(p0, p1)); + } + for (j = 0; j < ((int)sv.size() - 1); j++) { + vector pv; + pv.push_back(sv[j].getP0()); + pv.push_back(sv[j].getP1()); + pv.push_back(sv[j + 1].getP1()); + pv.push_back(sv[j + 1].getP0()); + flash.drawPolyline(pv); + } + } } //============================================================================= TZigzagStrokeStyle::TZigzagStrokeStyle() - : m_color(TPixel32(0, 0, 0)), m_minDist(0.5), m_maxDist(6.0), m_minAngle(30.0), m_maxAngle(60.0), m_thickness(1.0) -{ + : m_color(TPixel32(0, 0, 0)) + , m_minDist(0.5) + , m_maxDist(6.0) + , m_minAngle(30.0) + , m_maxAngle(60.0) + , m_thickness(1.0) {} + +//----------------------------------------------------------------------------- + +TColorStyle *TZigzagStrokeStyle::clone() const { + return new TZigzagStrokeStyle(*this); +} + +//----------------------------------------------------------------------------- + +int TZigzagStrokeStyle::getParamCount() const { return 5; } + +//----------------------------------------------------------------------------- + +TColorStyle::ParamType TZigzagStrokeStyle::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; +} + +//----------------------------------------------------------------------------- + +QString TZigzagStrokeStyle::getParamNames(int index) const { + assert(0 <= index && index < 5); + QString value; + switch (index) { + case 0: + value = QCoreApplication::translate("TZigzagStrokeStyle", "Min Distance"); + break; + case 1: + value = QCoreApplication::translate("TZigzagStrokeStyle", "Max Distance"); + break; + case 2: + value = QCoreApplication::translate("TZigzagStrokeStyle", "Min Angle"); + break; + case 3: + value = QCoreApplication::translate("TZigzagStrokeStyle", "Max Angle"); + break; + case 4: + value = QCoreApplication::translate("TZigzagStrokeStyle", "Thickness"); + break; + } + return value; +} + +//----------------------------------------------------------------------------- + +void TZigzagStrokeStyle::getParamRange(int index, double &min, + double &max) const { + assert(0 <= index && index < 5); + switch (index) { + case 0: + min = 0.5; + max = 50.0; + break; + case 1: + min = 0.5; + max = 50.0; + break; + case 2: + min = -90.0; + max = 90.0; + break; + case 3: + min = -90.0; + max = 90.0; + break; + case 4: + min = 0.0; + max = 3.0; + break; + } } //----------------------------------------------------------------------------- -TColorStyle *TZigzagStrokeStyle::clone() const -{ - return new TZigzagStrokeStyle(*this); +double TZigzagStrokeStyle::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 5); + double value = 0; + switch (index) { + case 0: + value = m_minDist; + break; + case 1: + value = m_maxDist; + break; + case 2: + value = m_minAngle; + break; + case 3: + value = m_maxAngle; + break; + case 4: + value = m_thickness; + break; + } + return value; +} + +//----------------------------------------------------------------------------- + +void TZigzagStrokeStyle::setParamValue(int index, double value) { + assert(0 <= index && index < 5); + switch (index) { + case 0: + m_minDist = value; + break; + case 1: + m_maxDist = value; + break; + case 2: + m_minAngle = value; + break; + case 3: + m_maxAngle = value; + break; + case 4: + m_thickness = value; + break; + } + updateVersionNumber(); } //----------------------------------------------------------------------------- -int TZigzagStrokeStyle::getParamCount() const -{ - return 5; +bool TZigzagStrokeStyle::getZigZagPosition(const TStroke *stroke, TRandom &rnd, + const double s, const int first, + const double minTranslLength, + TThickPoint &pos, + TThickPoint &pos1) const { + double w = stroke->getParameterAtLength(s); + pos = stroke->getThickPoint(w); + TPointD u = stroke->getSpeed(w); + if (norm2(u) < TConsts::epsilon) return false; + u = normalize(u); + TPointD uu = u; + double angle = + m_minAngle + (m_maxAngle - m_minAngle) * (double)rnd.getUInt(101) * 0.01; + TRotation rotM(angle); + u = rotM * u; + double maxTranslLength = angle == 90 ? 1.0 : 2.0; + if (angle > 30 && angle < 90) { + double rta = 1.0 / tan(degree2rad(angle)); + maxTranslLength = sqrt(sq(rta) + 1.0); + } + double r = + (minTranslLength + (maxTranslLength - minTranslLength) * rnd.getFloat()) * + pos.thick * first; + pos = pos + r * u; + pos1 = pos + uu * m_thickness; + return true; } //----------------------------------------------------------------------------- -TColorStyle::ParamType TZigzagStrokeStyle::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +void TZigzagStrokeStyle::setRealMinMax() const { + TZigzagStrokeStyle *ncpthis = const_cast(this); + double minDist = std::min(m_minDist, m_maxDist); + double maxDist = std::max(m_minDist, m_maxDist); + double minAngle = std::min(m_minAngle, m_maxAngle); + double maxAngle = std::max(m_minAngle, m_maxAngle); + ncpthis->m_minDist = minDist; + ncpthis->m_maxDist = maxDist; + ncpthis->m_minAngle = minAngle; + ncpthis->m_maxAngle = maxAngle; } //----------------------------------------------------------------------------- -QString TZigzagStrokeStyle::getParamNames(int index) const -{ - assert(0 <= index && index < 5); - QString value; - switch (index) { - case 0: - value = QCoreApplication::translate("TZigzagStrokeStyle", "Min Distance"); - break; - case 1: - value = QCoreApplication::translate("TZigzagStrokeStyle", "Max Distance"); - break; - case 2: - value = QCoreApplication::translate("TZigzagStrokeStyle", "Min Angle"); - break; - case 3: - value = QCoreApplication::translate("TZigzagStrokeStyle", "Max Angle"); - break; - case 4: - value = QCoreApplication::translate("TZigzagStrokeStyle", "Thickness"); - break; - } - return value; -} - -//----------------------------------------------------------------------------- - -void TZigzagStrokeStyle::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 5); - switch (index) { - case 0: - min = 0.5; - max = 50.0; - break; - case 1: - min = 0.5; - max = 50.0; - break; - case 2: - min = -90.0; - max = 90.0; - break; - case 3: - min = -90.0; - max = 90.0; - break; - case 4: - min = 0.0; - max = 3.0; - break; - } -} - -//----------------------------------------------------------------------------- - -double TZigzagStrokeStyle::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 5); - double value = 0; - switch (index) { - case 0: - value = m_minDist; - break; - case 1: - value = m_maxDist; - break; - case 2: - value = m_minAngle; - break; - case 3: - value = m_maxAngle; - break; - case 4: - value = m_thickness; - break; - } - return value; -} - -//----------------------------------------------------------------------------- - -void TZigzagStrokeStyle::setParamValue(int index, double value) -{ - assert(0 <= index && index < 5); - switch (index) { - case 0: - m_minDist = value; - break; - case 1: - m_maxDist = value; - break; - case 2: - m_minAngle = value; - break; - case 3: - m_maxAngle = value; - break; - case 4: - m_thickness = value; - break; - } - updateVersionNumber(); -} +void TZigzagStrokeStyle::computeData(Points &points, const TStroke *stroke, + const TColorFunction *cf) const { + assert(glGetError() == GL_NO_ERROR); + assert(!!stroke); + double length = stroke->getLength(); + if (length <= 0) return; -//----------------------------------------------------------------------------- + setRealMinMax(); + // e.g minimum translation length is the half of the thickness + const double minTranslLength = 0.7; + // const bool isTransparent=m_color.m<255; -bool TZigzagStrokeStyle::getZigZagPosition(const TStroke *stroke, TRandom &rnd, - const double s, const int first, - const double minTranslLength, - TThickPoint &pos, TThickPoint &pos1) const -{ - double w = stroke->getParameterAtLength(s); - pos = stroke->getThickPoint(w); - TPointD u = stroke->getSpeed(w); - if (norm2(u) < TConsts::epsilon) - return false; - u = normalize(u); - TPointD uu = u; - double angle = m_minAngle + (m_maxAngle - m_minAngle) * (double)rnd.getUInt(101) * 0.01; - TRotation rotM(angle); - u = rotM * u; - double maxTranslLength = angle == 90 ? 1.0 : 2.0; - if (angle > 30 && angle < 90) { - double rta = 1.0 / tan(degree2rad(angle)); - maxTranslLength = sqrt(sq(rta) + 1.0); - } - double r = (minTranslLength + (maxTranslLength - minTranslLength) * rnd.getFloat()) * pos.thick * first; - pos = pos + r * u; - pos1 = pos + uu * m_thickness; - return true; -} - -//----------------------------------------------------------------------------- - -void TZigzagStrokeStyle::setRealMinMax() const -{ - TZigzagStrokeStyle *ncpthis = const_cast(this); - double minDist = std::min(m_minDist, m_maxDist); - double maxDist = std::max(m_minDist, m_maxDist); - double minAngle = std::min(m_minAngle, m_maxAngle); - double maxAngle = std::max(m_minAngle, m_maxAngle); - ncpthis->m_minDist = minDist; - ncpthis->m_maxDist = maxDist; - ncpthis->m_minAngle = minAngle; - ncpthis->m_maxAngle = maxAngle; + int first = 1; + TThickPoint pos; + TThickPoint pos1; + TRandom rnd; + + points.clear(); + points.reserve(tceil(length / m_minDist) * 2 + 2); + + for (double s = 0.0; s <= length; first = -first) { + if (getZigZagPosition(stroke, rnd, s, first, minTranslLength, pos, pos1)) { + // TRectD rec(pos.x,pos.y,pos1.x,pos1.y); + points.push_back(pos); + points.push_back(pos1); + } + s += m_minDist + (m_maxDist - m_minDist) * (double)rnd.getUInt(101) * 0.01; + } + if (getZigZagPosition(stroke, rnd, length - TConsts::epsilon, first, + minTranslLength, pos, pos1)) { + points.push_back(pos); + points.push_back(pos1); + } } //----------------------------------------------------------------------------- -void TZigzagStrokeStyle::computeData(Points &points, const TStroke *stroke, const TColorFunction *cf) const -{ - assert(glGetError() == GL_NO_ERROR); - assert(!!stroke); - double length = stroke->getLength(); - if (length <= 0) - return; - - setRealMinMax(); - // e.g minimum translation length is the half of the thickness - const double minTranslLength = 0.7; - //const bool isTransparent=m_color.m<255; - - int first = 1; - TThickPoint pos; - TThickPoint pos1; - TRandom rnd; - - points.clear(); - points.reserve(tceil(length / m_minDist) * 2 + 2); - - for (double s = 0.0; s <= length; first = -first) { - if (getZigZagPosition(stroke, rnd, s, first, minTranslLength, pos, pos1)) { - //TRectD rec(pos.x,pos.y,pos1.x,pos1.y); - points.push_back(pos); - points.push_back(pos1); - } - s += m_minDist + (m_maxDist - m_minDist) * (double)rnd.getUInt(101) * 0.01; - } - if (getZigZagPosition(stroke, rnd, length - TConsts::epsilon, first, minTranslLength, pos, pos1)) { - points.push_back(pos); - points.push_back(pos1); - } -} - -//----------------------------------------------------------------------------- - -void TZigzagStrokeStyle::drawStroke(const TColorFunction *cf, Points &points, const TStroke *stroke) const -{ - if (points.size() <= 1) - return; - TPixel32 color; +void TZigzagStrokeStyle::drawStroke(const TColorFunction *cf, Points &points, + const TStroke *stroke) const { + if (points.size() <= 1) return; + TPixel32 color; - if (cf) - color = (*(cf))(m_color); - else - color = m_color; + if (cf) + color = (*(cf))(m_color); + else + color = m_color; - tglColor(m_color); + tglColor(m_color); - glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_DOUBLE, sizeof(TPointD), &points[0]); - glDrawArrays(GL_QUAD_STRIP, 0, points.size()); - /* - glBegin(GL_QUAD_STRIP); - for(UINT i=0; igetLength(); + if (length <= 0) return; + + setRealMinMax(); + // e.g minimum translation length is the half of the thickness + const double minTranslLength = 0.7; + + int first = 1; + TThickPoint pos; + TThickPoint pos1; + TRandom rnd; + RectVector rects; - if (!stroke) - return; - double length = stroke->getLength(); - if (length <= 0) - return; - - setRealMinMax(); - // e.g minimum translation length is the half of the thickness - const double minTranslLength = 0.7; - - int first = 1; - TThickPoint pos; - TThickPoint pos1; - TRandom rnd; - RectVector rects; - - for (double s = 0.0; s <= length; first = -first) { - if (getZigZagPosition(stroke, rnd, s, first, minTranslLength, pos, pos1)) { - TRectD rec(pos.x, pos.y, pos1.x, pos1.y); - rects.push_back(rec); - } - s += m_minDist + (m_maxDist - m_minDist) * (double)rnd.getUInt(101) * 0.01; - } - if (getZigZagPosition(stroke, rnd, length - TConsts::epsilon, first, minTranslLength, pos, pos1)) { - TRectD rec(pos.x, pos.y, pos1.x, pos1.y); - rects.push_back(rec); - } - - flash.setLineColor(m_color); - vector segmentsArray; - - flash.setThickness(m_thickness); - RectVector::const_iterator rvi = rects.begin(); - for (; rvi != (rects.end() - 1); rvi++) { - RectVector::const_iterator rvii = rvi + 1; - TPointD p0((rvi->x0 + rvi->x1) / 2.0, (rvi->y0 + rvi->y1) / 2.0); - TPointD p1((rvii->x0 + rvii->x1) / 2.0, (rvii->y0 + rvii->y1) / 2.0); - segmentsArray.push_back(TSegment(p0, p1)); - } - - flash.drawSegments(segmentsArray, false); + for (double s = 0.0; s <= length; first = -first) { + if (getZigZagPosition(stroke, rnd, s, first, minTranslLength, pos, pos1)) { + TRectD rec(pos.x, pos.y, pos1.x, pos1.y); + rects.push_back(rec); + } + s += m_minDist + (m_maxDist - m_minDist) * (double)rnd.getUInt(101) * 0.01; + } + if (getZigZagPosition(stroke, rnd, length - TConsts::epsilon, first, + minTranslLength, pos, pos1)) { + TRectD rec(pos.x, pos.y, pos1.x, pos1.y); + rects.push_back(rec); + } + + flash.setLineColor(m_color); + vector segmentsArray; + + flash.setThickness(m_thickness); + RectVector::const_iterator rvi = rects.begin(); + for (; rvi != (rects.end() - 1); rvi++) { + RectVector::const_iterator rvii = rvi + 1; + TPointD p0((rvi->x0 + rvi->x1) / 2.0, (rvi->y0 + rvi->y1) / 2.0); + TPointD p1((rvii->x0 + rvii->x1) / 2.0, (rvii->y0 + rvii->y1) / 2.0); + segmentsArray.push_back(TSegment(p0, p1)); + } + + flash.drawSegments(segmentsArray, false); } //============================================================================= TSinStrokeStyle::TSinStrokeStyle() - : m_color(TPixel32::Black), m_frequency(10.0), m_thick(0.4) -{ + : m_color(TPixel32::Black), m_frequency(10.0), m_thick(0.4) {} + +//----------------------------------------------------------------------------- + +TColorStyle *TSinStrokeStyle::clone() const { + return new TSinStrokeStyle(*this); } //----------------------------------------------------------------------------- -TColorStyle *TSinStrokeStyle::clone() const -{ - return new TSinStrokeStyle(*this); +int TSinStrokeStyle::getParamCount() const { return 2; } + +//----------------------------------------------------------------------------- + +TColorStyle::ParamType TSinStrokeStyle::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -int TSinStrokeStyle::getParamCount() const -{ - return 2; +QString TSinStrokeStyle::getParamNames(int index) const { + assert(0 <= index && index < 2); + return index == 0 + ? QCoreApplication::translate("TSinStrokeStyle", "Frequency") + : QCoreApplication::translate("TZigzTSinStrokeStyleagStrokeStyle", + "Thickness"); } //----------------------------------------------------------------------------- -TColorStyle::ParamType TSinStrokeStyle::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +void TSinStrokeStyle::getParamRange(int index, double &min, double &max) const { + assert(0 <= index && index < 2); + if (index == 0) { + min = 1.0; + max = 20.0; + } else { + min = 0.0; + max = 1.0; + } } //----------------------------------------------------------------------------- -QString TSinStrokeStyle::getParamNames(int index) const -{ - assert(0 <= index && index < 2); - return index == 0 ? QCoreApplication::translate("TSinStrokeStyle", "Frequency") : QCoreApplication::translate("TZigzTSinStrokeStyleagStrokeStyle", "Thickness"); +double TSinStrokeStyle::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 2); + return index == 0 ? m_frequency : m_thick; } //----------------------------------------------------------------------------- -void TSinStrokeStyle::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 2); - if (index == 0) { - min = 1.0; - max = 20.0; - } else { - min = 0.0; - max = 1.0; - } +void TSinStrokeStyle::setParamValue(int index, double value) { + assert(0 <= index && index < 2); + if (index == 0) + m_frequency = value; + else + m_thick = value; + + updateVersionNumber(); } //----------------------------------------------------------------------------- -double TSinStrokeStyle::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 2); - return index == 0 ? m_frequency : m_thick; +void TSinStrokeStyle::computeData(Points &positions, const TStroke *stroke, + const TColorFunction *cf) const { + double length = stroke->getLength(); + double step = 5.0; + + positions.clear(); + positions.reserve(tceil((length + 1) / step)); + + double frequency = m_frequency / 100; + ; + double s = 0; + // bool firstRing = true; + double thick = 1 - m_thick; + while (s <= length) { + double w = stroke->getParameterAtLength(s); + // if(w<0) {s+=0.1; continue;} // per tamponare il baco della + // getParameterAtLength() + TThickPoint pos = stroke->getThickPoint(w); + TPointD u = stroke->getSpeed(w); + double normu = norm2(u); + if (normu == 0) { + s += 0.1; + continue; + } // non dovrebbe succedere mai, ma per prudenza.... + u = normalize(u); + TPointD v = rotate90(u); + double sinvalue = sin(frequency * s); + positions.push_back(pos + v * pos.thick * sinvalue); + positions.push_back(pos + v * thick * pos.thick * sinvalue); + s += step; + } } //----------------------------------------------------------------------------- -void TSinStrokeStyle::setParamValue(int index, double value) -{ - assert(0 <= index && index < 2); - if (index == 0) - m_frequency = value; - else - m_thick = value; +void TSinStrokeStyle::drawStroke(const TColorFunction *cf, + std::vector &positions, + const TStroke *stroke) const { + TPixel32 color; + if (cf) + color = (*(cf))(m_color); + else + color = m_color; + tglColor(color); - updateVersionNumber(); + glBegin(GL_QUAD_STRIP); + int i = 0; + for (; i < (int)positions.size(); i += 2) { + tglVertex(positions[i]); + tglVertex(positions[i + 1]); + } + glEnd(); + glBegin(GL_LINE_STRIP); + for (i = 0; i < (int)positions.size(); i += 2) { + tglVertex(positions[i]); + } + glEnd(); + glBegin(GL_LINE_STRIP); + for (i = 1; i < (int)positions.size() - 1; i += 2) { + tglVertex(positions[i]); + } + glEnd(); } //----------------------------------------------------------------------------- -void TSinStrokeStyle::computeData(Points &positions, - const TStroke *stroke, - const TColorFunction *cf) const -{ - double length = stroke->getLength(); - double step = 5.0; - - positions.clear(); - positions.reserve(tceil((length + 1) / step)); - - double frequency = m_frequency / 100; - ; - double s = 0; - //bool firstRing = true; - double thick = 1 - m_thick; - while (s <= length) { - double w = stroke->getParameterAtLength(s); - //if(w<0) {s+=0.1; continue;} // per tamponare il baco della getParameterAtLength() - TThickPoint pos = stroke->getThickPoint(w); - TPointD u = stroke->getSpeed(w); - double normu = norm2(u); - if (normu == 0) { - s += 0.1; - continue; - } // non dovrebbe succedere mai, ma per prudenza.... - u = normalize(u); - TPointD v = rotate90(u); - double sinvalue = sin(frequency * s); - positions.push_back(pos + v * pos.thick * sinvalue); - positions.push_back(pos + v * thick * pos.thick * sinvalue); - s += step; - } -} - -//----------------------------------------------------------------------------- - -void TSinStrokeStyle::drawStroke(const TColorFunction *cf, std::vector &positions, - const TStroke *stroke) const -{ - TPixel32 color; - if (cf) - color = (*(cf))(m_color); - else - color = m_color; - tglColor(color); - - glBegin(GL_QUAD_STRIP); - int i = 0; - for (; i < (int)positions.size(); i += 2) { - tglVertex(positions[i]); - tglVertex(positions[i + 1]); - } - glEnd(); - glBegin(GL_LINE_STRIP); - for (i = 0; i < (int)positions.size(); i += 2) { - tglVertex(positions[i]); - } - glEnd(); - glBegin(GL_LINE_STRIP); - for (i = 1; i < (int)positions.size() - 1; i += 2) { - tglVertex(positions[i]); - } - glEnd(); -} - -//----------------------------------------------------------------------------- - -void TSinStrokeStyle::drawStroke(TFlash &flash, const TStroke *stroke) const -{ +void TSinStrokeStyle::drawStroke(TFlash &flash, const TStroke *stroke) const { + double length = stroke->getLength(); + double step = 5.0; + + double frequency = m_frequency / 100; + ; + vector points; + + double s = 0; + // bool firstRing = true; + double thick = 1 - m_thick; + while (s <= length) { + double w = stroke->getParameterAtLength(s); + // if(w<0) {s+=0.1; continue;} // per tamponare il baco della + // getParameterAtLength() + TThickPoint pos = stroke->getThickPoint(w); + TPointD u = stroke->getSpeed(w); + double normu = norm2(u); + if (normu == 0) { + s += 0.1; + continue; + } // non dovrebbe succedere mai, ma per prudenza.... + u = normalize(u); + TPointD v = rotate90(u); + double sinvalue = sin(frequency * s); + points.push_back(pos + v * pos.thick * sinvalue); + points.push_back(pos + v * thick * pos.thick * sinvalue); + s += step; + } - double length = stroke->getLength(); - double step = 5.0; - - double frequency = m_frequency / 100; - ; - vector points; - - double s = 0; - //bool firstRing = true; - double thick = 1 - m_thick; - while (s <= length) { - double w = stroke->getParameterAtLength(s); - //if(w<0) {s+=0.1; continue;} // per tamponare il baco della getParameterAtLength() - TThickPoint pos = stroke->getThickPoint(w); - TPointD u = stroke->getSpeed(w); - double normu = norm2(u); - if (normu == 0) { - s += 0.1; - continue; - } // non dovrebbe succedere mai, ma per prudenza.... - u = normalize(u); - TPointD v = rotate90(u); - double sinvalue = sin(frequency * s); - points.push_back(pos + v * pos.thick * sinvalue); - points.push_back(pos + v * thick * pos.thick * sinvalue); - s += step; - } - - // Polyline version - flash.setThickness(0.0); - flash.setFillColor(m_color); - for (int i = 0; i < ((int)points.size() - 2); i += 2) { - vector plv; - plv.push_back(points[i]); - plv.push_back(points[i + 1]); - plv.push_back(points[i + 3]); - plv.push_back(points[i + 2]); - flash.drawPolyline(plv); - } - - // Quadratic version - /* flash.setThickness(m_thick); - vector pp; - for( int i=0; i<(int)(points.size()-1); i+=2 ) - pp.push_back(TPointD((points[i]+points[i+1])*0.5)); - - if ( pp.size()<=2 ) { - if ( pp.size()==2 ) { - vector sv; - sv.push_back(TSegment(pp[0],pp[1])); - flash.setLineColor(m_color); - flash.drawSegments(sv,false); - } - return; - } - - vector qv; - qv.push_back(TQuadratic(pp[i],pp[i]*0.75+pp[i+1]*0.25,(pp[i]+pp[i+1])*0.5)); - for( i=1; i<(int)(pp.size()-1); i++ ) { - TPointD p0=((pp[i-1]+pp[i])*0.5); - TPointD p1=pp[i]; - TPointD p2=((pp[i]+pp[i+1])*0.5); - qv.push_back(TQuadratic(p0,p1,p2)); - } - int n=pp.size()-1; - qv.push_back(TQuadratic((pp[n-1]+pp[n])*0.5,pp[n-1]*0.25+pp[n]*0.75,pp[n])); + // Polyline version + flash.setThickness(0.0); + flash.setFillColor(m_color); + for (int i = 0; i < ((int)points.size() - 2); i += 2) { + vector plv; + plv.push_back(points[i]); + plv.push_back(points[i + 1]); + plv.push_back(points[i + 3]); + plv.push_back(points[i + 2]); + flash.drawPolyline(plv); + } - flash.setLineColor(m_color); - flash.setThickness(m_thick); - flash.drawquads(qv); + // Quadratic version + /* flash.setThickness(m_thick); +vector pp; +for( int i=0; i<(int)(points.size()-1); i+=2 ) + pp.push_back(TPointD((points[i]+points[i+1])*0.5)); + +if ( pp.size()<=2 ) { + if ( pp.size()==2 ) { + vector sv; + sv.push_back(TSegment(pp[0],pp[1])); + flash.setLineColor(m_color); + flash.drawSegments(sv,false); + } + return; +} + +vector qv; +qv.push_back(TQuadratic(pp[i],pp[i]*0.75+pp[i+1]*0.25,(pp[i]+pp[i+1])*0.5)); +for( i=1; i<(int)(pp.size()-1); i++ ) { + TPointD p0=((pp[i-1]+pp[i])*0.5); + TPointD p1=pp[i]; + TPointD p2=((pp[i]+pp[i+1])*0.5); + qv.push_back(TQuadratic(p0,p1,p2)); +} +int n=pp.size()-1; +qv.push_back(TQuadratic((pp[n-1]+pp[n])*0.5,pp[n-1]*0.25+pp[n]*0.75,pp[n])); + +flash.setLineColor(m_color); +flash.setThickness(m_thick); +flash.drawquads(qv); */ } //============================================================================= TFriezeStrokeStyle2::TFriezeStrokeStyle2() - : m_color(TPixel32::Black), m_parameter(0.7), m_thick(0.3) -{ + : m_color(TPixel32::Black), m_parameter(0.7), m_thick(0.3) {} + +//----------------------------------------------------------------------------- + +TColorStyle *TFriezeStrokeStyle2::clone() const { + return new TFriezeStrokeStyle2(*this); } //----------------------------------------------------------------------------- -TColorStyle *TFriezeStrokeStyle2::clone() const -{ - return new TFriezeStrokeStyle2(*this); +int TFriezeStrokeStyle2::getParamCount() const { return 2; } + +//----------------------------------------------------------------------------- + +TColorStyle::ParamType TFriezeStrokeStyle2::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -int TFriezeStrokeStyle2::getParamCount() const -{ - return 2; +QString TFriezeStrokeStyle2::getParamNames(int index) const { + assert(0 <= index && index < 2); + if (index == 0) + return QCoreApplication::translate("TFriezeStrokeStyle2", "Twirl"); + else + return QCoreApplication::translate("TFriezeStrokeStyle2", "Thickness"); } //----------------------------------------------------------------------------- -TColorStyle::ParamType TFriezeStrokeStyle2::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +void TFriezeStrokeStyle2::getParamRange(int index, double &min, + double &max) const { + assert(0 <= index && index < 2); + if (index == 0) { + min = -1.0; + max = 1.0; + } else { + min = 0.0; + max = 1.0; + } } //----------------------------------------------------------------------------- -QString TFriezeStrokeStyle2::getParamNames(int index) const -{ - assert(0 <= index && index < 2); - if (index == 0) - return QCoreApplication::translate("TFriezeStrokeStyle2", "Twirl"); - else - return QCoreApplication::translate("TFriezeStrokeStyle2", "Thickness"); +double TFriezeStrokeStyle2::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 2); + if (index == 0) + return m_parameter; + else + return m_thick; } //----------------------------------------------------------------------------- -void TFriezeStrokeStyle2::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 2); - if (index == 0) { - min = -1.0; - max = 1.0; - } else { - min = 0.0; - max = 1.0; - } +void TFriezeStrokeStyle2::setParamValue(int index, double value) { + assert(0 <= index && index < 2); + if (index == 0) + m_parameter = value; + else + m_thick = value; + + updateVersionNumber(); } //----------------------------------------------------------------------------- -double TFriezeStrokeStyle2::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 2); - if (index == 0) - return m_parameter; - else - return m_thick; +void TFriezeStrokeStyle2::loadData(int ids, TInputStreamInterface &is) { + if (ids != 102) + throw TException("Frieze stroke style: unknown obsolete format"); + m_thick = 0.0; + is >> m_color >> m_parameter; } //----------------------------------------------------------------------------- -void TFriezeStrokeStyle2::setParamValue(int index, double value) -{ - assert(0 <= index && index < 2); - if (index == 0) - m_parameter = value; - else - m_thick = value; +void TFriezeStrokeStyle2::computeData(Points &positions, const TStroke *stroke, + const TColorFunction *cf) const { + // TStroke *stroke = getStroke(); + double length = stroke->getLength(); + + double ds = 0.5; + + positions.clear(); + positions.reserve(tceil((length + 1) / ds)); - updateVersionNumber(); + double s = 0.01; + double lastS = 0; + double phi = 0; + double lastW = 0; + double thick = 1 - m_thick; + vector points; + while (s <= length) { + double w = stroke->getParameterAtLength(s); + if (w < lastW) { + s += 0.1; + continue; + } + lastW = w; + TThickPoint pos = stroke->getThickPoint(w); + TPointD u = normalize(stroke->getSpeed(w)); + TPointD v = rotate90(u); + + double thickness = pos.thick; // 5; //(1-t)*40 + t * 10; + + if (thickness > 0) { + double omega = M_PI / thickness; + + double q = 0.5 * (1 - cos(phi)); + double theta = M_PI_2 - M_PI * m_parameter * q; + double r = thickness * sin(phi); + double r1 = r * thick; + double costheta = cos(theta); + double sintheta = sin(theta); + positions.push_back(pos + u * (r * costheta) + v * (r * sintheta)); + positions.push_back(pos + u * (r1 * costheta) + v * (r1 * sintheta)); + phi += (s - lastS) * omega; + lastS = s; + } else { + positions.push_back(pos); + positions.push_back(pos); + } + + s += ds; + } } //----------------------------------------------------------------------------- -void TFriezeStrokeStyle2::loadData(int ids, TInputStreamInterface &is) -{ - if (ids != 102) - throw TException("Frieze stroke style: unknown obsolete format"); - m_thick = 0.0; - is >> m_color >> m_parameter; +void TFriezeStrokeStyle2::drawStroke(const TColorFunction *cf, + Points &positions, + const TStroke *stroke) const { + TPixel32 color; + if (cf) + color = (*(cf))(m_color); + else + color = m_color; + tglColor(color); + + glBegin(GL_QUAD_STRIP); + int i = 0; + for (; i < (int)positions.size(); i += 2) { + tglVertex(positions[i]); + tglVertex(positions[i + 1]); + } + glEnd(); + glBegin(GL_LINE_STRIP); + for (i = 0; i < (int)positions.size(); i += 2) { + tglVertex(positions[i]); + } + glEnd(); + glBegin(GL_LINE_STRIP); + for (i = 1; i < (int)positions.size() - 1; i += 2) { + tglVertex(positions[i]); + } + glEnd(); } //----------------------------------------------------------------------------- -void TFriezeStrokeStyle2::computeData(Points &positions, - const TStroke *stroke, - const TColorFunction *cf) const -{ - using TConsts::pi; - //TStroke *stroke = getStroke(); - double length = stroke->getLength(); - - double ds = 0.5; - - positions.clear(); - positions.reserve(tceil((length + 1) / ds)); - - double s = 0.01; - double lastS = 0; - double phi = 0; - double lastW = 0; - double thick = 1 - m_thick; - vector points; - while (s <= length) { - double w = stroke->getParameterAtLength(s); - if (w < lastW) { - s += 0.1; - continue; - } - lastW = w; - TThickPoint pos = stroke->getThickPoint(w); - TPointD u = normalize(stroke->getSpeed(w)); - TPointD v = rotate90(u); - - double thickness = pos.thick; // 5; //(1-t)*40 + t * 10; - - if (thickness > 0) { - double omega = pi * 2 / (thickness * 2); - - double q = 0.5 * (1 - cos(phi)); - double theta = pi * 0.5 - pi * m_parameter * q; - double r = thickness * sin(phi); - double r1 = r * thick; - double costheta = cos(theta); - double sintheta = sin(theta); - positions.push_back(pos + u * (r * costheta) + v * (r * sintheta)); - positions.push_back(pos + u * (r1 * costheta) + v * (r1 * sintheta)); - phi += (s - lastS) * omega; - lastS = s; - } else { - positions.push_back(pos); - positions.push_back(pos); - } - - s += ds; - } -} - -//----------------------------------------------------------------------------- - -void TFriezeStrokeStyle2::drawStroke(const TColorFunction *cf, Points &positions, - const TStroke *stroke) const -{ - TPixel32 color; - if (cf) - color = (*(cf))(m_color); - else - color = m_color; - tglColor(color); - - glBegin(GL_QUAD_STRIP); - int i = 0; - for (; i < (int)positions.size(); i += 2) { - tglVertex(positions[i]); - tglVertex(positions[i + 1]); - } - glEnd(); - glBegin(GL_LINE_STRIP); - for (i = 0; i < (int)positions.size(); i += 2) { - tglVertex(positions[i]); - } - glEnd(); - glBegin(GL_LINE_STRIP); - for (i = 1; i < (int)positions.size() - 1; i += 2) { - tglVertex(positions[i]); - } - glEnd(); -} - -//----------------------------------------------------------------------------- - -void TFriezeStrokeStyle2::drawStroke(TFlash &flash, const TStroke *stroke) const -{ - using TConsts::pi; - //TStroke *stroke = getStroke(); - double length = stroke->getLength(); - - double s = 0.01; - double lastS = 0; - double phi = 0; - double lastW = 0; - double thick = 1 - m_thick; - vector points; - while (s <= length) { - double w = stroke->getParameterAtLength(s); - if (w < lastW) { - s += 0.1; - continue; - } - lastW = w; - TThickPoint pos = stroke->getThickPoint(w); - TPointD u = normalize(stroke->getSpeed(w)); - TPointD v = rotate90(u); - - double thickness = pos.thick; // 5; //(1-t)*40 + t * 10; - - if (thickness > 0) { - double omega = pi * 2 / (thickness * 2); - - double q = 0.5 * (1 - cos(phi)); - double theta = pi * 0.5 - pi * m_parameter * q; - double r = thickness * sin(phi); - double r1 = r * thick; - double costheta = cos(theta); - double sintheta = sin(theta); - points.push_back(pos + u * (r * costheta) + v * (r * sintheta)); - points.push_back(pos + u * (r1 * costheta) + v * (r1 * sintheta)); - phi += (s - lastS) * omega; - lastS = s; - } else { - points.push_back(pos); - points.push_back(pos); - } - - double ds = 0.5; - s += ds; - } - - // Polyline version - flash.setThickness(0.0); - flash.setFillColor(m_color); - for (int i = 0; i < ((int)points.size() - 2); i += 2) { - vector plv; - plv.push_back(points[i]); - plv.push_back(points[i + 1]); - plv.push_back(points[i + 3]); - plv.push_back(points[i + 2]); - flash.drawPolyline(plv); - } - - /* - vector pp; - for( int i=0; i<((int)points.size()-1); i+=2 ) - pp.push_back(TPointD((points[i]+points[i+1])*0.5)); +void TFriezeStrokeStyle2::drawStroke(TFlash &flash, + const TStroke *stroke) const { + // TStroke *stroke = getStroke(); + double length = stroke->getLength(); + + double s = 0.01; + double lastS = 0; + double phi = 0; + double lastW = 0; + double thick = 1 - m_thick; + vector points; + while (s <= length) { + double w = stroke->getParameterAtLength(s); + if (w < lastW) { + s += 0.1; + continue; + } + lastW = w; + TThickPoint pos = stroke->getThickPoint(w); + TPointD u = normalize(stroke->getSpeed(w)); + TPointD v = rotate90(u); + + double thickness = pos.thick; // 5; //(1-t)*40 + t * 10; + + if (thickness > 0) { + double omega = M_PI / thickness; + + double q = 0.5 * (1 - cos(phi)); + double theta = M_PI_2 - M_PI * m_parameter * q; + double r = thickness * sin(phi); + double r1 = r * thick; + double costheta = cos(theta); + double sintheta = sin(theta); + points.push_back(pos + u * (r * costheta) + v * (r * sintheta)); + points.push_back(pos + u * (r1 * costheta) + v * (r1 * sintheta)); + phi += (s - lastS) * omega; + lastS = s; + } else { + points.push_back(pos); + points.push_back(pos); + } + + double ds = 0.5; + s += ds; + } + + // Polyline version + flash.setThickness(0.0); + flash.setFillColor(m_color); + for (int i = 0; i < ((int)points.size() - 2); i += 2) { + vector plv; + plv.push_back(points[i]); + plv.push_back(points[i + 1]); + plv.push_back(points[i + 3]); + plv.push_back(points[i + 2]); + flash.drawPolyline(plv); + } + + /* +vector pp; +for( int i=0; i<((int)points.size()-1); i+=2 ) + pp.push_back(TPointD((points[i]+points[i+1])*0.5)); // Quadratic version - if ( pp.size()<=2 ) { - if ( pp.size()==2 ) { - vector sv; - sv.push_back(TSegment(pp[0],pp[1])); - flash.setLineColor(m_color); - flash.drawSegments(sv,false); - } - return; - } - - vector qv; - qv.push_back(TQuadratic(pp[i],pp[i]*0.75+pp[i+1]*0.25,(pp[i]+pp[i+1])*0.5)); - for( i=1; i<(int)(pp.size()-1); i++ ) { - TPointD p0=((pp[i-1]+pp[i])*0.5); - TPointD p1=pp[i]; - TPointD p2=((pp[i]+pp[i+1])*0.5); - qv.push_back(TQuadratic(p0,p1,p2)); - } - int n=pp.size()-1; - qv.push_back(TQuadratic((pp[n-1]+pp[n])*0.5,pp[n-1]*0.25+pp[n]*0.75,pp[n])); +if ( pp.size()<=2 ) { + if ( pp.size()==2 ) { + vector sv; + sv.push_back(TSegment(pp[0],pp[1])); + flash.setLineColor(m_color); + flash.drawSegments(sv,false); + } + return; +} - flash.setLineColor(m_color); - flash.setThickness(m_thick); - flash.drawquads(qv); +vector qv; +qv.push_back(TQuadratic(pp[i],pp[i]*0.75+pp[i+1]*0.25,(pp[i]+pp[i+1])*0.5)); +for( i=1; i<(int)(pp.size()-1); i++ ) { + TPointD p0=((pp[i-1]+pp[i])*0.5); + TPointD p1=pp[i]; + TPointD p2=((pp[i]+pp[i+1])*0.5); + qv.push_back(TQuadratic(p0,p1,p2)); +} +int n=pp.size()-1; +qv.push_back(TQuadratic((pp[n-1]+pp[n])*0.5,pp[n-1]*0.25+pp[n]*0.75,pp[n])); + +flash.setLineColor(m_color); +flash.setThickness(m_thick); +flash.drawquads(qv); */ - // Segment version - /* - flash.setThickness(m_thick); - flash.setLineColor(m_color); - for( i=0; i<(int)(pp.size()-1); i++ ) { - vector sv; - sv.push_back(TSegment(pp[i],pp[i+1])); - flash.drawSegments(sv,false); - } + // Segment version + /* +flash.setThickness(m_thick); +flash.setLineColor(m_color); + for( i=0; i<(int)(pp.size()-1); i++ ) { + vector sv; + sv.push_back(TSegment(pp[i],pp[i+1])); + flash.drawSegments(sv,false); + } */ } //============================================================================= -TDualColorStrokeStyle2::TDualColorStrokeStyle2( - TPixel32 color0, TPixel32 color1, double parameter) - : m_color0(color0), m_color1(color1), m_parameter(parameter) -{ -} +TDualColorStrokeStyle2::TDualColorStrokeStyle2(TPixel32 color0, TPixel32 color1, + double parameter) + : m_color0(color0), m_color1(color1), m_parameter(parameter) {} //----------------------------------------------------------------------------- -TColorStyle *TDualColorStrokeStyle2::clone() const -{ - return new TDualColorStrokeStyle2(*this); +TColorStyle *TDualColorStrokeStyle2::clone() const { + return new TDualColorStrokeStyle2(*this); } //----------------------------------------------------------------------------- -void TDualColorStrokeStyle2::computeOutline(const TStroke *stroke, - TStrokeOutline &outline, - TOutlineUtil::OutlineParameter param) const -{ - param.m_lengthStep = m_parameter; - TOutlineStyle::computeOutline(stroke, outline, param); +void TDualColorStrokeStyle2::computeOutline( + const TStroke *stroke, TStrokeOutline &outline, + TOutlineUtil::OutlineParameter param) const { + param.m_lengthStep = m_parameter; + TOutlineStyle::computeOutline(stroke, outline, param); } //----------------------------------------------------------------------------- -void TDualColorStrokeStyle2::drawStroke(const TColorFunction *cf, TStrokeOutline *outline, - const TStroke *stroke) const -{ - UINT i; - const std::vector &v = outline->getArray(); - TPixel32 colorv[2]; - - if (cf) { - colorv[0] = (*(cf))(m_color0); - colorv[1] = (*(cf))(m_color1); - } else { - colorv[0] = m_color0; - colorv[1] = m_color1; - } - int colorindex = 0; - if (v.empty()) - return; - glBegin(GL_LINE_STRIP); - tglColor(colorv[0]); - for (i = 0; i < v.size(); i += 2) { - glVertex2dv(&v[i].x); - if (0 != v[i].stepCount) { - colorindex++; - tglColor(colorv[colorindex & 1]); - glVertex2dv(&v[i].x); - } - } - glEnd(); - - colorindex = 0; - glBegin(GL_LINE_STRIP); - tglColor(colorv[0]); - for (i = 1; i < v.size(); i += 2) { - glVertex2dv(&v[i].x); - if (0 != v[i].stepCount) { - colorindex++; - tglColor(colorv[colorindex & 1]); - glVertex2dv(&v[i].x); - } - } - glEnd(); - - colorindex = 0; - glBegin(GL_QUAD_STRIP); - tglColor(colorv[0]); - for (i = 0; i < v.size(); i += 2) { - glVertex2dv(&v[i].x); - glVertex2dv(&v[i + 1].x); - if (0 != v[i].stepCount) { - colorindex++; - tglColor(colorv[colorindex & 1]); - glVertex2dv(&v[i].x); - glVertex2dv(&v[i + 1].x); - } - } - glEnd(); - - //antialias delle linee normali - tglColor(colorv[0]); - for (i = 0; i < v.size(); i += 2) { - if (0 != v[i].stepCount) { - glBegin(GL_LINES); - glVertex2dv(&v[i].x); - glVertex2dv(&v[i + 1].x); - glEnd(); - } - } -} - -//----------------------------------------------------------------------------- - -void TDualColorStrokeStyle2::drawStroke(TFlash &flash, const TStroke *stroke) const -{ +void TDualColorStrokeStyle2::drawStroke(const TColorFunction *cf, + TStrokeOutline *outline, + const TStroke *stroke) const { + UINT i; + const std::vector &v = outline->getArray(); + TPixel32 colorv[2]; - TOutlineUtil::OutlineParameter param; - param.m_lengthStep = m_parameter; - TStrokeOutline outline; - TOutlineStyle::computeOutline(stroke, outline, param); - const std::vector &v = outline.getArray(); - if (v.empty()) - return; - - TPixel32 colorv[2] = {m_color0, m_color1}; - int colorindex = 0; - flash.setThickness(0.0); - flash.setFillColor(TPixel32(0, 0, 0, 255)); - for (UINT i = 0; i < (v.size() - 2); i += 2) { - vector tpv; - tpv.push_back(TPointD(v[i].x, v[i].y)); - tpv.push_back(TPointD(v[i + 1].x, v[i + 1].y)); - tpv.push_back(TPointD(v[i + 3].x, v[i + 3].y)); - tpv.push_back(TPointD(v[i + 2].x, v[i + 2].y)); - - if (0 != v[i].stepCount) { - colorindex++; - flash.setFillColor(colorv[colorindex & 1]); - } - flash.drawPolyline(tpv); - - /* --- testing --- - vector s; - s.push_back(TSegment(tpv[0],tpv[1])); - s.push_back(TSegment(tpv[1],tpv[2])); - s.push_back(TSegment(tpv[2],tpv[3])); - s.push_back(TSegment(tpv[3],tpv[0])); - flash.drawSegments(s,false); -*/ - } + if (cf) { + colorv[0] = (*(cf))(m_color0); + colorv[1] = (*(cf))(m_color1); + } else { + colorv[0] = m_color0; + colorv[1] = m_color1; + } + int colorindex = 0; + if (v.empty()) return; + glBegin(GL_LINE_STRIP); + tglColor(colorv[0]); + for (i = 0; i < v.size(); i += 2) { + glVertex2dv(&v[i].x); + if (0 != v[i].stepCount) { + colorindex++; + tglColor(colorv[colorindex & 1]); + glVertex2dv(&v[i].x); + } + } + glEnd(); + + colorindex = 0; + glBegin(GL_LINE_STRIP); + tglColor(colorv[0]); + for (i = 1; i < v.size(); i += 2) { + glVertex2dv(&v[i].x); + if (0 != v[i].stepCount) { + colorindex++; + tglColor(colorv[colorindex & 1]); + glVertex2dv(&v[i].x); + } + } + glEnd(); + + colorindex = 0; + glBegin(GL_QUAD_STRIP); + tglColor(colorv[0]); + for (i = 0; i < v.size(); i += 2) { + glVertex2dv(&v[i].x); + glVertex2dv(&v[i + 1].x); + if (0 != v[i].stepCount) { + colorindex++; + tglColor(colorv[colorindex & 1]); + glVertex2dv(&v[i].x); + glVertex2dv(&v[i + 1].x); + } + } + glEnd(); + + // antialias delle linee normali + tglColor(colorv[0]); + for (i = 0; i < v.size(); i += 2) { + if (0 != v[i].stepCount) { + glBegin(GL_LINES); + glVertex2dv(&v[i].x); + glVertex2dv(&v[i + 1].x); + glEnd(); + } + } } //----------------------------------------------------------------------------- -int TDualColorStrokeStyle2::getParamCount() const -{ - return 1; +void TDualColorStrokeStyle2::drawStroke(TFlash &flash, + const TStroke *stroke) const { + TOutlineUtil::OutlineParameter param; + param.m_lengthStep = m_parameter; + TStrokeOutline outline; + TOutlineStyle::computeOutline(stroke, outline, param); + const std::vector &v = outline.getArray(); + if (v.empty()) return; + + TPixel32 colorv[2] = {m_color0, m_color1}; + int colorindex = 0; + flash.setThickness(0.0); + flash.setFillColor(TPixel32(0, 0, 0, 255)); + for (UINT i = 0; i < (v.size() - 2); i += 2) { + vector tpv; + tpv.push_back(TPointD(v[i].x, v[i].y)); + tpv.push_back(TPointD(v[i + 1].x, v[i + 1].y)); + tpv.push_back(TPointD(v[i + 3].x, v[i + 3].y)); + tpv.push_back(TPointD(v[i + 2].x, v[i + 2].y)); + + if (0 != v[i].stepCount) { + colorindex++; + flash.setFillColor(colorv[colorindex & 1]); + } + flash.drawPolyline(tpv); + + /* --- testing --- +vector s; +s.push_back(TSegment(tpv[0],tpv[1])); +s.push_back(TSegment(tpv[1],tpv[2])); +s.push_back(TSegment(tpv[2],tpv[3])); +s.push_back(TSegment(tpv[3],tpv[0])); +flash.drawSegments(s,false); +*/ + } } //----------------------------------------------------------------------------- -TColorStyle::ParamType TDualColorStrokeStyle2::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +int TDualColorStrokeStyle2::getParamCount() const { return 1; } + +//----------------------------------------------------------------------------- + +TColorStyle::ParamType TDualColorStrokeStyle2::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -QString TDualColorStrokeStyle2::getParamNames(int index) const -{ - assert(0 <= index && index < 1); +QString TDualColorStrokeStyle2::getParamNames(int index) const { + assert(0 <= index && index < 1); - return QCoreApplication::translate("TDualColorStrokeStyle2", "Distance"); + return QCoreApplication::translate("TDualColorStrokeStyle2", "Distance"); } //----------------------------------------------------------------------------- -void TDualColorStrokeStyle2::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 1); - min = 1.0; - max = 100.0; +void TDualColorStrokeStyle2::getParamRange(int index, double &min, + double &max) const { + assert(0 <= index && index < 1); + min = 1.0; + max = 100.0; } //----------------------------------------------------------------------------- -double TDualColorStrokeStyle2::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 1); - return m_parameter; +double TDualColorStrokeStyle2::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 1); + return m_parameter; } //----------------------------------------------------------------------------- -void TDualColorStrokeStyle2::setParamValue(int index, double value) -{ - assert(0 <= index && index < 1); - m_parameter = value; - updateVersionNumber(); //questo si chiama per ogno cambiamento di parametro per cui di deve ricalcolare l'outline +void TDualColorStrokeStyle2::setParamValue(int index, double value) { + assert(0 <= index && index < 1); + m_parameter = value; + updateVersionNumber(); // questo si chiama per ogno cambiamento di parametro + // per cui di deve ricalcolare l'outline } //============================================================================= -TLongBlendStrokeStyle2::TLongBlendStrokeStyle2( - TPixel32 color0, TPixel32 color1, double parameter) - : m_color0(color0), m_color1(color1), m_parameter(parameter) -{ +TLongBlendStrokeStyle2::TLongBlendStrokeStyle2(TPixel32 color0, TPixel32 color1, + double parameter) + : m_color0(color0), m_color1(color1), m_parameter(parameter) {} + +//----------------------------------------------------------------------------- + +TColorStyle *TLongBlendStrokeStyle2::clone() const { + return new TLongBlendStrokeStyle2(*this); } //----------------------------------------------------------------------------- -TColorStyle *TLongBlendStrokeStyle2::clone() const -{ - return new TLongBlendStrokeStyle2(*this); +void TLongBlendStrokeStyle2::computeOutline( + const TStroke *stroke, TStrokeOutline &outline, + TOutlineUtil::OutlineParameter param) const { + param.m_lengthStep = m_parameter; + TOutlineStyle::computeOutline(stroke, outline, param); } //----------------------------------------------------------------------------- -void TLongBlendStrokeStyle2::computeOutline(const TStroke *stroke, - TStrokeOutline &outline, - TOutlineUtil::OutlineParameter param) const -{ - param.m_lengthStep = m_parameter; - TOutlineStyle::computeOutline(stroke, outline, param); +void TLongBlendStrokeStyle2::drawStroke(const TColorFunction *cf, + TStrokeOutline *outline, + const TStroke *stroke) const { + TPixel32 color0, color1; + if (cf) { + color0 = (*(cf))(m_color0); + color1 = (*(cf))(m_color1); + } else { + color0 = m_color0; + color1 = m_color1; + } + UINT i; + + const std::vector &v = outline->getArray(); + if (v.empty()) return; + + // outline with antialiasing + glBegin(GL_LINE_STRIP); + int mystepCount = 0; + + double totallength = stroke->getLength(); + double ntick = totallength / m_parameter + 1; + tglColor(color0); + for (i = 0; i < v.size(); i += 2) { + if (0 != v[i].stepCount) { + tglColor(blend(color0, color1, (double)mystepCount / ntick)); + mystepCount++; + } + glVertex2dv(&v[i].x); + } + glEnd(); + + glBegin(GL_LINE_STRIP); + mystepCount = 0; + tglColor(color0); + for (i = 1; i < v.size(); i += 2) { + if (0 != v[i].stepCount) { + tglColor(blend(color0, color1, (double)mystepCount / ntick)); + mystepCount++; + } + glVertex2dv(&v[i].x); + } + glEnd(); + + glBegin(GL_QUAD_STRIP); + mystepCount = 0; + tglColor(color0); + for (i = 0; i < v.size(); i += 2) { + if (0 != v[i].stepCount) { + tglColor(blend(color0, color1, (double)mystepCount / ntick)); + mystepCount++; + } + glVertex2dv(&v[i].x); + glVertex2dv(&v[i + 1].x); + } + glEnd(); } //----------------------------------------------------------------------------- -void TLongBlendStrokeStyle2::drawStroke(const TColorFunction *cf, TStrokeOutline *outline, - const TStroke *stroke) const -{ - TPixel32 color0, color1; - if (cf) { - color0 = (*(cf))(m_color0); - color1 = (*(cf))(m_color1); - } else { - color0 = m_color0; - color1 = m_color1; - } - UINT i; - - const std::vector &v = outline->getArray(); - if (v.empty()) - return; - - // outline with antialiasing - glBegin(GL_LINE_STRIP); - int mystepCount = 0; - - double totallength = stroke->getLength(); - double ntick = totallength / m_parameter + 1; - tglColor(color0); - for (i = 0; i < v.size(); i += 2) { - if (0 != v[i].stepCount) { - tglColor(blend(color0, color1, (double)mystepCount / ntick)); - mystepCount++; - } - glVertex2dv(&v[i].x); - } - glEnd(); - - glBegin(GL_LINE_STRIP); - mystepCount = 0; - tglColor(color0); - for (i = 1; i < v.size(); i += 2) { - if (0 != v[i].stepCount) { - tglColor(blend(color0, color1, (double)mystepCount / ntick)); - mystepCount++; - } - glVertex2dv(&v[i].x); - } - glEnd(); - - glBegin(GL_QUAD_STRIP); - mystepCount = 0; - tglColor(color0); - for (i = 0; i < v.size(); i += 2) { - if (0 != v[i].stepCount) { - tglColor(blend(color0, color1, (double)mystepCount / ntick)); - mystepCount++; - } - glVertex2dv(&v[i].x); - glVertex2dv(&v[i + 1].x); - } - glEnd(); -} - -//----------------------------------------------------------------------------- - -void TLongBlendStrokeStyle2::drawStroke(TFlash &flash, const TStroke *stroke) const -{ - TPixel32 color0, color1; - color0 = m_color0; - color1 = m_color1; - - UINT i; - TOutlineUtil::OutlineParameter param; - double lParameter = m_parameter >= 20.0 || m_parameter < 0.0 ? 10.0 : m_parameter; - param.m_lengthStep = lParameter; - TStrokeOutline outline; - TOutlineStyle::computeOutline(stroke, outline, param); - const std::vector &v = outline.getArray(); - if (v.empty()) - return; - - flash.setThickness(0.0); - - int mystepCount = 0; - double totallength = stroke->getLength(); - double ntick = totallength / lParameter + 1; - SFlashUtils sfu; - TPixel32 col0, col1; - col0 = col1 = color0; - for (i = 2; i < v.size(); i += 2) { - if (0 != v[i].stepCount) { - col1 = blend(color0, color1, (double)mystepCount / ntick); - mystepCount++; - } - vector plv; - plv.push_back(TPointD(v[i - 2].x, v[i - 2].y)); - plv.push_back(TPointD(v[i - 1].x, v[i - 1].y)); - plv.push_back(TPointD(v[i + 1].x, v[i + 1].y)); - plv.push_back(TPointD(v[i].x, v[i].y)); - sfu.drawGradedPolyline(flash, plv, col0, col1); - col0 = col1; - } -} - -//----------------------------------------------------------------------------- - -int TLongBlendStrokeStyle2::getParamCount() const -{ - return 1; +void TLongBlendStrokeStyle2::drawStroke(TFlash &flash, + const TStroke *stroke) const { + TPixel32 color0, color1; + color0 = m_color0; + color1 = m_color1; + + UINT i; + TOutlineUtil::OutlineParameter param; + double lParameter = + m_parameter >= 20.0 || m_parameter < 0.0 ? 10.0 : m_parameter; + param.m_lengthStep = lParameter; + TStrokeOutline outline; + TOutlineStyle::computeOutline(stroke, outline, param); + const std::vector &v = outline.getArray(); + if (v.empty()) return; + + flash.setThickness(0.0); + + int mystepCount = 0; + double totallength = stroke->getLength(); + double ntick = totallength / lParameter + 1; + SFlashUtils sfu; + TPixel32 col0, col1; + col0 = col1 = color0; + for (i = 2; i < v.size(); i += 2) { + if (0 != v[i].stepCount) { + col1 = blend(color0, color1, (double)mystepCount / ntick); + mystepCount++; + } + vector plv; + plv.push_back(TPointD(v[i - 2].x, v[i - 2].y)); + plv.push_back(TPointD(v[i - 1].x, v[i - 1].y)); + plv.push_back(TPointD(v[i + 1].x, v[i + 1].y)); + plv.push_back(TPointD(v[i].x, v[i].y)); + sfu.drawGradedPolyline(flash, plv, col0, col1); + col0 = col1; + } } //----------------------------------------------------------------------------- -TColorStyle::ParamType TLongBlendStrokeStyle2::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +int TLongBlendStrokeStyle2::getParamCount() const { return 1; } + +//----------------------------------------------------------------------------- + +TColorStyle::ParamType TLongBlendStrokeStyle2::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -QString TLongBlendStrokeStyle2::getParamNames(int index) const -{ - assert(0 <= index && index < 1); +QString TLongBlendStrokeStyle2::getParamNames(int index) const { + assert(0 <= index && index < 1); - return "Distance"; //W_Watercolor_Distance + return "Distance"; // W_Watercolor_Distance } //----------------------------------------------------------------------------- -void TLongBlendStrokeStyle2::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 1); - min = 0.1; - max = 100.0; +void TLongBlendStrokeStyle2::getParamRange(int index, double &min, + double &max) const { + assert(0 <= index && index < 1); + min = 0.1; + max = 100.0; } //----------------------------------------------------------------------------- -double TLongBlendStrokeStyle2::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 1); - return m_parameter; +double TLongBlendStrokeStyle2::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 1); + return m_parameter; } //----------------------------------------------------------------------------- -void TLongBlendStrokeStyle2::setParamValue(int index, double value) -{ - assert(0 <= index && index < 1); - m_parameter = value; - updateVersionNumber(); //questo si chiama per ogno cambiamento di parametro per cui di deve ricalcolare l'outline +void TLongBlendStrokeStyle2::setParamValue(int index, double value) { + assert(0 <= index && index < 1); + m_parameter = value; + updateVersionNumber(); // questo si chiama per ogno cambiamento di parametro + // per cui di deve ricalcolare l'outline } //============================================================================= #ifdef _DEBUG -OutlineViewerStyle::OutlineViewerStyle( - TPixel32 color, double parameter0, double parameter1, - double parameter2, double parameter3) - : TSolidColorStyle(color), m_boolPar(false), m_intPar(1), m_enumPar(2), m_pathPar("testPath") -{ - m_parameter[0] = parameter0; - m_parameter[1] = parameter1; - m_parameter[2] = parameter2; - m_parameter[3] = parameter3; +OutlineViewerStyle::OutlineViewerStyle(TPixel32 color, double parameter0, + double parameter1, double parameter2, + double parameter3) + : TSolidColorStyle(color) + , m_boolPar(false) + , m_intPar(1) + , m_enumPar(2) + , m_pathPar("testPath") { + m_parameter[0] = parameter0; + m_parameter[1] = parameter1; + m_parameter[2] = parameter2; + m_parameter[3] = parameter3; } //----------------------------------------------------------------------------- -TColorStyle *OutlineViewerStyle::clone() const -{ - return new OutlineViewerStyle(*this); +TColorStyle *OutlineViewerStyle::clone() const { + return new OutlineViewerStyle(*this); } //----------------------------------------------------------------------------- -int OutlineViewerStyle::getParamCount() const -{ - return 8; -} +int OutlineViewerStyle::getParamCount() const { return 8; } //----------------------------------------------------------------------------- -TColorStyle::ParamType OutlineViewerStyle::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - static const TColorStyle::ParamType types[8] = - {TColorStyle::DOUBLE, TColorStyle::DOUBLE, TColorStyle::DOUBLE, TColorStyle::DOUBLE, - TColorStyle::BOOL, TColorStyle::INT, TColorStyle::ENUM, TColorStyle::FILEPATH}; +TColorStyle::ParamType OutlineViewerStyle::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + static const TColorStyle::ParamType types[8] = { + TColorStyle::DOUBLE, TColorStyle::DOUBLE, TColorStyle::DOUBLE, + TColorStyle::DOUBLE, TColorStyle::BOOL, TColorStyle::INT, + TColorStyle::ENUM, TColorStyle::FILEPATH}; - return types[index]; + return types[index]; } //----------------------------------------------------------------------------- -QString OutlineViewerStyle::getParamNames(int index) const -{ - assert(0 <= index && index < 8); - - switch (index) { - case 0: - return QCoreApplication::translate("OutlineViewerStyle", "Control Point"); - case 1: - return QCoreApplication::translate("OutlineViewerStyle", "Center Line"); - case 2: - return QCoreApplication::translate("OutlineViewerStyle", "Outline Mode"); - case 3: - return QCoreApplication::translate("OutlineViewerStyle", "Distance"); - case 4: - return "Bool"; - case 5: - return "Int"; - case 6: - return "Enum"; - case 7: - return "Path"; - } - - assert(0); - return QCoreApplication::translate("OutlineViewerStyle", "distance"); -} - -//----------------------------------------------------------------------------- - -void OutlineViewerStyle::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 4); - switch (index) { - case 0: min = 0.0; max = 2.99; break; - case 1: min = 0.0; max = 1.99; break; - case 2: min = 0.0; max = 3.99; break; - case 3: min = 3.0; max = 100.0; break; - } +QString OutlineViewerStyle::getParamNames(int index) const { + assert(0 <= index && index < 8); + + switch (index) { + case 0: + return QCoreApplication::translate("OutlineViewerStyle", "Control Point"); + case 1: + return QCoreApplication::translate("OutlineViewerStyle", "Center Line"); + case 2: + return QCoreApplication::translate("OutlineViewerStyle", "Outline Mode"); + case 3: + return QCoreApplication::translate("OutlineViewerStyle", "Distance"); + case 4: + return "Bool"; + case 5: + return "Int"; + case 6: + return "Enum"; + case 7: + return "Path"; + } + + assert(0); + return QCoreApplication::translate("OutlineViewerStyle", "distance"); +} + +//----------------------------------------------------------------------------- + +void OutlineViewerStyle::getParamRange(int index, double &min, + double &max) const { + assert(0 <= index && index < 4); + switch (index) { + case 0: + min = 0.0; + max = 2.99; + break; + case 1: + min = 0.0; + max = 1.99; + break; + case 2: + min = 0.0; + max = 3.99; + break; + case 3: + min = 3.0; + max = 100.0; + break; + } } //----------------------------------------------------------------------------- -void OutlineViewerStyle::getParamRange(int index, int &min, int &max) const -{ - assert(5 <= index && index < 7); - switch (index) { - case 5: min = 0, max = 10; break; - case 6: min = 0, max = 4; break; - } +void OutlineViewerStyle::getParamRange(int index, int &min, int &max) const { + assert(5 <= index && index < 7); + switch (index) { + case 5: + min = 0, max = 10; + break; + case 6: + min = 0, max = 4; + break; + } } //----------------------------------------------------------------------------- -void OutlineViewerStyle::getParamRange(int index, QStringList &enumItems) const -{ - enumItems << "Prova 1" - << "Prova 2" - << "Prova 3" - << "Prova 4"; +void OutlineViewerStyle::getParamRange(int index, + QStringList &enumItems) const { + enumItems << "Prova 1" + << "Prova 2" + << "Prova 3" + << "Prova 4"; } //----------------------------------------------------------------------------- -bool OutlineViewerStyle::getParamValue(TColorStyle::bool_tag, int index) const -{ - assert(index == 4); - return m_boolPar; +bool OutlineViewerStyle::getParamValue(TColorStyle::bool_tag, int index) const { + assert(index == 4); + return m_boolPar; } //----------------------------------------------------------------------------- -int OutlineViewerStyle::getParamValue(TColorStyle::int_tag, int index) const -{ - assert(5 <= index && index < 7); - return (index == 5) ? m_intPar : m_enumPar; +int OutlineViewerStyle::getParamValue(TColorStyle::int_tag, int index) const { + assert(5 <= index && index < 7); + return (index == 5) ? m_intPar : m_enumPar; } //----------------------------------------------------------------------------- -double OutlineViewerStyle::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 4); - return m_parameter[index]; +double OutlineViewerStyle::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 4); + return m_parameter[index]; } //----------------------------------------------------------------------------- -TFilePath OutlineViewerStyle::getParamValue(TColorStyle::TFilePath_tag, int index) const -{ - assert(index == 7); - return m_pathPar; +TFilePath OutlineViewerStyle::getParamValue(TColorStyle::TFilePath_tag, + int index) const { + assert(index == 7); + return m_pathPar; } //----------------------------------------------------------------------------- -void OutlineViewerStyle::setParamValue(int index, bool value) -{ - assert(index == 4); - m_boolPar = value; +void OutlineViewerStyle::setParamValue(int index, bool value) { + assert(index == 4); + m_boolPar = value; } //----------------------------------------------------------------------------- -void OutlineViewerStyle::setParamValue(int index, int value) -{ - assert(5 <= index && index < 7); - (index == 5) ? m_intPar = value : m_enumPar = value; +void OutlineViewerStyle::setParamValue(int index, int value) { + assert(5 <= index && index < 7); + (index == 5) ? m_intPar = value : m_enumPar = value; } //----------------------------------------------------------------------------- -void OutlineViewerStyle::setParamValue(int index, double value) -{ - assert(0 <= index && index < 4); +void OutlineViewerStyle::setParamValue(int index, double value) { + assert(0 <= index && index < 4); - if (index >= 2 && (int)m_parameter[index] != (int)value) //cambia l'outline - { - updateVersionNumber(); - } + if (index >= 2 && (int)m_parameter[index] != (int)value) // cambia l'outline + { + updateVersionNumber(); + } - m_parameter[index] = value; + m_parameter[index] = value; } //----------------------------------------------------------------------------- -void OutlineViewerStyle::setParamValue(int index, const TFilePath &value) -{ - assert(index == 7); - m_pathPar = value; +void OutlineViewerStyle::setParamValue(int index, const TFilePath &value) { + assert(index == 7); + m_pathPar = value; } //----------------------------------------------------------------------------- -void OutlineViewerStyle::loadData(TInputStreamInterface &is) -{ - TPixel32 color; - is >> color; - TSolidColorStyle::setMainColor(color); - is >> m_parameter[0]; - is >> m_parameter[1]; - is >> m_parameter[2]; - is >> m_parameter[3]; +void OutlineViewerStyle::loadData(TInputStreamInterface &is) { + TPixel32 color; + is >> color; + TSolidColorStyle::setMainColor(color); + is >> m_parameter[0]; + is >> m_parameter[1]; + is >> m_parameter[2]; + is >> m_parameter[3]; - int boolPar; - is >> boolPar; - m_boolPar = boolPar; - is >> m_intPar; - is >> m_enumPar; - std::string str; - is >> str; - m_pathPar = TFilePath(::to_wstring(str)); + int boolPar; + is >> boolPar; + m_boolPar = boolPar; + is >> m_intPar; + is >> m_enumPar; + std::string str; + is >> str; + m_pathPar = TFilePath(::to_wstring(str)); } //----------------------------------------------------------------------------- -void OutlineViewerStyle::saveData(TOutputStreamInterface &os) const -{ - os << TSolidColorStyle::getMainColor(); - os << m_parameter[0]; - os << m_parameter[1]; - os << m_parameter[2]; - os << m_parameter[3]; +void OutlineViewerStyle::saveData(TOutputStreamInterface &os) const { + os << TSolidColorStyle::getMainColor(); + os << m_parameter[0]; + os << m_parameter[1]; + os << m_parameter[2]; + os << m_parameter[3]; - os << int(m_boolPar); - os << m_intPar; - os << m_enumPar; - os << ::to_string(m_pathPar.getWideString()); + os << int(m_boolPar); + os << m_intPar; + os << m_enumPar; + os << ::to_string(m_pathPar.getWideString()); } //----------------------------------------------------------------------------- -void OutlineViewerStyle::computeOutline(const TStroke *stroke, - TStrokeOutline &outline, - TOutlineUtil::OutlineParameter param) const -{ - if (m_parameter[2] >= 1.0) { - param.m_lengthStep = (m_parameter[2] >= 3.0) ? m_parameter[3] : 0; +void OutlineViewerStyle::computeOutline( + const TStroke *stroke, TStrokeOutline &outline, + TOutlineUtil::OutlineParameter param) const { + if (m_parameter[2] >= 1.0) { + param.m_lengthStep = (m_parameter[2] >= 3.0) ? m_parameter[3] : 0; - TOutlineStyle::computeOutline(stroke, outline, param); - } + TOutlineStyle::computeOutline(stroke, outline, param); + } } //----------------------------------------------------------------------------- -namespace -{ +namespace { -void drawOutline(TStrokeOutline *outline, bool cut) -{ - const std::vector &v = outline->getArray(); +void drawOutline(TStrokeOutline *outline, bool cut) { + const std::vector &v = outline->getArray(); - if (v.empty()) - return; + if (v.empty()) return; - UINT i; - // outline with antialiasing - glBegin(GL_LINE_STRIP); - for (i = 0; i < v.size(); i += 2) - glVertex2dv(&v[i].x); - glEnd(); + UINT i; + // outline with antialiasing + glBegin(GL_LINE_STRIP); + for (i = 0; i < v.size(); i += 2) glVertex2dv(&v[i].x); + glEnd(); - glBegin(GL_LINE_STRIP); - for (i = 1; i < v.size(); i += 2) - glVertex2dv(&v[i].x); - glEnd(); + glBegin(GL_LINE_STRIP); + for (i = 1; i < v.size(); i += 2) glVertex2dv(&v[i].x); + glEnd(); - if (cut) { - static const int stride = sizeof(TOutlinePoint); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_DOUBLE, stride, &v[0]); - glDrawArrays(GL_LINES, 0, v.size()); - glDisableClientState(GL_VERTEX_ARRAY); - } + if (cut) { + static const int stride = sizeof(TOutlinePoint); + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_DOUBLE, stride, &v[0]); + glDrawArrays(GL_LINES, 0, v.size()); + glDisableClientState(GL_VERTEX_ARRAY); + } } -void drawControlPoints(const TStroke *stroke, bool allPoints) -{ - int i; - TPointD p; - glPointSize(4.0); - glBegin(GL_POINTS); - - if (allPoints) { - int n = stroke->getControlPointCount(); - for (i = 0; i < n; ++i) { - p = stroke->getControlPoint(i); - glColor3d((i + 1) & 1, i & 1, 0.0); - glVertex2d(p.x, p.y); - } - } else { - int n = stroke->getChunkCount(); - for (i = 0; i < n; ++i) { - const TThickQuadratic *chunk = stroke->getChunk(i); - p = chunk->getP0(); - glColor3d(1.0, 0.0, 0.0); - glVertex2d(p.x, p.y); - } - const TThickQuadratic *chunk = stroke->getChunk(n - 1); - glColor3d(1.0, 0.0, 0.0); - p = chunk->getP2(); - glVertex2d(p.x, p.y); - } - - glEnd(); -} - -void drawCenterline(const TStroke *stroke) -{ - glBegin(GL_LINE_STRIP); - int n = stroke->getChunkCount(); - int i = 0; - for (i = 0; i < n; ++i) { - const TThickQuadratic *chunk = stroke->getChunk(i); - double length = chunk->getLength(0, 1); - int maxCount = std::max(tceil(length / (5 * sqrt(tglGetPixelSize2()))), 1); - double deltaT = 1.0 / maxCount; - double t = 0; - for (t = 0; t < 1 + (deltaT / 2); t += deltaT) { - TPointD point = chunk->getPoint(t); - glVertex2d(point.x, point.y); - } - } - glEnd(); - return; +void drawControlPoints(const TStroke *stroke, bool allPoints) { + int i; + TPointD p; + glPointSize(4.0); + glBegin(GL_POINTS); + + if (allPoints) { + int n = stroke->getControlPointCount(); + for (i = 0; i < n; ++i) { + p = stroke->getControlPoint(i); + glColor3d((i + 1) & 1, i & 1, 0.0); + glVertex2d(p.x, p.y); + } + } else { + int n = stroke->getChunkCount(); + for (i = 0; i < n; ++i) { + const TThickQuadratic *chunk = stroke->getChunk(i); + p = chunk->getP0(); + glColor3d(1.0, 0.0, 0.0); + glVertex2d(p.x, p.y); + } + const TThickQuadratic *chunk = stroke->getChunk(n - 1); + glColor3d(1.0, 0.0, 0.0); + p = chunk->getP2(); + glVertex2d(p.x, p.y); + } + + glEnd(); +} + +void drawCenterline(const TStroke *stroke) { + glBegin(GL_LINE_STRIP); + int n = stroke->getChunkCount(); + int i = 0; + for (i = 0; i < n; ++i) { + const TThickQuadratic *chunk = stroke->getChunk(i); + double length = chunk->getLength(0, 1); + int maxCount = std::max(tceil(length / (5 * sqrt(tglGetPixelSize2()))), 1); + double deltaT = 1.0 / maxCount; + double t = 0; + for (t = 0; t < 1 + (deltaT / 2); t += deltaT) { + TPointD point = chunk->getPoint(t); + glVertex2d(point.x, point.y); + } + } + glEnd(); + return; } } //------------------------------------------------------------ -void OutlineViewerStyle::drawStroke(const TColorFunction *cf, TStrokeOutline *outline, const TStroke *stroke) const -{ - TPixel32 color; - if (cf) - color = (*(cf))(getMainColor()); - else - color = getMainColor(); +void OutlineViewerStyle::drawStroke(const TColorFunction *cf, + TStrokeOutline *outline, + const TStroke *stroke) const { + TPixel32 color; + if (cf) + color = (*(cf))(getMainColor()); + else + color = getMainColor(); - tglColor(color); + tglColor(color); - if (m_parameter[1] >= 1.0) - drawCenterline(stroke); + if (m_parameter[1] >= 1.0) drawCenterline(stroke); - if (m_parameter[2] >= 1.0) - drawOutline(outline, m_parameter[2] >= 2.0); + if (m_parameter[2] >= 1.0) drawOutline(outline, m_parameter[2] >= 2.0); - if (m_parameter[0] >= 1.0) - drawControlPoints(stroke, m_parameter[0] >= 2.0); + if (m_parameter[0] >= 1.0) drawControlPoints(stroke, m_parameter[0] >= 2.0); } #endif //============================================================================= -TMatrioskaStrokeProp::TMatrioskaStrokeProp(const TStroke *stroke, TMatrioskaStrokeStyle *style) - : TStrokeProp(stroke), m_colorStyle(style), m_outline(), m_outlinePixelSize(0) -{ - m_styleVersionNumber = m_colorStyle->getVersionNumber(); +TMatrioskaStrokeProp::TMatrioskaStrokeProp(const TStroke *stroke, + TMatrioskaStrokeStyle *style) + : TStrokeProp(stroke) + , m_colorStyle(style) + , m_outline() + , m_outlinePixelSize(0) { + m_styleVersionNumber = m_colorStyle->getVersionNumber(); } //----------------------------------------------------------------------------- -TStrokeProp *TMatrioskaStrokeProp::clone(const TStroke *stroke) const -{ - TMatrioskaStrokeProp *prop = new TMatrioskaStrokeProp(stroke, m_colorStyle); - prop->m_strokeChanged = m_strokeChanged; - prop->m_outline = m_outline; - prop->m_outlinePixelSize = m_outlinePixelSize; - return prop; +TStrokeProp *TMatrioskaStrokeProp::clone(const TStroke *stroke) const { + TMatrioskaStrokeProp *prop = new TMatrioskaStrokeProp(stroke, m_colorStyle); + prop->m_strokeChanged = m_strokeChanged; + prop->m_outline = m_outline; + prop->m_outlinePixelSize = m_outlinePixelSize; + return prop; } //----------------------------------------------------------------------------- -const TColorStyle *TMatrioskaStrokeProp::getColorStyle() const -{ - return m_colorStyle; +const TColorStyle *TMatrioskaStrokeProp::getColorStyle() const { + return m_colorStyle; } //----------------------------------------------------------------------------- -namespace -{ -void recomputeStrokes(const TStroke *stroke, vector &strokes, int strokeNumber) -{ - clearPointerContainer(strokes); +namespace { +void recomputeStrokes(const TStroke *stroke, vector &strokes, + int strokeNumber) { + clearPointerContainer(strokes); - strokes.resize(strokeNumber); + strokes.resize(strokeNumber); - int nCP = stroke->getControlPointCount(); + int nCP = stroke->getControlPointCount(); - double reduction; + double reduction; - for (int strokeId = 0; strokeId != strokeNumber; strokeId++) { - strokes[strokeId] = new TStroke(*stroke); + for (int strokeId = 0; strokeId != strokeNumber; strokeId++) { + strokes[strokeId] = new TStroke(*stroke); - reduction = ((double)strokeId + 0.5) / (double)(strokeNumber + 0.5); + reduction = ((double)strokeId + 0.5) / (double)(strokeNumber + 0.5); - for (int i = 0; i < nCP; i++) { - TThickPoint tp = strokes[strokeId]->getControlPoint(i); - tp.thick *= reduction; - strokes[strokeId]->setControlPoint(i, tp); - } - } + for (int i = 0; i < nCP; i++) { + TThickPoint tp = strokes[strokeId]->getControlPoint(i); + tp.thick *= reduction; + strokes[strokeId]->setControlPoint(i, tp); + } + } } -void recomputeOutlines(const TStroke *stroke, vector &strokes, vector &outlines, const TSolidColorStyle *style) -{ - TOutlineUtil::OutlineParameter param; - int strokeNumber = strokes.size(); - outlines.resize(strokeNumber + 1); - int strokeId; - for (strokeId = 0; strokeId != strokeNumber; strokeId++) { - outlines[strokeId].getArray().clear(); - style->computeOutline(strokes[strokeId], outlines[strokeId], param); - } - outlines[strokeId].getArray().clear(); - style->computeOutline(stroke, outlines[strokeId], param); +void recomputeOutlines(const TStroke *stroke, vector &strokes, + vector &outlines, + const TSolidColorStyle *style) { + TOutlineUtil::OutlineParameter param; + int strokeNumber = strokes.size(); + outlines.resize(strokeNumber + 1); + int strokeId; + for (strokeId = 0; strokeId != strokeNumber; strokeId++) { + outlines[strokeId].getArray().clear(); + style->computeOutline(strokes[strokeId], outlines[strokeId], param); + } + outlines[strokeId].getArray().clear(); + style->computeOutline(stroke, outlines[strokeId], param); } }; -void TMatrioskaStrokeProp::draw(const TVectorRenderData &rd) -{ - if (rd.m_clippingRect != TRect() && !rd.m_is3dView && !convert(rd.m_aff * m_stroke->getBBox()).overlaps(rd.m_clippingRect)) - return; - - int strokeId; - glPushMatrix(); - tglMultMatrix(rd.m_aff); - - double pixelSize = sqrt(tglGetPixelSize2()); - int strokeNumber = (int)(m_colorStyle->getParamValue(TColorStyle::double_tag(), 0)) - 1; - - if (m_strokeChanged || (UINT)strokeNumber != m_appStrokes.size()) { - m_strokeChanged = false; - m_outlinePixelSize = pixelSize; - recomputeStrokes(m_stroke, m_appStrokes, strokeNumber); - recomputeOutlines(m_stroke, m_appStrokes, m_outline, m_colorStyle); - } else if (!isAlmostZero(pixelSize - m_outlinePixelSize, 1e-5) - // || m_styleVersionNumber != m_colorStyle->getVersionNumber() - ) { - m_strokeChanged = false; - m_outlinePixelSize = pixelSize; - recomputeOutlines(m_stroke, m_appStrokes, m_outline, m_colorStyle); - } - - m_colorStyle->drawStroke(rd.m_cf, &m_outline[m_appStrokes.size()], m_stroke); - - TSolidColorStyle appStyle(m_colorStyle->getColorParamValue(1)); - - // if(m_colorStyle->isAlternate()) - // { - - for (strokeId = strokeNumber - 1; strokeId >= 0; strokeId--) { - if ((m_appStrokes.size() - strokeId) & 1) - appStyle.drawStroke(rd.m_cf, &m_outline[strokeId], m_appStrokes[strokeId]); - else - m_colorStyle->drawStroke(rd.m_cf, &m_outline[strokeId], m_appStrokes[strokeId]); - } - - // } - // else - // { - // TPixel32 color0=m_colorStyle->getColorParamValue(0); - // TPixel32 color1=m_colorStyle->getColorParamValue(1); - - // for(strokeId=strokeNumber-1; strokeId>=0;strokeId--) - // { - // double r2=(double)strokeId/(double)(strokeNumber); - // double r1=1-r2; - // TPixel32 color((int)(color0.r*r2+color1.r*r1), - // (int)(color0.g*r2+color1.g*r1), - // (int)(color0.b*r2+color1.b*r1), - // (int)(color0.m*r2+color1.m*r1) - // ); - - // appStyle.setMainColor(color); - // appStyle.drawStroke(rd.m_cf, &m_outline[strokeId],m_appStrokes[strokeId]); - // } - - // } - - glPopMatrix(); +void TMatrioskaStrokeProp::draw(const TVectorRenderData &rd) { + if (rd.m_clippingRect != TRect() && !rd.m_is3dView && + !convert(rd.m_aff * m_stroke->getBBox()).overlaps(rd.m_clippingRect)) + return; + + int strokeId; + glPushMatrix(); + tglMultMatrix(rd.m_aff); + + double pixelSize = sqrt(tglGetPixelSize2()); + int strokeNumber = + (int)(m_colorStyle->getParamValue(TColorStyle::double_tag(), 0)) - 1; + + if (m_strokeChanged || (UINT)strokeNumber != m_appStrokes.size()) { + m_strokeChanged = false; + m_outlinePixelSize = pixelSize; + recomputeStrokes(m_stroke, m_appStrokes, strokeNumber); + recomputeOutlines(m_stroke, m_appStrokes, m_outline, m_colorStyle); + } else if (!isAlmostZero(pixelSize - m_outlinePixelSize, 1e-5) + // || m_styleVersionNumber != m_colorStyle->getVersionNumber() + ) { + m_strokeChanged = false; + m_outlinePixelSize = pixelSize; + recomputeOutlines(m_stroke, m_appStrokes, m_outline, m_colorStyle); + } + + m_colorStyle->drawStroke(rd.m_cf, &m_outline[m_appStrokes.size()], m_stroke); + + TSolidColorStyle appStyle(m_colorStyle->getColorParamValue(1)); + + // if(m_colorStyle->isAlternate()) + // { + + for (strokeId = strokeNumber - 1; strokeId >= 0; strokeId--) { + if ((m_appStrokes.size() - strokeId) & 1) + appStyle.drawStroke(rd.m_cf, &m_outline[strokeId], + m_appStrokes[strokeId]); + else + m_colorStyle->drawStroke(rd.m_cf, &m_outline[strokeId], + m_appStrokes[strokeId]); + } + + // } + // else + // { + // TPixel32 color0=m_colorStyle->getColorParamValue(0); + // TPixel32 color1=m_colorStyle->getColorParamValue(1); + + // for(strokeId=strokeNumber-1; strokeId>=0;strokeId--) + // { + // double r2=(double)strokeId/(double)(strokeNumber); + // double r1=1-r2; + // TPixel32 color((int)(color0.r*r2+color1.r*r1), + // (int)(color0.g*r2+color1.g*r1), + // (int)(color0.b*r2+color1.b*r1), + // (int)(color0.m*r2+color1.m*r1) + // ); + + // appStyle.setMainColor(color); + // appStyle.drawStroke(rd.m_cf, + // &m_outline[strokeId],m_appStrokes[strokeId]); + // } + + // } + + glPopMatrix(); } //------------------------------------------------------------------------------------------ -void TMatrioskaStrokeProp::draw(TFlash &flash) -{ - int strokeId, strokeNumber = (int)(m_colorStyle->getParamValue(TColorStyle::double_tag(), 0)) - 1; - if ((UINT)strokeNumber != m_appStrokes.size()) { - recomputeStrokes(m_stroke, m_appStrokes, strokeNumber); - } +void TMatrioskaStrokeProp::draw(TFlash &flash) { + int strokeId, + strokeNumber = + (int)(m_colorStyle->getParamValue(TColorStyle::double_tag(), 0)) - 1; + if ((UINT)strokeNumber != m_appStrokes.size()) { + recomputeStrokes(m_stroke, m_appStrokes, strokeNumber); + } - m_colorStyle->TOutlineStyle::drawStroke(flash, m_stroke); + m_colorStyle->TOutlineStyle::drawStroke(flash, m_stroke); - TSolidColorStyle appStyle(m_colorStyle->getColorParamValue(1)); + TSolidColorStyle appStyle(m_colorStyle->getColorParamValue(1)); - for (strokeId = strokeNumber - 1; strokeId >= 0; strokeId--) { - if ((m_appStrokes.size() - strokeId) & 1) - appStyle.TOutlineStyle::drawStroke(flash, m_appStrokes[strokeId]); - else - m_colorStyle->TOutlineStyle::drawStroke(flash, m_appStrokes[strokeId]); - } + for (strokeId = strokeNumber - 1; strokeId >= 0; strokeId--) { + if ((m_appStrokes.size() - strokeId) & 1) + appStyle.TOutlineStyle::drawStroke(flash, m_appStrokes[strokeId]); + else + m_colorStyle->TOutlineStyle::drawStroke(flash, m_appStrokes[strokeId]); + } } //----------------------------------------------------------------------------- -TMatrioskaStrokeProp::~TMatrioskaStrokeProp() -{ - clearPointerContainer(m_appStrokes); +TMatrioskaStrokeProp::~TMatrioskaStrokeProp() { + clearPointerContainer(m_appStrokes); } //============================================================================= -TMatrioskaStrokeStyle::TMatrioskaStrokeStyle( - TPixel32 color1, TPixel32 color2, double parameter, bool alternate) - : TSolidColorStyle(color1), m_color2(color2), m_parameter(parameter) -{ -} +TMatrioskaStrokeStyle::TMatrioskaStrokeStyle(TPixel32 color1, TPixel32 color2, + double parameter, bool alternate) + : TSolidColorStyle(color1), m_color2(color2), m_parameter(parameter) {} //----------------------------------------------------------------------------- -TColorStyle *TMatrioskaStrokeStyle::clone() const -{ - return new TMatrioskaStrokeStyle(*this); +TColorStyle *TMatrioskaStrokeStyle::clone() const { + return new TMatrioskaStrokeStyle(*this); } //----------------------------------------------------------------------------- -TStrokeProp *TMatrioskaStrokeStyle::makeStrokeProp(const TStroke *stroke) -{ - return new TMatrioskaStrokeProp(stroke, this); +TStrokeProp *TMatrioskaStrokeStyle::makeStrokeProp(const TStroke *stroke) { + return new TMatrioskaStrokeProp(stroke, this); } //----------------------------------------------------------------------------- -int TMatrioskaStrokeStyle::getParamCount() const -{ - return 1; -} +int TMatrioskaStrokeStyle::getParamCount() const { return 1; } //----------------------------------------------------------------------------- -TColorStyle::ParamType TMatrioskaStrokeStyle::getParamType(int index) const -{ - assert(0 <= index && index < getParamCount()); - return TColorStyle::DOUBLE; +TColorStyle::ParamType TMatrioskaStrokeStyle::getParamType(int index) const { + assert(0 <= index && index < getParamCount()); + return TColorStyle::DOUBLE; } //----------------------------------------------------------------------------- -QString TMatrioskaStrokeStyle::getParamNames(int index) const -{ - assert(0 <= index && index < 1); +QString TMatrioskaStrokeStyle::getParamNames(int index) const { + assert(0 <= index && index < 1); - // if(index) - // return "alter/gradual"; - // else + // if(index) + // return "alter/gradual"; + // else - return QCoreApplication::translate("TMatrioskaStrokeStyle", "Stripes"); + return QCoreApplication::translate("TMatrioskaStrokeStyle", "Stripes"); } //----------------------------------------------------------------------------- -void TMatrioskaStrokeStyle::getParamRange(int index, double &min, double &max) const -{ - assert(0 <= index && index < 1); +void TMatrioskaStrokeStyle::getParamRange(int index, double &min, + double &max) const { + assert(0 <= index && index < 1); - // if(index) - // { - // min = 0; - // max = 1; - // } - // else - // { + // if(index) + // { + // min = 0; + // max = 1; + // } + // else + // { - min = 1.0; - max = 10.0; - //} + min = 1.0; + max = 10.0; + //} } //----------------------------------------------------------------------------- -double TMatrioskaStrokeStyle::getParamValue(TColorStyle::double_tag, int index) const -{ - assert(0 <= index && index < 1); +double TMatrioskaStrokeStyle::getParamValue(TColorStyle::double_tag, + int index) const { + assert(0 <= index && index < 1); - // if(index) - // return (m_alternate)? 0 : 1; - // else + // if(index) + // return (m_alternate)? 0 : 1; + // else - return m_parameter; + return m_parameter; } //----------------------------------------------------------------------------- -void TMatrioskaStrokeStyle::setParamValue(int index, double value) -{ - assert(0 <= index && index < 1); +void TMatrioskaStrokeStyle::setParamValue(int index, double value) { + assert(0 <= index && index < 1); - // if(index) - // m_alternate = value<0.5; - // else + // if(index) + // m_alternate = value<0.5; + // else - m_parameter = value; + m_parameter = value; - updateVersionNumber(); + updateVersionNumber(); } //----------------------------------------------------------------------------- -TPixel32 TMatrioskaStrokeStyle::getColorParamValue(int index) const -{ - assert(0 <= index && index < 2); - TPixel32 tmp; - switch (index) { - case (0): - tmp = TSolidColorStyle::getMainColor(); - break; - case (1): - tmp = m_color2; - break; - } - return tmp; +TPixel32 TMatrioskaStrokeStyle::getColorParamValue(int index) const { + assert(0 <= index && index < 2); + TPixel32 tmp; + switch (index) { + case (0): + tmp = TSolidColorStyle::getMainColor(); + break; + case (1): + tmp = m_color2; + break; + } + return tmp; } //----------------------------------------------------------------------------- -void TMatrioskaStrokeStyle::setColorParamValue(int index, const TPixel32 &color) -{ - assert(0 <= index && index < 2); - switch (index) { - case (0): - TSolidColorStyle::setMainColor(color); - break; - case (1): - m_color2 = color; - break; - } +void TMatrioskaStrokeStyle::setColorParamValue(int index, + const TPixel32 &color) { + assert(0 <= index && index < 2); + switch (index) { + case (0): + TSolidColorStyle::setMainColor(color); + break; + case (1): + m_color2 = color; + break; + } } //----------------------------------------------------------------------------- -void TMatrioskaStrokeStyle::loadData(TInputStreamInterface &is) -{ - TSolidColorStyle::loadData(is); - is >> m_parameter; - is >> m_color2; +void TMatrioskaStrokeStyle::loadData(TInputStreamInterface &is) { + TSolidColorStyle::loadData(is); + is >> m_parameter; + is >> m_color2; } //------------------------------------------------------------ -void TMatrioskaStrokeStyle::saveData(TOutputStreamInterface &os) const -{ - TSolidColorStyle::saveData(os); - os << m_parameter; - os << m_color2; +void TMatrioskaStrokeStyle::saveData(TOutputStreamInterface &os) const { + TSolidColorStyle::saveData(os); + os << m_parameter; + os << m_color2; } diff --git a/toonz/sources/colorfx/strokestyles.h b/toonz/sources/colorfx/strokestyles.h index 8d1caff..38e614d 100644 --- a/toonz/sources/colorfx/strokestyles.h +++ b/toonz/sources/colorfx/strokestyles.h @@ -26,16 +26,16 @@ class TRandom; //============================================================================= typedef struct { - TPointD point; - double dbl1; - double dbl2; + TPointD point; + double dbl1; + double dbl2; } PointAnd2Double; typedef std::vector Points; typedef struct { - float blend; - Points points; + float blend; + Points points; } BlendAndPoint; typedef std::vector> PointsAndColors; @@ -49,1064 +49,1192 @@ typedef std::vector BlendAndPoints; //============================================================================= template -class TOptimizedStrokeStyleT : public TColorStyle -{ +class TOptimizedStrokeStyleT : public TColorStyle { public: - TOptimizedStrokeStyleT() {} + TOptimizedStrokeStyleT() {} - bool isRegionStyle() const { return false; } - bool isStrokeStyle() const { return true; } + bool isRegionStyle() const { return false; } + bool isStrokeStyle() const { return true; } - TStrokeProp *makeStrokeProp(const TStroke *stroke); + TStrokeProp *makeStrokeProp(const TStroke *stroke); - TRegionProp *makeRegionProp(const TRegion *region) - { - assert(false); - return 0; - }; + TRegionProp *makeRegionProp(const TRegion *region) { + assert(false); + return 0; + }; - virtual void computeData(T &data, const TStroke *stroke, const TColorFunction *cf) const = 0; - virtual void drawStroke(const TColorFunction *cf, T &data, const TStroke *stroke) const = 0; + virtual void computeData(T &data, const TStroke *stroke, + const TColorFunction *cf) const = 0; + virtual void drawStroke(const TColorFunction *cf, T &data, + const TStroke *stroke) const = 0; }; //------------------------------------------------------------------- -class TFurStrokeStyle : public TOptimizedStrokeStyleT -{ - double m_cs, m_sn, m_angle, m_length; - TPixel32 m_color; +class TFurStrokeStyle : public TOptimizedStrokeStyleT { + double m_cs, m_sn, m_angle, m_length; + TPixel32 m_color; public: - TFurStrokeStyle(); + TFurStrokeStyle(); - TColorStyle *clone() const; + TColorStyle *clone() const; - void invalidate() {} + void invalidate() {} - void computeData(Points &positions, const TStroke *stroke, const TColorFunction *cf) const; - void drawStroke(const TColorFunction *cf, Points &positions, const TStroke *stroke) const; - void drawStroke(TFlash &rd, const TStroke *stroke) const; + void computeData(Points &positions, const TStroke *stroke, + const TColorFunction *cf) const; + void drawStroke(const TColorFunction *cf, Points &positions, + const TStroke *stroke) const; + void drawStroke(TFlash &rd, const TStroke *stroke) const; - QString getDescription() const { return QCoreApplication::translate("TFurStrokeStyle", "Herringbone"); } + QString getDescription() const { + return QCoreApplication::translate("TFurStrokeStyle", "Herringbone"); + } - bool hasMainColor() const { return true; } - TPixel32 getMainColor() const { return m_color; } - void setMainColor(const TPixel32 &color) { m_color = color; } + bool hasMainColor() const { return true; } + TPixel32 getMainColor() const { return m_color; } + void setMainColor(const TPixel32 &color) { m_color = color; } - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); - void saveData(TOutputStreamInterface &os) const - { - os << m_color << m_angle << m_length; - } + void saveData(TOutputStreamInterface &os) const { + os << m_color << m_angle << m_length; + } - void loadData(TInputStreamInterface &is) - { - is >> m_color >> m_angle >> m_length; - m_cs = cos(m_angle); - m_sn = sin(m_angle); - } + void loadData(TInputStreamInterface &is) { + is >> m_color >> m_angle >> m_length; + m_cs = cos(m_angle); + m_sn = sin(m_angle); + } - int getTagId() const { return 103; }; + int getTagId() const { return 103; }; }; //------------------------------------------------------------------- -class TChainStrokeStyle : public TOptimizedStrokeStyleT -{ - TPixel32 m_color; +class TChainStrokeStyle : public TOptimizedStrokeStyleT { + TPixel32 m_color; public: - TChainStrokeStyle(const TPixel32 &color); - TChainStrokeStyle(); + TChainStrokeStyle(const TPixel32 &color); + TChainStrokeStyle(); - void invalidate() {} + void invalidate() {} - TColorStyle *clone() const; + TColorStyle *clone() const; - QString getDescription() const { return QCoreApplication::translate("TChainStrokeStyle", "Chain"); } + QString getDescription() const { + return QCoreApplication::translate("TChainStrokeStyle", "Chain"); + } - bool hasMainColor() const { return true; } - TPixel32 getMainColor() const { return m_color; } - void setMainColor(const TPixel32 &color) { m_color = color; } + bool hasMainColor() const { return true; } + TPixel32 getMainColor() const { return m_color; } + void setMainColor(const TPixel32 &color) { m_color = color; } - void computeData(Points &positions, const TStroke *stroke, const TColorFunction *cf) const; - void drawStroke(const TColorFunction *cf, Points &positions, const TStroke *stroke) const; - void drawStroke(TFlash &flash, const TStroke *stroke) const; + void computeData(Points &positions, const TStroke *stroke, + const TColorFunction *cf) const; + void drawStroke(const TColorFunction *cf, Points &positions, + const TStroke *stroke) const; + void drawStroke(TFlash &flash, const TStroke *stroke) const; - void loadData(TInputStreamInterface &is) { is >> m_color; } - void saveData(TOutputStreamInterface &os) const { os << m_color; } - int getTagId() const { return 104; }; + void loadData(TInputStreamInterface &is) { is >> m_color; } + void saveData(TOutputStreamInterface &os) const { os << m_color; } + int getTagId() const { return 104; }; }; //------------------------------------------------------------------- -class TSprayStrokeStyle : public TSimpleStrokeStyle -{ - TPixel32 m_color; - double m_blend, m_intensity, m_radius; +class TSprayStrokeStyle : public TSimpleStrokeStyle { + TPixel32 m_color; + double m_blend, m_intensity, m_radius; public: - TSprayStrokeStyle(); + TSprayStrokeStyle(); - void invalidate() {} + void invalidate() {} - TColorStyle *clone() const; + TColorStyle *clone() const; - QString getDescription() const { return QCoreApplication::translate("TSprayStrokeStyle", "Circlets"); } + QString getDescription() const { + return QCoreApplication::translate("TSprayStrokeStyle", "Circlets"); + } - bool hasMainColor() const { return true; } - TPixel32 getMainColor() const { return m_color; } - void setMainColor(const TPixel32 &color) { m_color = color; } + bool hasMainColor() const { return true; } + TPixel32 getMainColor() const { return m_color; } + void setMainColor(const TPixel32 &color) { m_color = color; } - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); - void drawStroke(const TColorFunction *cf, const TStroke *stroke) const; - void drawStroke(TFlash &flash, const TStroke *stroke) const; + void drawStroke(const TColorFunction *cf, const TStroke *stroke) const; + void drawStroke(TFlash &flash, const TStroke *stroke) const; - void loadData(TInputStreamInterface &is) { is >> m_color >> m_blend >> m_intensity >> m_radius; } - void saveData(TOutputStreamInterface &os) const { os << m_color << m_blend << m_intensity << m_radius; } - int getTagId() const { return 106; }; + void loadData(TInputStreamInterface &is) { + is >> m_color >> m_blend >> m_intensity >> m_radius; + } + void saveData(TOutputStreamInterface &os) const { + os << m_color << m_blend << m_intensity << m_radius; + } + int getTagId() const { return 106; }; }; //------------------------------------------------------------------- -class TGraphicPenStrokeStyle : public TOptimizedStrokeStyleT -{ - TPixel32 m_color; - double m_intensity; +class TGraphicPenStrokeStyle + : public TOptimizedStrokeStyleT { + TPixel32 m_color; + double m_intensity; public: - TGraphicPenStrokeStyle(); + TGraphicPenStrokeStyle(); - void invalidate() {} + void invalidate() {} - TColorStyle *clone() const; + TColorStyle *clone() const; - QString getDescription() const { return QCoreApplication::translate("TGraphicPenStrokeStyle", "Dashes"); } + QString getDescription() const { + return QCoreApplication::translate("TGraphicPenStrokeStyle", "Dashes"); + } - bool hasMainColor() const { return true; } - TPixel32 getMainColor() const { return m_color; } - void setMainColor(const TPixel32 &color) { m_color = color; } + bool hasMainColor() const { return true; } + TPixel32 getMainColor() const { return m_color; } + void setMainColor(const TPixel32 &color) { m_color = color; } - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); - void computeData(DrawmodePointsMatrix &data, const TStroke *stroke, const TColorFunction *cf) const; - void drawStroke(const TColorFunction *cf, DrawmodePointsMatrix &data, const TStroke *stroke) const; - void drawStroke(TFlash &flash, const TStroke *s) const; + void computeData(DrawmodePointsMatrix &data, const TStroke *stroke, + const TColorFunction *cf) const; + void drawStroke(const TColorFunction *cf, DrawmodePointsMatrix &data, + const TStroke *stroke) const; + void drawStroke(TFlash &flash, const TStroke *s) const; - void loadData(TInputStreamInterface &is) { is >> m_color >> m_intensity; } - void saveData(TOutputStreamInterface &os) const { os << m_color << m_intensity; } - int getTagId() const { return 107; }; + void loadData(TInputStreamInterface &is) { is >> m_color >> m_intensity; } + void saveData(TOutputStreamInterface &os) const { + os << m_color << m_intensity; + } + int getTagId() const { return 107; }; }; //------------------------------------------------------------------- -class TDottedLineStrokeStyle : public TOptimizedStrokeStyleT -{ - TPixel32 m_color; - double m_in, m_line, m_out, m_blank; +class TDottedLineStrokeStyle : public TOptimizedStrokeStyleT { + TPixel32 m_color; + double m_in, m_line, m_out, m_blank; public: - TDottedLineStrokeStyle(); + TDottedLineStrokeStyle(); - void computeData(Points &positions, const TStroke *stroke, const TColorFunction *cf) const; - void drawStroke(const TColorFunction *cf, Points &positions, const TStroke *stroke) const; - void drawStroke(TFlash &flash, const TStroke *stroke) const; + void computeData(Points &positions, const TStroke *stroke, + const TColorFunction *cf) const; + void drawStroke(const TColorFunction *cf, Points &positions, + const TStroke *stroke) const; + void drawStroke(TFlash &flash, const TStroke *stroke) const; - void invalidate() {} + void invalidate() {} - TColorStyle *clone() const; + TColorStyle *clone() const; - QString getDescription() const { return QCoreApplication::translate("TDottedLineStrokeStyle", "Vanishing"); } + QString getDescription() const { + return QCoreApplication::translate("TDottedLineStrokeStyle", "Vanishing"); + } - bool hasMainColor() const { return true; } - TPixel32 getMainColor() const { return m_color; } - void setMainColor(const TPixel32 &color) { m_color = color; } + bool hasMainColor() const { return true; } + TPixel32 getMainColor() const { return m_color; } + void setMainColor(const TPixel32 &color) { m_color = color; } - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); - void loadData(TInputStreamInterface &is) { is >> m_color >> m_in >> m_line >> m_out >> m_blank; } - void saveData(TOutputStreamInterface &os) const { os << m_color << m_in << m_line << m_out << m_blank; } - bool isSaveSupported() { return true; } + void loadData(TInputStreamInterface &is) { + is >> m_color >> m_in >> m_line >> m_out >> m_blank; + } + void saveData(TOutputStreamInterface &os) const { + os << m_color << m_in << m_line << m_out << m_blank; + } + bool isSaveSupported() { return true; } - int getTagId() const { return 111; } + int getTagId() const { return 111; } }; //------------------------------------------------------------------- -class TRopeStrokeStyle : public TOptimizedStrokeStyleT -{ - TPixel32 m_color; - double m_bend; +class TRopeStrokeStyle : public TOptimizedStrokeStyleT { + TPixel32 m_color; + double m_bend; public: - TRopeStrokeStyle(); + TRopeStrokeStyle(); - void computeData(Points &positions, const TStroke *stroke, const TColorFunction *cf) const; - void drawStroke(const TColorFunction *cf, Points &positions, const TStroke *stroke) const; - void drawStroke(TFlash &flash, const TStroke *stroke) const; + void computeData(Points &positions, const TStroke *stroke, + const TColorFunction *cf) const; + void drawStroke(const TColorFunction *cf, Points &positions, + const TStroke *stroke) const; + void drawStroke(TFlash &flash, const TStroke *stroke) const; - void invalidate() {} + void invalidate() {} - TColorStyle *clone() const; + TColorStyle *clone() const; - QString getDescription() const { return QCoreApplication::translate("TRopeStrokeStyle", "Rope"); } + QString getDescription() const { + return QCoreApplication::translate("TRopeStrokeStyle", "Rope"); + } - bool hasMainColor() const { return true; } - TPixel32 getMainColor() const { return m_color; } - void setMainColor(const TPixel32 &color) { m_color = color; } + bool hasMainColor() const { return true; } + TPixel32 getMainColor() const { return m_color; } + void setMainColor(const TPixel32 &color) { m_color = color; } - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); - void loadData(TInputStreamInterface &is) { is >> m_color >> m_bend; } - void saveData(TOutputStreamInterface &os) const { os << m_color << m_bend; } - bool isSaveSupported() { return true; } + void loadData(TInputStreamInterface &is) { is >> m_color >> m_bend; } + void saveData(TOutputStreamInterface &os) const { os << m_color << m_bend; } + bool isSaveSupported() { return true; } - int getTagId() const { return 108; } + int getTagId() const { return 108; } }; //------------------------------------------------------------------- -class TCrystallizeStrokeStyle : public TOptimizedStrokeStyleT -{ - TPixel32 m_color; - double m_period, m_opacity; +class TCrystallizeStrokeStyle : public TOptimizedStrokeStyleT { + TPixel32 m_color; + double m_period, m_opacity; public: - TCrystallizeStrokeStyle(); + TCrystallizeStrokeStyle(); - void computeData(Points &positions, const TStroke *stroke, const TColorFunction *cf) const; - void drawStroke(const TColorFunction *cf, Points &positions, const TStroke *stroke) const; - void drawStroke(TFlash &flash, const TStroke *stroke) const; + void computeData(Points &positions, const TStroke *stroke, + const TColorFunction *cf) const; + void drawStroke(const TColorFunction *cf, Points &positions, + const TStroke *stroke) const; + void drawStroke(TFlash &flash, const TStroke *stroke) const; - void invalidate() {} + void invalidate() {} - TColorStyle *clone() const; + TColorStyle *clone() const; - QString getDescription() const { return QCoreApplication::translate("TCrystallizeStrokeStyle", "Tulle"); } + QString getDescription() const { + return QCoreApplication::translate("TCrystallizeStrokeStyle", "Tulle"); + } - bool hasMainColor() const { return true; } - TPixel32 getMainColor() const { return m_color; } - void setMainColor(const TPixel32 &color) { m_color = color; } + bool hasMainColor() const { return true; } + TPixel32 getMainColor() const { return m_color; } + void setMainColor(const TPixel32 &color) { m_color = color; } - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); - void loadData(TInputStreamInterface &is) { is >> m_color >> m_period >> m_opacity; } - void saveData(TOutputStreamInterface &os) const { os << m_color << m_period << m_opacity; } - bool isSaveSupported() { return true; } + void loadData(TInputStreamInterface &is) { + is >> m_color >> m_period >> m_opacity; + } + void saveData(TOutputStreamInterface &os) const { + os << m_color << m_period << m_opacity; + } + bool isSaveSupported() { return true; } - int getTagId() const { return 109; } + int getTagId() const { return 109; } }; //------------------------------------------------------------------- -class TBraidStrokeStyle : public TSimpleStrokeStyle -{ - TPixel32 m_colors[3]; - double m_period; +class TBraidStrokeStyle : public TSimpleStrokeStyle { + TPixel32 m_colors[3]; + double m_period; public: - TBraidStrokeStyle(); + TBraidStrokeStyle(); - TColorStyle *clone() const; + TColorStyle *clone() const; - void drawStroke(const TColorFunction *cf, const TStroke *stroke) const; - void drawStroke(TFlash &flash, const TStroke *stroke) const; + void drawStroke(const TColorFunction *cf, const TStroke *stroke) const; + void drawStroke(TFlash &flash, const TStroke *stroke) const; - void invalidate() {} + void invalidate() {} - QString getDescription() const { return QCoreApplication::translate("TBraidStrokeStyle", "Plait"); } + QString getDescription() const { + return QCoreApplication::translate("TBraidStrokeStyle", "Plait"); + } - bool hasMainColor() const { return true; } - TPixel32 getMainColor() const { return m_colors[0]; } - void setMainColor(const TPixel32 &color) { m_colors[0] = color; } + bool hasMainColor() const { return true; } + TPixel32 getMainColor() const { return m_colors[0]; } + void setMainColor(const TPixel32 &color) { m_colors[0] = color; } - int getColorParamCount() const { return 3; } - TPixel32 getColorParamValue(int index) const; - void setColorParamValue(int index, const TPixel32 &color); + int getColorParamCount() const { return 3; } + TPixel32 getColorParamValue(int index) const; + void setColorParamValue(int index, const TPixel32 &color); - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); - void loadData(TInputStreamInterface &is) { is >> m_colors[0] >> m_colors[1] >> m_colors[2] >> m_period; } - void loadData(int oldId, TInputStreamInterface &); - void saveData(TOutputStreamInterface &os) const { os << m_colors[0] << m_colors[1] << m_colors[2] << m_period; } - bool isSaveSupported() { return true; } + void loadData(TInputStreamInterface &is) { + is >> m_colors[0] >> m_colors[1] >> m_colors[2] >> m_period; + } + void loadData(int oldId, TInputStreamInterface &); + void saveData(TOutputStreamInterface &os) const { + os << m_colors[0] << m_colors[1] << m_colors[2] << m_period; + } + bool isSaveSupported() { return true; } - int getTagId() const { return 136; }; - void getObsoleteTagIds(std::vector &ids) const { ids.push_back(112); } + int getTagId() const { return 136; }; + void getObsoleteTagIds(std::vector &ids) const { ids.push_back(112); } }; //------------------------------------------------------------------- -class TSketchStrokeStyle : public TSimpleStrokeStyle -{ - TPixel32 m_color; - double m_density; +class TSketchStrokeStyle : public TSimpleStrokeStyle { + TPixel32 m_color; + double m_density; public: - TSketchStrokeStyle(); + TSketchStrokeStyle(); - TColorStyle *clone() const; + TColorStyle *clone() const; - void invalidate() {} + void invalidate() {} - QString getDescription() const { return QCoreApplication::translate("TSketchStrokeStyle", "Fuzz"); } + QString getDescription() const { + return QCoreApplication::translate("TSketchStrokeStyle", "Fuzz"); + } - bool hasMainColor() const { return true; } - TPixel32 getMainColor() const { return m_color; } - void setMainColor(const TPixel32 &color) { m_color = color; } + bool hasMainColor() const { return true; } + TPixel32 getMainColor() const { return m_color; } + void setMainColor(const TPixel32 &color) { m_color = color; } - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); - void drawStroke(const TColorFunction *cf, const TStroke *stroke) const; - void drawStroke(TFlash &fl, const TStroke *s) const; + void drawStroke(const TColorFunction *cf, const TStroke *stroke) const; + void drawStroke(TFlash &fl, const TStroke *s) const; - void loadData(TInputStreamInterface &is) { is >> m_color >> m_density; } - void saveData(TOutputStreamInterface &os) const { os << m_color << m_density; } - bool isSaveSupported() { return true; } + void loadData(TInputStreamInterface &is) { is >> m_color >> m_density; } + void saveData(TOutputStreamInterface &os) const { + os << m_color << m_density; + } + bool isSaveSupported() { return true; } - int getTagId() const { return 113; } + int getTagId() const { return 113; } }; //------------------------------------------------------------------- -class TBubbleStrokeStyle : public TSimpleStrokeStyle -{ - TPixel32 m_color0, m_color1; +class TBubbleStrokeStyle : public TSimpleStrokeStyle { + TPixel32 m_color0, m_color1; public: - TBubbleStrokeStyle(); - - TColorStyle *clone() const; - - void invalidate() {} - - QString getDescription() const { return QCoreApplication::translate("TBubbleStrokeStyle", "Bubbles"); } - - bool hasMainColor() const { return true; } - TPixel32 getMainColor() const { return m_color0; } - void setMainColor(const TPixel32 &color) { m_color0 = color; } - - int getColorParamCount() const { return 2; } - TPixel32 getColorParamValue(int index) const { return index == 0 ? m_color0 : m_color1; } - void setColorParamValue(int index, const TPixel32 &color) - { - if (index == 0) - m_color0 = color; - else - m_color1 = color; - } - - void drawStroke(const TColorFunction *cf, const TStroke *stroke) const; - void drawStroke(TFlash &flash, const TStroke *stroke) const; - - void loadData(TInputStreamInterface &is) { is >> m_color0 >> m_color1; } - void loadData(int oldId, TInputStreamInterface &); - void saveData(TOutputStreamInterface &os) const { os << m_color0 << m_color1; } - bool isSaveSupported() { return true; } - - int getTagId() const { return 114; }; - void getObsoleteTagIds(std::vector &ids) const { ids.push_back(137); } + TBubbleStrokeStyle(); + + TColorStyle *clone() const; + + void invalidate() {} + + QString getDescription() const { + return QCoreApplication::translate("TBubbleStrokeStyle", "Bubbles"); + } + + bool hasMainColor() const { return true; } + TPixel32 getMainColor() const { return m_color0; } + void setMainColor(const TPixel32 &color) { m_color0 = color; } + + int getColorParamCount() const { return 2; } + TPixel32 getColorParamValue(int index) const { + return index == 0 ? m_color0 : m_color1; + } + void setColorParamValue(int index, const TPixel32 &color) { + if (index == 0) + m_color0 = color; + else + m_color1 = color; + } + + void drawStroke(const TColorFunction *cf, const TStroke *stroke) const; + void drawStroke(TFlash &flash, const TStroke *stroke) const; + + void loadData(TInputStreamInterface &is) { is >> m_color0 >> m_color1; } + void loadData(int oldId, TInputStreamInterface &); + void saveData(TOutputStreamInterface &os) const { + os << m_color0 << m_color1; + } + bool isSaveSupported() { return true; } + + int getTagId() const { return 114; }; + void getObsoleteTagIds(std::vector &ids) const { ids.push_back(137); } }; //------------------------------------------------------------------- -class TTissueStrokeStyle : public TOptimizedStrokeStyleT -{ - TPixel32 m_color; - double m_density, m_border; +class TTissueStrokeStyle : public TOptimizedStrokeStyleT { + TPixel32 m_color; + double m_density, m_border; public: - TTissueStrokeStyle(); + TTissueStrokeStyle(); - TColorStyle *clone() const; + TColorStyle *clone() const; - void computeData(PointMatrix &data, const TStroke *stroke, const TColorFunction *cf) const; - void drawStroke(const TColorFunction *cf, PointMatrix &data, const TStroke *stroke) const; - void drawStroke(TFlash &flash, const TStroke *stroke) const; + void computeData(PointMatrix &data, const TStroke *stroke, + const TColorFunction *cf) const; + void drawStroke(const TColorFunction *cf, PointMatrix &data, + const TStroke *stroke) const; + void drawStroke(TFlash &flash, const TStroke *stroke) const; - void invalidate() {} + void invalidate() {} - QString getDescription() const { return QCoreApplication::translate("TTissueStrokeStyle", "Gauze"); } + QString getDescription() const { + return QCoreApplication::translate("TTissueStrokeStyle", "Gauze"); + } - bool hasMainColor() const { return true; } - TPixel32 getMainColor() const { return m_color; } - void setMainColor(const TPixel32 &color) { m_color = color; } + bool hasMainColor() const { return true; } + TPixel32 getMainColor() const { return m_color; } + void setMainColor(const TPixel32 &color) { m_color = color; } - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); - void loadData(TInputStreamInterface &is) { is >> m_color >> m_density >> m_border; } - void saveData(TOutputStreamInterface &os) const { os << m_color << m_density << m_border; } + void loadData(TInputStreamInterface &is) { + is >> m_color >> m_density >> m_border; + } + void saveData(TOutputStreamInterface &os) const { + os << m_color << m_density << m_border; + } - int getTagId() const { return 117; } + int getTagId() const { return 117; } }; //------------------------------------------------------------------- -class TBiColorStrokeStyle : public TOutlineStyle -{ - TPixel32 m_color0, m_color1; - double m_parameter; +class TBiColorStrokeStyle : public TOutlineStyle { + TPixel32 m_color0, m_color1; + double m_parameter; public: - TBiColorStrokeStyle(); - - TColorStyle *clone() const; - - void drawStroke(const TColorFunction *cf, TStrokeOutline *outline, const TStroke *stroke) const; - void drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const; - void drawStroke(TFlash &flash, const TStroke *stroke) const; - - bool isRegionStyle() const { return false; } - bool isStrokeStyle() const { return true; } - - void invalidate() {} - - QString getDescription() const { return QCoreApplication::translate("TBiColorStrokeStyle", "Shade"); } - - bool hasMainColor() const { return true; } - TPixel32 getMainColor() const { return m_color0; } - void setMainColor(const TPixel32 &color) { m_color0 = color; } - - void loadData(TInputStreamInterface &is); - void loadData(int oldId, TInputStreamInterface &); - - void saveData(TOutputStreamInterface &os) const; - - int getColorParamCount() const { return 2; } - TPixel32 getColorParamValue(int index) const { return index == 0 ? m_color0 : m_color1; } - void setColorParamValue(int index, const TPixel32 &color) - { - if (index == 0) - m_color0 = color; - else - m_color1 = color; - } - - int getTagId() const { return 135; }; - void getObsoleteTagIds(std::vector &ids) const - { - ids.push_back(115); - ids.push_back(119); - } + TBiColorStrokeStyle(); + + TColorStyle *clone() const; + + void drawStroke(const TColorFunction *cf, TStrokeOutline *outline, + const TStroke *stroke) const; + void drawRegion(const TColorFunction *cf, const bool antiAliasing, + TRegionOutline &boundary) const; + void drawStroke(TFlash &flash, const TStroke *stroke) const; + + bool isRegionStyle() const { return false; } + bool isStrokeStyle() const { return true; } + + void invalidate() {} + + QString getDescription() const { + return QCoreApplication::translate("TBiColorStrokeStyle", "Shade"); + } + + bool hasMainColor() const { return true; } + TPixel32 getMainColor() const { return m_color0; } + void setMainColor(const TPixel32 &color) { m_color0 = color; } + + void loadData(TInputStreamInterface &is); + void loadData(int oldId, TInputStreamInterface &); + + void saveData(TOutputStreamInterface &os) const; + + int getColorParamCount() const { return 2; } + TPixel32 getColorParamValue(int index) const { + return index == 0 ? m_color0 : m_color1; + } + void setColorParamValue(int index, const TPixel32 &color) { + if (index == 0) + m_color0 = color; + else + m_color1 = color; + } + + int getTagId() const { return 135; }; + void getObsoleteTagIds(std::vector &ids) const { + ids.push_back(115); + ids.push_back(119); + } }; //------------------------------------------------------------------- -class TNormal2StrokeStyle : public TOutlineStyle -{ - TPixel32 m_color; - double m_lightx, m_lighty, m_shininess, m_metal, m_bend; +class TNormal2StrokeStyle : public TOutlineStyle { + TPixel32 m_color; + double m_lightx, m_lighty, m_shininess, m_metal, m_bend; public: - TNormal2StrokeStyle(); + TNormal2StrokeStyle(); - TColorStyle *clone() const; + TColorStyle *clone() const; - void drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const; - void drawStroke(const TColorFunction *cf, TStrokeOutline *outline, const TStroke *stroke) const; - void drawStroke(TFlash &flash, const TStroke *stroke) const; + void drawRegion(const TColorFunction *cf, const bool antiAliasing, + TRegionOutline &boundary) const; + void drawStroke(const TColorFunction *cf, TStrokeOutline *outline, + const TStroke *stroke) const; + void drawStroke(TFlash &flash, const TStroke *stroke) const; - bool isRegionStyle() const { return false; } - bool isStrokeStyle() const { return true; } + bool isRegionStyle() const { return false; } + bool isStrokeStyle() const { return true; } - void invalidate() {} + void invalidate() {} - QString getDescription() const { return QCoreApplication::translate("TNormal2StrokeStyle", "Bump"); } + QString getDescription() const { + return QCoreApplication::translate("TNormal2StrokeStyle", "Bump"); + } - bool hasMainColor() const { return true; } - TPixel32 getMainColor() const { return m_color; } - void setMainColor(const TPixel32 &color) { m_color = color; } + bool hasMainColor() const { return true; } + TPixel32 getMainColor() const { return m_color; } + void setMainColor(const TPixel32 &color) { m_color = color; } - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); - void loadData(TInputStreamInterface &is) { is >> m_color >> m_lightx >> m_lighty >> m_shininess >> m_metal >> m_bend; } - void loadData(int oldId, TInputStreamInterface &); - void saveData(TOutputStreamInterface &os) const { os << m_color << m_lightx << m_lighty - << m_shininess << m_metal << m_bend; } + void loadData(TInputStreamInterface &is) { + is >> m_color >> m_lightx >> m_lighty >> m_shininess >> m_metal >> m_bend; + } + void loadData(int oldId, TInputStreamInterface &); + void saveData(TOutputStreamInterface &os) const { + os << m_color << m_lightx << m_lighty << m_shininess << m_metal << m_bend; + } - int getTagId() const { return 120; }; - void getObsoleteTagIds(std::vector &ids) const { ids.push_back(121); } + int getTagId() const { return 120; }; + void getObsoleteTagIds(std::vector &ids) const { ids.push_back(121); } }; //------------------------------------------------------------------- -class TChalkStrokeStyle2 : public TOptimizedStrokeStyleT -{ - TPixel32 m_color; - double m_blend, m_intensity, m_in, m_out, m_noise; +class TChalkStrokeStyle2 : public TOptimizedStrokeStyleT { + TPixel32 m_color; + double m_blend, m_intensity, m_in, m_out, m_noise; public: - TChalkStrokeStyle2(); - - TColorStyle *clone() const; - - void invalidate() {} - - QString getDescription() const { return QCoreApplication::translate("TChalkStrokeStyle2", "Chalk"); } - - bool hasMainColor() const { return true; } - TPixel32 getMainColor() const { return m_color; } - void setMainColor(const TPixel32 &color) { m_color = color; } - - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; - - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); - - void computeData(Doubles &positions, const TStroke *stroke, const TColorFunction *cf) const; - void drawStroke(const TColorFunction *cf, Doubles &positions, const TStroke *stroke) const; - - void loadData(TInputStreamInterface &is) { is >> m_color >> m_blend >> m_intensity >> m_in >> m_out >> m_noise; } - void loadData(int oldId, TInputStreamInterface &); - void saveData(TOutputStreamInterface &os) const { os << m_color << m_blend << m_intensity << m_in - << m_out << m_noise; } - int getTagId() const { return 123; }; - void getObsoleteTagIds(std::vector &ids) const { ids.push_back(105); } + TChalkStrokeStyle2(); + + TColorStyle *clone() const; + + void invalidate() {} + + QString getDescription() const { + return QCoreApplication::translate("TChalkStrokeStyle2", "Chalk"); + } + + bool hasMainColor() const { return true; } + TPixel32 getMainColor() const { return m_color; } + void setMainColor(const TPixel32 &color) { m_color = color; } + + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; + + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); + + void computeData(Doubles &positions, const TStroke *stroke, + const TColorFunction *cf) const; + void drawStroke(const TColorFunction *cf, Doubles &positions, + const TStroke *stroke) const; + + void loadData(TInputStreamInterface &is) { + is >> m_color >> m_blend >> m_intensity >> m_in >> m_out >> m_noise; + } + void loadData(int oldId, TInputStreamInterface &); + void saveData(TOutputStreamInterface &os) const { + os << m_color << m_blend << m_intensity << m_in << m_out << m_noise; + } + int getTagId() const { return 123; }; + void getObsoleteTagIds(std::vector &ids) const { ids.push_back(105); } }; //------------------------------------------------------------------- -class TBlendStrokeStyle2 : public TOptimizedStrokeStyleT -{ - TPixel32 m_color; - double m_blend, m_in, m_out; +class TBlendStrokeStyle2 : public TOptimizedStrokeStyleT { + TPixel32 m_color; + double m_blend, m_in, m_out; public: - TBlendStrokeStyle2(); + TBlendStrokeStyle2(); - TColorStyle *clone() const; + TColorStyle *clone() const; - void computeData(PointsAndDoubles &data, const TStroke *stroke, const TColorFunction *cf) const; - void drawStroke(const TColorFunction *cf, PointsAndDoubles &data, const TStroke *stroke) const; - void drawStroke(TFlash &flash, const TStroke *stroke) const; + void computeData(PointsAndDoubles &data, const TStroke *stroke, + const TColorFunction *cf) const; + void drawStroke(const TColorFunction *cf, PointsAndDoubles &data, + const TStroke *stroke) const; + void drawStroke(TFlash &flash, const TStroke *stroke) const; - void invalidate() {} + void invalidate() {} - QString getDescription() const { return QCoreApplication::translate("TBlendStrokeStyle2", "Fade"); } + QString getDescription() const { + return QCoreApplication::translate("TBlendStrokeStyle2", "Fade"); + } - bool hasMainColor() const { return true; } - TPixel32 getMainColor() const { return m_color; } - void setMainColor(const TPixel32 &color) { m_color = color; } + bool hasMainColor() const { return true; } + TPixel32 getMainColor() const { return m_color; } + void setMainColor(const TPixel32 &color) { m_color = color; } - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); - void loadData(TInputStreamInterface &is) { is >> m_color >> m_blend >> m_in >> m_out; } - void loadData(int oldId, TInputStreamInterface &); - void saveData(TOutputStreamInterface &os) const { os << m_color << m_blend << m_in << m_out; } - bool isSaveSupported() { return true; } + void loadData(TInputStreamInterface &is) { + is >> m_color >> m_blend >> m_in >> m_out; + } + void loadData(int oldId, TInputStreamInterface &); + void saveData(TOutputStreamInterface &os) const { + os << m_color << m_blend << m_in << m_out; + } + bool isSaveSupported() { return true; } - int getTagId() const { return 125; }; - void getObsoleteTagIds(std::vector &ids) const { ids.push_back(110); } + int getTagId() const { return 125; }; + void getObsoleteTagIds(std::vector &ids) const { ids.push_back(110); } }; //------------------------------------------------------------------- -class TTwirlStrokeStyle : public TOptimizedStrokeStyleT -{ - TPixel32 m_color; - double m_period, m_blend; +class TTwirlStrokeStyle : public TOptimizedStrokeStyleT { + TPixel32 m_color; + double m_period, m_blend; public: - TTwirlStrokeStyle(); + TTwirlStrokeStyle(); - TColorStyle *clone() const; + TColorStyle *clone() const; - void computeData(Doubles &data, const TStroke *stroke, const TColorFunction *cf) const; - void drawStroke(const TColorFunction *cf, Doubles &data, const TStroke *stroke) const; - //void drawStroke(const TColorFunction *cf, const TStroke *stroke) const; - void drawStroke(TFlash &flash, const TStroke *stroke) const; + void computeData(Doubles &data, const TStroke *stroke, + const TColorFunction *cf) const; + void drawStroke(const TColorFunction *cf, Doubles &data, + const TStroke *stroke) const; + // void drawStroke(const TColorFunction *cf, const TStroke *stroke) const; + void drawStroke(TFlash &flash, const TStroke *stroke) const; - void invalidate() {} + void invalidate() {} - QString getDescription() const { return QCoreApplication::translate("TTwirlStrokeStyle", "Ribbon"); } + QString getDescription() const { + return QCoreApplication::translate("TTwirlStrokeStyle", "Ribbon"); + } - bool hasMainColor() const { return true; } - TPixel32 getMainColor() const { return m_color; } - void setMainColor(const TPixel32 &color) { m_color = color; } + bool hasMainColor() const { return true; } + TPixel32 getMainColor() const { return m_color; } + void setMainColor(const TPixel32 &color) { m_color = color; } - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); - void loadData(TInputStreamInterface &is) { is >> m_color >> m_period >> m_blend; } - void saveData(TOutputStreamInterface &os) const { os << m_color << m_period << m_blend; } - bool isSaveSupported() { return true; } + void loadData(TInputStreamInterface &is) { + is >> m_color >> m_period >> m_blend; + } + void saveData(TOutputStreamInterface &os) const { + os << m_color << m_period << m_blend; + } + bool isSaveSupported() { return true; } - int getTagId() const { return 126; } + int getTagId() const { return 126; } }; //------------------------------------------------------------------- -class TSawToothStrokeStyle : public TOutlineStyle -{ - TPixel32 m_color; - double m_parameter; +class TSawToothStrokeStyle : public TOutlineStyle { + TPixel32 m_color; + double m_parameter; public: - TSawToothStrokeStyle(TPixel32 color = TPixel32::Blue, - double parameter = 20.0); + TSawToothStrokeStyle(TPixel32 color = TPixel32::Blue, + double parameter = 20.0); - TColorStyle *clone() const; + TColorStyle *clone() const; - void drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const {} - void drawStroke(const TColorFunction *cf, TStrokeOutline *outline, const TStroke *stroke) const; - void drawStroke(TFlash &flash, const TStroke *stroke) const; + void drawRegion(const TColorFunction *cf, const bool antiAliasing, + TRegionOutline &boundary) const {} + void drawStroke(const TColorFunction *cf, TStrokeOutline *outline, + const TStroke *stroke) const; + void drawStroke(TFlash &flash, const TStroke *stroke) const; - bool isRegionStyle() const { return false; } - bool isStrokeStyle() const { return true; } + bool isRegionStyle() const { return false; } + bool isStrokeStyle() const { return true; } - void invalidate() {} + void invalidate() {} - void computeOutline(const TStroke *stroke, - TStrokeOutline &outline, - TOutlineUtil::OutlineParameter param) const; + void computeOutline(const TStroke *stroke, TStrokeOutline &outline, + TOutlineUtil::OutlineParameter param) const; - QString getDescription() const { return QCoreApplication::translate("TSawToothStrokeStyle", "Jagged"); } + QString getDescription() const { + return QCoreApplication::translate("TSawToothStrokeStyle", "Jagged"); + } - bool hasMainColor() const { return true; } - TPixel32 getMainColor() const { return m_color; } - void setMainColor(const TPixel32 &color) { m_color = color; } + bool hasMainColor() const { return true; } + TPixel32 getMainColor() const { return m_color; } + void setMainColor(const TPixel32 &color) { m_color = color; } - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); - int getTagId() const { return 127; }; - void loadData(TInputStreamInterface &is) { is >> m_color >> m_parameter; } - void saveData(TOutputStreamInterface &os) const { os << m_color << m_parameter; } + int getTagId() const { return 127; }; + void loadData(TInputStreamInterface &is) { is >> m_color >> m_parameter; } + void saveData(TOutputStreamInterface &os) const { + os << m_color << m_parameter; + } }; //------------------------------------------------------------------- -class TMultiLineStrokeStyle2 : public TOptimizedStrokeStyleT -{ - TPixel32 m_color0, m_color1; - double m_intensity, m_length, m_thick, m_noise; +class TMultiLineStrokeStyle2 : public TOptimizedStrokeStyleT { + TPixel32 m_color0, m_color1; + double m_intensity, m_length, m_thick, m_noise; public: - TMultiLineStrokeStyle2(); - - TColorStyle *clone() const; - - void computeData(BlendAndPoints &data, const TStroke *stroke, const TColorFunction *cf) const; - void drawStroke(const TColorFunction *cf, BlendAndPoints &data, const TStroke *stroke) const; - //void drawStroke(const TColorFunction *cf, const TStroke *stroke) const; - void drawStroke(TFlash &flash, const TStroke *stroke) const; - - void invalidate() {} - - QString getDescription() const { return QCoreApplication::translate("TMultiLineStrokeStyle2", "Gouache"); } - - bool hasMainColor() const { return true; } - TPixel32 getMainColor() const { return m_color0; } - void setMainColor(const TPixel32 &color) { m_color0 = color; } - - int getColorParamCount() const { return 2; } - TPixel32 getColorParamValue(int index) const { return index == 0 ? m_color0 : m_color1; } - void setColorParamValue(int index, const TPixel32 &color) - { - if (index == 0) - m_color0 = color; - else - m_color1 = color; - } - - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; - - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); - - void loadData(TInputStreamInterface &is) { is >> m_color0 >> m_color1 >> m_intensity >> m_length >> m_thick >> m_noise; } - void loadData(int oldId, TInputStreamInterface &); - void saveData(TOutputStreamInterface &os) const { os << m_color0 << m_color1 << m_intensity << m_length << m_thick << m_noise; } - bool isSaveSupported() { return true; } - - int getTagId() const { return 138; }; - void getObsoleteTagIds(std::vector &ids) const - { - ids.push_back(118); - ids.push_back(128); - } + TMultiLineStrokeStyle2(); + + TColorStyle *clone() const; + + void computeData(BlendAndPoints &data, const TStroke *stroke, + const TColorFunction *cf) const; + void drawStroke(const TColorFunction *cf, BlendAndPoints &data, + const TStroke *stroke) const; + // void drawStroke(const TColorFunction *cf, const TStroke *stroke) const; + void drawStroke(TFlash &flash, const TStroke *stroke) const; + + void invalidate() {} + + QString getDescription() const { + return QCoreApplication::translate("TMultiLineStrokeStyle2", "Gouache"); + } + + bool hasMainColor() const { return true; } + TPixel32 getMainColor() const { return m_color0; } + void setMainColor(const TPixel32 &color) { m_color0 = color; } + + int getColorParamCount() const { return 2; } + TPixel32 getColorParamValue(int index) const { + return index == 0 ? m_color0 : m_color1; + } + void setColorParamValue(int index, const TPixel32 &color) { + if (index == 0) + m_color0 = color; + else + m_color1 = color; + } + + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; + + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); + + void loadData(TInputStreamInterface &is) { + is >> m_color0 >> m_color1 >> m_intensity >> m_length >> m_thick >> m_noise; + } + void loadData(int oldId, TInputStreamInterface &); + void saveData(TOutputStreamInterface &os) const { + os << m_color0 << m_color1 << m_intensity << m_length << m_thick << m_noise; + } + bool isSaveSupported() { return true; } + + int getTagId() const { return 138; }; + void getObsoleteTagIds(std::vector &ids) const { + ids.push_back(118); + ids.push_back(128); + } }; //------------------------------------------------------------------- -class TZigzagStrokeStyle : public TOptimizedStrokeStyleT -{ - TPixel32 m_color; - double m_minDist, m_maxDist; - double m_minAngle, m_maxAngle; - double m_thickness; +class TZigzagStrokeStyle : public TOptimizedStrokeStyleT { + TPixel32 m_color; + double m_minDist, m_maxDist; + double m_minAngle, m_maxAngle; + double m_thickness; - //void drawBLines(RectVector& rects) const; - void setRealMinMax() const; - bool getZigZagPosition(const TStroke *stroke, TRandom &rnd, - const double s, const int first, - const double minTranslLength, - TThickPoint &pos, TThickPoint &pos1) const; + // void drawBLines(RectVector& rects) const; + void setRealMinMax() const; + bool getZigZagPosition(const TStroke *stroke, TRandom &rnd, const double s, + const int first, const double minTranslLength, + TThickPoint &pos, TThickPoint &pos1) const; public: - TZigzagStrokeStyle(); - - TColorStyle *clone() const; - - void computeData(Points &positions, const TStroke *stroke, const TColorFunction *cf) const; - void drawStroke(const TColorFunction *cf, Points &positions, const TStroke *stroke) const; - //void drawStroke(const TColorFunction *cf, const TStroke *stroke) const; - void drawStroke(TFlash &flash, const TStroke *stroke) const; - - void invalidate() {} - - QString getDescription() const { return QCoreApplication::translate("TZigzagStrokeStyle", "Zigzag"); } - - bool hasMainColor() const { return true; } - TPixel32 getMainColor() const { return m_color; } - void setMainColor(const TPixel32 &color) { m_color = color; } - - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; - - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); - - void loadData(TInputStreamInterface &is) { is >> m_color >> m_minDist >> m_maxDist >> m_minAngle >> m_maxAngle >> m_thickness; } - void saveData(TOutputStreamInterface &os) const { os << m_color << m_minDist << m_maxDist << m_minAngle << m_maxAngle << m_thickness; } - bool isSaveSupported() { return true; } - - int getTagId() const { return 129; } + TZigzagStrokeStyle(); + + TColorStyle *clone() const; + + void computeData(Points &positions, const TStroke *stroke, + const TColorFunction *cf) const; + void drawStroke(const TColorFunction *cf, Points &positions, + const TStroke *stroke) const; + // void drawStroke(const TColorFunction *cf, const TStroke *stroke) const; + void drawStroke(TFlash &flash, const TStroke *stroke) const; + + void invalidate() {} + + QString getDescription() const { + return QCoreApplication::translate("TZigzagStrokeStyle", "Zigzag"); + } + + bool hasMainColor() const { return true; } + TPixel32 getMainColor() const { return m_color; } + void setMainColor(const TPixel32 &color) { m_color = color; } + + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; + + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); + + void loadData(TInputStreamInterface &is) { + is >> m_color >> m_minDist >> m_maxDist >> m_minAngle >> m_maxAngle >> + m_thickness; + } + void saveData(TOutputStreamInterface &os) const { + os << m_color << m_minDist << m_maxDist << m_minAngle << m_maxAngle + << m_thickness; + } + bool isSaveSupported() { return true; } + + int getTagId() const { return 129; } }; //------------------------------------------------------------------- -class TSinStrokeStyle : public TOptimizedStrokeStyleT -{ - TPixel32 m_color; - double m_frequency, m_thick; +class TSinStrokeStyle : public TOptimizedStrokeStyleT { + TPixel32 m_color; + double m_frequency, m_thick; public: - TSinStrokeStyle(); + TSinStrokeStyle(); - TColorStyle *clone() const; + TColorStyle *clone() const; - void computeData(Points &positions, const TStroke *stroke, const TColorFunction *cf) const; - void drawStroke(const TColorFunction *cf, Points &positions, const TStroke *stroke) const; - //void drawStroke(const TColorFunction *cf, const TStroke *stroke) const; - void drawStroke(TFlash &flash, const TStroke *stroke) const; + void computeData(Points &positions, const TStroke *stroke, + const TColorFunction *cf) const; + void drawStroke(const TColorFunction *cf, Points &positions, + const TStroke *stroke) const; + // void drawStroke(const TColorFunction *cf, const TStroke *stroke) const; + void drawStroke(TFlash &flash, const TStroke *stroke) const; - void invalidate() {} + void invalidate() {} - QString getDescription() const { return QCoreApplication::translate("TSinStrokeStyle", "Wave"); } + QString getDescription() const { + return QCoreApplication::translate("TSinStrokeStyle", "Wave"); + } - bool hasMainColor() const { return true; } - TPixel32 getMainColor() const { return m_color; } - void setMainColor(const TPixel32 &color) { m_color = color; } + bool hasMainColor() const { return true; } + TPixel32 getMainColor() const { return m_color; } + void setMainColor(const TPixel32 &color) { m_color = color; } - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); - void loadData(TInputStreamInterface &is) { is >> m_color >> m_frequency >> m_thick; } - void saveData(TOutputStreamInterface &os) const { os << m_color << m_frequency << m_thick; } + void loadData(TInputStreamInterface &is) { + is >> m_color >> m_frequency >> m_thick; + } + void saveData(TOutputStreamInterface &os) const { + os << m_color << m_frequency << m_thick; + } - int getTagId() const { return 130; } + int getTagId() const { return 130; } }; //------------------------------------------------------------------- -class TFriezeStrokeStyle2 : public TOptimizedStrokeStyleT -{ - TPixel32 m_color; - double m_parameter, m_thick; +class TFriezeStrokeStyle2 : public TOptimizedStrokeStyleT { + TPixel32 m_color; + double m_parameter, m_thick; public: - TFriezeStrokeStyle2(); - - TColorStyle *clone() const; - - void invalidate() {} - - QString getDescription() const { return QCoreApplication::translate("TFriezeStrokeStyle2", "Curl"); } - - bool hasMainColor() const { return true; } - TPixel32 getMainColor() const { return m_color; } - void setMainColor(const TPixel32 &color) { m_color = color; } - - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; - - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); - - void computeData(std::vector &positions, const TStroke *stroke, const TColorFunction *cf) const; - void drawStroke(const TColorFunction *cf, std::vector &positions, const TStroke *stroke) const; - //void drawStroke(const TColorFunction *cf, const TStroke *stroke) const; - void drawStroke(TFlash &flash, const TStroke *stroke) const; - - void loadData(TInputStreamInterface &is) { is >> m_color >> m_parameter >> m_thick; } - void loadData(int oldId, TInputStreamInterface &); - void saveData(TOutputStreamInterface &os) const { os << m_color << m_parameter << m_thick; } - int getTagId() const { return 133; }; - void getObsoleteTagIds(std::vector &ids) const { ids.push_back(102); } + TFriezeStrokeStyle2(); + + TColorStyle *clone() const; + + void invalidate() {} + + QString getDescription() const { + return QCoreApplication::translate("TFriezeStrokeStyle2", "Curl"); + } + + bool hasMainColor() const { return true; } + TPixel32 getMainColor() const { return m_color; } + void setMainColor(const TPixel32 &color) { m_color = color; } + + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; + + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); + + void computeData(std::vector &positions, const TStroke *stroke, + const TColorFunction *cf) const; + void drawStroke(const TColorFunction *cf, std::vector &positions, + const TStroke *stroke) const; + // void drawStroke(const TColorFunction *cf, const TStroke *stroke) const; + void drawStroke(TFlash &flash, const TStroke *stroke) const; + + void loadData(TInputStreamInterface &is) { + is >> m_color >> m_parameter >> m_thick; + } + void loadData(int oldId, TInputStreamInterface &); + void saveData(TOutputStreamInterface &os) const { + os << m_color << m_parameter << m_thick; + } + int getTagId() const { return 133; }; + void getObsoleteTagIds(std::vector &ids) const { ids.push_back(102); } }; //------------------------------------------------------------------- -class TDualColorStrokeStyle2 : public TOutlineStyle -{ - TPixel32 m_color0, m_color1; - double m_parameter; +class TDualColorStrokeStyle2 : public TOutlineStyle { + TPixel32 m_color0, m_color1; + double m_parameter; public: - TDualColorStrokeStyle2( - TPixel32 color0 = TPixel32::Blue, - TPixel32 color1 = TPixel32::Yellow, - double parameter = 20.0); - - TColorStyle *clone() const; - - void drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const {} - void drawStroke(const TColorFunction *cf, TStrokeOutline *outline, const TStroke *stroke) const; - void drawStroke(TFlash &flash, const TStroke *stroke) const; - - bool isRegionStyle() const { return false; } - bool isStrokeStyle() const { return true; } - - void invalidate() {} - - void computeOutline(const TStroke *stroke, - TStrokeOutline &outline, - TOutlineUtil::OutlineParameter param) const; - - QString getDescription() const { return QCoreApplication::translate("TDualColorStrokeStyle2", "Striped"); } - - bool hasMainColor() const { return true; } - TPixel32 getMainColor() const { return m_color0; } - void setMainColor(const TPixel32 &color) { m_color0 = color; } - - int getColorParamCount() const { return 2; } - TPixel32 getColorParamValue(int index) const { return (index == 0) ? m_color0 : m_color1; } - void setColorParamValue(int index, const TPixel32 &color) - { - if (index == 0) - m_color0 = color; - else - m_color1 = color; - } - - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; - - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); - - int getTagId() const { return 132; }; - void loadData(TInputStreamInterface &is) { is >> m_color0 >> m_color1 >> m_parameter; } - void saveData(TOutputStreamInterface &os) const { os << m_color0 << m_color1 << m_parameter; } + TDualColorStrokeStyle2(TPixel32 color0 = TPixel32::Blue, + TPixel32 color1 = TPixel32::Yellow, + double parameter = 20.0); + + TColorStyle *clone() const; + + void drawRegion(const TColorFunction *cf, const bool antiAliasing, + TRegionOutline &boundary) const {} + void drawStroke(const TColorFunction *cf, TStrokeOutline *outline, + const TStroke *stroke) const; + void drawStroke(TFlash &flash, const TStroke *stroke) const; + + bool isRegionStyle() const { return false; } + bool isStrokeStyle() const { return true; } + + void invalidate() {} + + void computeOutline(const TStroke *stroke, TStrokeOutline &outline, + TOutlineUtil::OutlineParameter param) const; + + QString getDescription() const { + return QCoreApplication::translate("TDualColorStrokeStyle2", "Striped"); + } + + bool hasMainColor() const { return true; } + TPixel32 getMainColor() const { return m_color0; } + void setMainColor(const TPixel32 &color) { m_color0 = color; } + + int getColorParamCount() const { return 2; } + TPixel32 getColorParamValue(int index) const { + return (index == 0) ? m_color0 : m_color1; + } + void setColorParamValue(int index, const TPixel32 &color) { + if (index == 0) + m_color0 = color; + else + m_color1 = color; + } + + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; + + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); + + int getTagId() const { return 132; }; + void loadData(TInputStreamInterface &is) { + is >> m_color0 >> m_color1 >> m_parameter; + } + void saveData(TOutputStreamInterface &os) const { + os << m_color0 << m_color1 << m_parameter; + } }; //------------------------------------------------------------------- -class TLongBlendStrokeStyle2 : public TOutlineStyle -{ - TPixel32 m_color0, m_color1; - double m_parameter; +class TLongBlendStrokeStyle2 : public TOutlineStyle { + TPixel32 m_color0, m_color1; + double m_parameter; public: - TLongBlendStrokeStyle2(TPixel32 color0 = TPixel32::Blue, - TPixel32 color1 = TPixel32::Transparent, - double parameter = 20.0); - - TColorStyle *clone() const; - - void drawRegion(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &boundary) const {} - void drawStroke(const TColorFunction *cf, TStrokeOutline *outline, const TStroke *stroke) const; - void drawStroke(TFlash &flash, const TStroke *stroke) const; - - bool isRegionStyle() const { return false; } - bool isStrokeStyle() const { return true; } - - void invalidate() {} - - void computeOutline(const TStroke *stroke, - TStrokeOutline &outline, - TOutlineUtil::OutlineParameter param) const; - - QString getDescription() const { return QCoreApplication::translate("TLongBlendStrokeStyle2", "Watercolor"); } - - bool hasMainColor() const { return true; } - TPixel32 getMainColor() const { return m_color0; } - void setMainColor(const TPixel32 &color0) { m_color0 = color0; } - - int getColorParamCount() const { return 2; } - TPixel32 getColorParamValue(int index) const { return index == 0 ? m_color0 : m_color1; } - void setColorParamValue(int index, const TPixel32 &color) - { - if (index == 0) - m_color0 = color; - else - m_color1 = color; - } - - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; - - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); - - int getTagId() const { return 134; }; - void loadData(TInputStreamInterface &is) { is >> m_color0 >> m_color1 >> m_parameter; } - void saveData(TOutputStreamInterface &os) const { os << m_color0 << m_color1 << m_parameter; } + TLongBlendStrokeStyle2(TPixel32 color0 = TPixel32::Blue, + TPixel32 color1 = TPixel32::Transparent, + double parameter = 20.0); + + TColorStyle *clone() const; + + void drawRegion(const TColorFunction *cf, const bool antiAliasing, + TRegionOutline &boundary) const {} + void drawStroke(const TColorFunction *cf, TStrokeOutline *outline, + const TStroke *stroke) const; + void drawStroke(TFlash &flash, const TStroke *stroke) const; + + bool isRegionStyle() const { return false; } + bool isStrokeStyle() const { return true; } + + void invalidate() {} + + void computeOutline(const TStroke *stroke, TStrokeOutline &outline, + TOutlineUtil::OutlineParameter param) const; + + QString getDescription() const { + return QCoreApplication::translate("TLongBlendStrokeStyle2", "Watercolor"); + } + + bool hasMainColor() const { return true; } + TPixel32 getMainColor() const { return m_color0; } + void setMainColor(const TPixel32 &color0) { m_color0 = color0; } + + int getColorParamCount() const { return 2; } + TPixel32 getColorParamValue(int index) const { + return index == 0 ? m_color0 : m_color1; + } + void setColorParamValue(int index, const TPixel32 &color) { + if (index == 0) + m_color0 = color; + else + m_color1 = color; + } + + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; + + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); + + int getTagId() const { return 134; }; + void loadData(TInputStreamInterface &is) { + is >> m_color0 >> m_color1 >> m_parameter; + } + void saveData(TOutputStreamInterface &os) const { + os << m_color0 << m_color1 << m_parameter; + } }; //------------------------------------------------------------------- #ifdef _DEBUG -class OutlineViewerStyle : public TSolidColorStyle -{ - double m_parameter[4]; +class OutlineViewerStyle : public TSolidColorStyle { + double m_parameter[4]; - bool m_boolPar; - int m_intPar; - int m_enumPar; - TFilePath m_pathPar; + bool m_boolPar; + int m_intPar; + int m_enumPar; + TFilePath m_pathPar; protected: - void loadData(TInputStreamInterface &is); - void saveData(TOutputStreamInterface &os) const; + void loadData(TInputStreamInterface &is); + void saveData(TOutputStreamInterface &os) const; public: - OutlineViewerStyle(TPixel32 color = TPixel32::Black, - double parameter0 = 0.0, double parameter1 = 0.0, - double parameter2 = 2.0, double parameter3 = 3.0); + OutlineViewerStyle(TPixel32 color = TPixel32::Black, double parameter0 = 0.0, + double parameter1 = 0.0, double parameter2 = 2.0, + double parameter3 = 3.0); - TColorStyle *clone() const; + TColorStyle *clone() const; - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; - QString getParamNames(int index) const; + QString getParamNames(int index) const; - bool getParamValue(TColorStyle::bool_tag, int index) const; - void setParamValue(int index, bool value); + bool getParamValue(TColorStyle::bool_tag, int index) const; + void setParamValue(int index, bool value); - void getParamRange(int index, int &min, int &max) const; - int getParamValue(TColorStyle::int_tag, int index) const; - void setParamValue(int index, int value); + void getParamRange(int index, int &min, int &max) const; + int getParamValue(TColorStyle::int_tag, int index) const; + void setParamValue(int index, int value); - void getParamRange(int index, QStringList &enumItems) const; + void getParamRange(int index, QStringList &enumItems) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); - TFilePath getParamValue(TColorStyle::TFilePath_tag, int index) const; - void setParamValue(int index, const TFilePath &path); + TFilePath getParamValue(TColorStyle::TFilePath_tag, int index) const; + void setParamValue(int index, const TFilePath &path); - void computeOutline(const TStroke *stroke, - TStrokeOutline &outline, - TOutlineUtil::OutlineParameter param) const; + void computeOutline(const TStroke *stroke, TStrokeOutline &outline, + TOutlineUtil::OutlineParameter param) const; - bool isRegionStyle() const { return false; } - bool isStrokeStyle() const { return true; } + bool isRegionStyle() const { return false; } + bool isStrokeStyle() const { return true; } - void drawStroke(const TColorFunction *cf, TStrokeOutline *outline, const TStroke *stroke) const; - QString getDescription() const { return QCoreApplication::translate("OutlineViewerStyle", "OutlineViewer(OnlyDebug)"); } - int getTagId() const { return 99; }; + void drawStroke(const TColorFunction *cf, TStrokeOutline *outline, + const TStroke *stroke) const; + QString getDescription() const { + return QCoreApplication::translate("OutlineViewerStyle", + "OutlineViewer(OnlyDebug)"); + } + int getTagId() const { return 99; }; }; #endif @@ -1115,65 +1243,62 @@ public: class TMatrioskaStrokeStyle; -class TMatrioskaStrokeProp : public TStrokeProp -{ - +class TMatrioskaStrokeProp : public TStrokeProp { protected: - double m_outlinePixelSize; - TMatrioskaStrokeStyle *m_colorStyle; + double m_outlinePixelSize; + TMatrioskaStrokeStyle *m_colorStyle; - std::vector m_outline; + std::vector m_outline; - std::vector m_appStrokes; + std::vector m_appStrokes; public: - TMatrioskaStrokeProp(const TStroke *stroke, TMatrioskaStrokeStyle *style); - ~TMatrioskaStrokeProp(); + TMatrioskaStrokeProp(const TStroke *stroke, TMatrioskaStrokeStyle *style); + ~TMatrioskaStrokeProp(); - const TColorStyle *getColorStyle() const; + const TColorStyle *getColorStyle() const; - TStrokeProp *clone(const TStroke *stroke) const; - void draw(const TVectorRenderData &rd); - void draw(TFlash &flash); + TStrokeProp *clone(const TStroke *stroke) const; + void draw(const TVectorRenderData &rd); + void draw(TFlash &flash); }; -class TMatrioskaStrokeStyle : public TSolidColorStyle -{ - double m_parameter; - TPixel32 m_color2; +class TMatrioskaStrokeStyle : public TSolidColorStyle { + double m_parameter; + TPixel32 m_color2; protected: - void loadData(TInputStreamInterface &is); - void saveData(TOutputStreamInterface &os) const; + void loadData(TInputStreamInterface &is); + void saveData(TOutputStreamInterface &os) const; public: - TMatrioskaStrokeStyle( - TPixel32 color1 = TPixel32::Magenta, - TPixel32 color2 = TPixel32::Blue, - double parameter = 6.0, - bool alternate = true); + TMatrioskaStrokeStyle(TPixel32 color1 = TPixel32::Magenta, + TPixel32 color2 = TPixel32::Blue, + double parameter = 6.0, bool alternate = true); - TColorStyle *clone() const; + TColorStyle *clone() const; - int getColorParamCount() const { return 2; } - TPixel32 getColorParamValue(int index) const; - void setColorParamValue(int index, const TPixel32 &color); + int getColorParamCount() const { return 2; } + TPixel32 getColorParamValue(int index) const; + void setColorParamValue(int index, const TPixel32 &color); - int getParamCount() const; - TColorStyle::ParamType getParamType(int index) const; + int getParamCount() const; + TColorStyle::ParamType getParamType(int index) const; - QString getParamNames(int index) const; - void getParamRange(int index, double &min, double &max) const; - double getParamValue(TColorStyle::double_tag, int index) const; - void setParamValue(int index, double value); + QString getParamNames(int index) const; + void getParamRange(int index, double &min, double &max) const; + double getParamValue(TColorStyle::double_tag, int index) const; + void setParamValue(int index, double value); - TStrokeProp *makeStrokeProp(const TStroke *stroke); + TStrokeProp *makeStrokeProp(const TStroke *stroke); - bool isRegionStyle() const { return false; } - bool isStrokeStyle() const { return true; } + bool isRegionStyle() const { return false; } + bool isStrokeStyle() const { return true; } - QString getDescription() const { return QCoreApplication::translate("TMatrioskaStrokeStyle", "Toothpaste"); } - int getTagId() const { return 141; }; + QString getDescription() const { + return QCoreApplication::translate("TMatrioskaStrokeStyle", "Toothpaste"); + } + int getTagId() const { return 141; }; }; -#endif // STROKESTYLES_H +#endif // STROKESTYLES_H diff --git a/toonz/sources/colorfx/zigzagstyles.cpp b/toonz/sources/colorfx/zigzagstyles.cpp index d870e78..d0c72ff 100644 --- a/toonz/sources/colorfx/zigzagstyles.cpp +++ b/toonz/sources/colorfx/zigzagstyles.cpp @@ -9,175 +9,165 @@ #ifdef POICIPENSO TZigzagStrokeStyle::TZigzagStrokeStyle(const TPixel32 &color) - : m_color(color), m_density(0.5) -{ -} + : m_color(color), m_density(0.5) {} //----------------------------------------------------------------------------- TZigzagStrokeStyle::TZigzagStrokeStyle() - : m_color(TPixel32(0, 0, 0, 255)), m_density(0.5) -{ -} + : m_color(TPixel32(0, 0, 0, 255)), m_density(0.5) {} //----------------------------------------------------------------------------- -void TZigzagStrokeStyle::draw(double pixelSize, const TColorFunction *) -{ - // Distance between sampling points - const double minDist = 0.5; - const double maxDist = 6.0; - // Rotation angle of tangent - const int minRotAngle = 0; - const int maxRotAngle = 10; - // e.g minimum translation length is the half of the thickness - const double minTranslLength = 0.7; - - TStroke *stroke = getStroke(); - if (!stroke) - return; - double length = stroke->getLength(); - if (length <= 0) - return; - - int count = (int)(length / (minDist + (maxDist - minDist) * (1.0 - m_density)) + 1); - double dist = length / count; - - TRandom rnd; - // glEnable(GL_BLEND); - tglColor(m_color); - glBegin(GL_LINE_STRIP); - int first = 1; - for (double s = 0; s < (length + dist); s += dist, first = -first) { - double w = stroke->getParameterAtLength(s); - TThickPoint pos = stroke->getThickPoint(w); - TPointD u = stroke->getSpeed(w); - if (norm2(u) < TConsts::epsilon) - continue; - u = normalize(u); - int angle = rnd.getInt(minRotAngle, maxRotAngle); - TRotation rotM(angle); - u = rotM * u; - double maxTranslLength = angle == 90 ? 1.0 : 2.0; - if (angle > 30 && angle < 90) { - double rta = 1.0 / tan(degree2rad(angle)); - maxTranslLength = sqrt(sq(rta) + 1.0); - } - double r = (minTranslLength + (maxTranslLength - minTranslLength) * rnd.getDouble()) * pos.thick * first; - glVertex(pos + r * u); - } - glEnd(); - // glDisable(GL_BLEND); - // glColor4d(0,0,0,1); +void TZigzagStrokeStyle::draw(double pixelSize, const TColorFunction *) { + // Distance between sampling points + const double minDist = 0.5; + const double maxDist = 6.0; + // Rotation angle of tangent + const int minRotAngle = 0; + const int maxRotAngle = 10; + // e.g minimum translation length is the half of the thickness + const double minTranslLength = 0.7; + + TStroke *stroke = getStroke(); + if (!stroke) return; + double length = stroke->getLength(); + if (length <= 0) return; + + int count = + (int)(length / (minDist + (maxDist - minDist) * (1.0 - m_density)) + 1); + double dist = length / count; + + TRandom rnd; + // glEnable(GL_BLEND); + tglColor(m_color); + glBegin(GL_LINE_STRIP); + int first = 1; + for (double s = 0; s < (length + dist); s += dist, first = -first) { + double w = stroke->getParameterAtLength(s); + TThickPoint pos = stroke->getThickPoint(w); + TPointD u = stroke->getSpeed(w); + if (norm2(u) < TConsts::epsilon) continue; + u = normalize(u); + int angle = rnd.getInt(minRotAngle, maxRotAngle); + TRotation rotM(angle); + u = rotM * u; + double maxTranslLength = angle == 90 ? 1.0 : 2.0; + if (angle > 30 && angle < 90) { + double rta = 1.0 / tan(degree2rad(angle)); + maxTranslLength = sqrt(sq(rta) + 1.0); + } + double r = (minTranslLength + + (maxTranslLength - minTranslLength) * rnd.getDouble()) * + pos.thick * first; + glVertex(pos + r * u); + } + glEnd(); + // glDisable(GL_BLEND); + // glColor4d(0,0,0,1); } //----------------------------------------------------------------------------- -void TZigzagStrokeStyle::changeParameter(double delta) -{ - m_density = tcrop(m_density + delta, 0.0, 1.0); +void TZigzagStrokeStyle::changeParameter(double delta) { + m_density = tcrop(m_density + delta, 0.0, 1.0); } //----------------------------------------------------------------------------- -TStrokeStyle *TZigzagStrokeStyle::clone() const -{ - TColorStyle *cs = new TZigzagStrokeStyle(*this); - cs->assignNames(this); - return cs; +TStrokeStyle *TZigzagStrokeStyle::clone() const { + TColorStyle *cs = new TZigzagStrokeStyle(*this); + cs->assignNames(this); + return cs; } //============================================================================= -TImageBasedZigzagStrokeStyle::TImageBasedZigzagStrokeStyle(const TPixel32 &color) - : m_color(color), m_textScale(1.0), m_texture(0) +TImageBasedZigzagStrokeStyle::TImageBasedZigzagStrokeStyle( + const TPixel32 &color) + : m_color(color) + , m_textScale(1.0) + , m_texture(0) -{ -} +{} //----------------------------------------------------------------------------- TImageBasedZigzagStrokeStyle::TImageBasedZigzagStrokeStyle() - : m_color(TPixel32(0, 0, 0, 255)), m_textScale(1.0), m_texture(0) -{ -} + : m_color(TPixel32(0, 0, 0, 255)), m_textScale(1.0), m_texture(0) {} //----------------------------------------------------------------------------- -TImageBasedZigzagStrokeStyle::TImageBasedZigzagStrokeStyle(const TRaster32P texture) - : m_color(TPixel32(0, 0, 0, 255)), m_textScale(1.0), m_texture(texture) -{ -} +TImageBasedZigzagStrokeStyle::TImageBasedZigzagStrokeStyle( + const TRaster32P texture) + : m_color(TPixel32(0, 0, 0, 255)), m_textScale(1.0), m_texture(texture) {} //----------------------------------------------------------------------------- -inline int TImageBasedZigzagStrokeStyle::realTextCoord(const int a, const int l) const -{ - return a == 0 ? 0 : (a > 0 ? a % l : l - 1 - ((-a) % l)); +inline int TImageBasedZigzagStrokeStyle::realTextCoord(const int a, + const int l) const { + return a == 0 ? 0 : (a > 0 ? a % l : l - 1 - ((-a) % l)); } //----------------------------------------------------------------------------- -void TImageBasedZigzagStrokeStyle::draw(double pixelSize, const TColorFunction *) -{ - // Distance between sampling points - const double dist = 1.0; - // Scaling of texture - double recScale = fabs(m_textScale) < TConsts::epsilon ? 1.0 : 1.0 / m_textScale; - - TStroke *stroke = getStroke(); - if (!stroke) - return; - double length = stroke->getLength(); - if (length <= 0) - return; - - TRandom rnd; - // glEnable(GL_BLEND); - glColor(m_color); - glBegin(GL_LINE_STRIP); - TPointD textC = m_texture->getCenterD(); - TRectD strokeBB = stroke->getBBox(); - TPointD strokeC((strokeBB.x0 + strokeBB.x1) / 2, (strokeBB.y0 + strokeBB.y1) / 2); - for (double s = 0; s < (length + dist); s += dist) { - double w = stroke->getParameterAtLength(s); - TThickPoint pos = stroke->getThickPoint(w); - TPointD textPos((pos.x - strokeC.x) * recScale + textC.x, (pos.y - strokeC.y) * recScale + textC.y); - TPointD u = stroke->getSpeed(w); - if (norm2(u) == 0) - continue; - u = normalize(u); - - TPoint iTextPos(tround(textPos.x), tround(textPos.y)); - iTextPos.x = realTextCoord(iTextPos.x, m_texture->getLx()); - iTextPos.y = realTextCoord(iTextPos.y, m_texture->getLy()); - TPixel32 color = m_texture->pixels(iTextPos.y)[iTextPos.x]; - double ch, cl, cs; - RGB2HLS(color.r / 255.0, color.g / 255.0, color.b / 255.0, &ch, &cl, &cs); - TRotation rotM(tround(ch)); - u = rotM * u; - double r = cl * pos.thick; - glVertex(pos + r * u); - } - glEnd(); - // glDisable(GL_BLEND); - // glColor4d(0,0,0,1); +void TImageBasedZigzagStrokeStyle::draw(double pixelSize, + const TColorFunction *) { + // Distance between sampling points + const double dist = 1.0; + // Scaling of texture + double recScale = + fabs(m_textScale) < TConsts::epsilon ? 1.0 : 1.0 / m_textScale; + + TStroke *stroke = getStroke(); + if (!stroke) return; + double length = stroke->getLength(); + if (length <= 0) return; + + TRandom rnd; + // glEnable(GL_BLEND); + glColor(m_color); + glBegin(GL_LINE_STRIP); + TPointD textC = m_texture->getCenterD(); + TRectD strokeBB = stroke->getBBox(); + TPointD strokeC((strokeBB.x0 + strokeBB.x1) / 2, + (strokeBB.y0 + strokeBB.y1) / 2); + for (double s = 0; s < (length + dist); s += dist) { + double w = stroke->getParameterAtLength(s); + TThickPoint pos = stroke->getThickPoint(w); + TPointD textPos((pos.x - strokeC.x) * recScale + textC.x, + (pos.y - strokeC.y) * recScale + textC.y); + TPointD u = stroke->getSpeed(w); + if (norm2(u) == 0) continue; + u = normalize(u); + + TPoint iTextPos(tround(textPos.x), tround(textPos.y)); + iTextPos.x = realTextCoord(iTextPos.x, m_texture->getLx()); + iTextPos.y = realTextCoord(iTextPos.y, m_texture->getLy()); + TPixel32 color = m_texture->pixels(iTextPos.y)[iTextPos.x]; + double ch, cl, cs; + RGB2HLS(color.r / 255.0, color.g / 255.0, color.b / 255.0, &ch, &cl, &cs); + TRotation rotM(tround(ch)); + u = rotM * u; + double r = cl * pos.thick; + glVertex(pos + r * u); + } + glEnd(); + // glDisable(GL_BLEND); + // glColor4d(0,0,0,1); } //----------------------------------------------------------------------------- -void TImageBasedZigzagStrokeStyle::changeParameter(double delta) -{ - m_textScale = tcrop(m_textScale + delta, 0.1, 2.5); +void TImageBasedZigzagStrokeStyle::changeParameter(double delta) { + m_textScale = tcrop(m_textScale + delta, 0.1, 2.5); } //----------------------------------------------------------------------------- -TStrokeStyle *TImageBasedZigzagStrokeStyle::clone() const -{ - TColorStyle *cs = new TImageBasedZigzagStrokeStyle(*this); - cs->assignNames(this); - return cs; +TStrokeStyle *TImageBasedZigzagStrokeStyle::clone() const { + TColorStyle *cs = new TImageBasedZigzagStrokeStyle(*this); + cs->assignNames(this); + return cs; } #endif diff --git a/toonz/sources/colorfx/zigzagstyles.h b/toonz/sources/colorfx/zigzagstyles.h index 3b4d4c8..6d55a5c 100644 --- a/toonz/sources/colorfx/zigzagstyles.h +++ b/toonz/sources/colorfx/zigzagstyles.h @@ -7,67 +7,65 @@ #ifdef POICIPENSO -class TZigzagStrokeStyle : public TStrokeStyle -{ - TPixel32 m_color; - double m_density; +class TZigzagStrokeStyle : public TStrokeStyle { + TPixel32 m_color; + double m_density; public: - TZigzagStrokeStyle(const TPixel32 &color); - TZigzagStrokeStyle(); + TZigzagStrokeStyle(const TPixel32 &color); + TZigzagStrokeStyle(); - void invalidate() {} + void invalidate() {} - void changeParameter(double delta); - TStrokeStyle *clone() const; + void changeParameter(double delta); + TStrokeStyle *clone() const; - void draw(double pixelSize, const TColorFunction * = 0); + void draw(double pixelSize, const TColorFunction * = 0); - void loadData(TInputStreamInterface &is) { is >> m_color >> m_density; } - void saveData(TOutputStreamInterface &os) const { os << m_color << m_density; } - bool isSaveSupported() { return true; } + void loadData(TInputStreamInterface &is) { is >> m_color >> m_density; } + void saveData(TOutputStreamInterface &os) const { + os << m_color << m_density; + } + bool isSaveSupported() { return true; } - int getTagId() const { return 115; }; - bool operator==(const TStrokeStyle &style) const - { - if (getTagId() != style.getTagId()) - return false; - return m_color == ((TZigzagStrokeStyle &)style).m_color && - m_density == ((TZigzagStrokeStyle &)style).m_density; - } + int getTagId() const { return 115; }; + bool operator==(const TStrokeStyle &style) const { + if (getTagId() != style.getTagId()) return false; + return m_color == ((TZigzagStrokeStyle &)style).m_color && + m_density == ((TZigzagStrokeStyle &)style).m_density; + } }; -class TImageBasedZigzagStrokeStyle : public TStrokeStyle -{ - TPixel32 m_color; - double m_textScale; - TRaster32P m_texture; +class TImageBasedZigzagStrokeStyle : public TStrokeStyle { + TPixel32 m_color; + double m_textScale; + TRaster32P m_texture; public: - TImageBasedZigzagStrokeStyle(const TPixel32 &color); - TImageBasedZigzagStrokeStyle(); - TImageBasedZigzagStrokeStyle(const TRaster32P texture); - - void invalidate() {} - inline int realTextCoord(const int a, const int l) const; - - void changeParameter(double delta); - TStrokeStyle *clone() const; - - void draw(double pixelSize, const TColorFunction * = 0); - - void loadData(TInputStreamInterface &is) { is >> m_color >> m_textScale; } - void saveData(TOutputStreamInterface &os) const { os << m_color << m_textScale; } - bool isSaveSupported() { return true; } - - int getTagId() const { return 116; }; - bool operator==(const TStrokeStyle &style) const - { - if (getTagId() != style.getTagId()) - return false; - return m_color == ((TImageBasedZigzagStrokeStyle &)style).m_color && - m_textScale == ((TImageBasedZigzagStrokeStyle &)style).m_textScale; - } + TImageBasedZigzagStrokeStyle(const TPixel32 &color); + TImageBasedZigzagStrokeStyle(); + TImageBasedZigzagStrokeStyle(const TRaster32P texture); + + void invalidate() {} + inline int realTextCoord(const int a, const int l) const; + + void changeParameter(double delta); + TStrokeStyle *clone() const; + + void draw(double pixelSize, const TColorFunction * = 0); + + void loadData(TInputStreamInterface &is) { is >> m_color >> m_textScale; } + void saveData(TOutputStreamInterface &os) const { + os << m_color << m_textScale; + } + bool isSaveSupported() { return true; } + + int getTagId() const { return 116; }; + bool operator==(const TStrokeStyle &style) const { + if (getTagId() != style.getTagId()) return false; + return m_color == ((TImageBasedZigzagStrokeStyle &)style).m_color && + m_textScale == ((TImageBasedZigzagStrokeStyle &)style).m_textScale; + } }; #endif diff --git a/toonz/sources/common/expressions/texpression.cpp b/toonz/sources/common/expressions/texpression.cpp index 8c6ffc5..f5df42d 100644 --- a/toonz/sources/common/expressions/texpression.cpp +++ b/toonz/sources/common/expressions/texpression.cpp @@ -13,200 +13,176 @@ using namespace TSyntax; // TExpression::Imp definition //********************************************************************************** -class TExpression::Imp -{ +class TExpression::Imp { public: - const Grammar *m_grammar; //!< (not owned) The expression's grammar - TDoubleParam *m_param; //!< (not owned) The expression's owner - Calculator *m_calculator; //!< (owned) Expression calculator object + const Grammar *m_grammar; //!< (not owned) The expression's grammar + TDoubleParam *m_param; //!< (not owned) The expression's owner + Calculator *m_calculator; //!< (owned) Expression calculator object - std::string m_text; //!< Text content + std::string m_text; //!< Text content - std::string m_error; //!< Description of an error in the expression's text - std::pair m_errorPos; //!< Position of the error in the expression's text + std::string m_error; //!< Description of an error in the expression's text + std::pair + m_errorPos; //!< Position of the error in the expression's text - bool m_isValid, //!< Whether the expression is valid - m_hasBeenParsed; //!< Whether the expression has already been parsed + bool m_isValid, //!< Whether the expression is valid + m_hasBeenParsed; //!< Whether the expression has already been parsed public: - Imp() : m_grammar(0), m_param(0), m_calculator(0), m_errorPos(0, -1), m_isValid(false), m_hasBeenParsed(true) {} - ~Imp() { delete m_calculator; } + Imp() + : m_grammar(0) + , m_param(0) + , m_calculator(0) + , m_errorPos(0, -1) + , m_isValid(false) + , m_hasBeenParsed(true) {} + ~Imp() { delete m_calculator; } }; //********************************************************************************** // TExpression implementation //********************************************************************************** -TExpression::TExpression() - : m_imp(new Imp()) -{ -} +TExpression::TExpression() : m_imp(new Imp()) {} //-------------------------------------------------------------------------- -TExpression::~TExpression() -{ -} +TExpression::~TExpression() {} //-------------------------------------------------------------------------- -TExpression::TExpression(const TExpression &src) - : m_imp(new Imp()) -{ - m_imp->m_grammar = src.m_imp->m_grammar; - m_imp->m_param = src.m_imp->m_param; - m_imp->m_text = src.m_imp->m_text; - m_imp->m_calculator = 0; - m_imp->m_isValid = src.m_imp->m_isValid; - m_imp->m_error = src.m_imp->m_error; - m_imp->m_errorPos = src.m_imp->m_errorPos; - m_imp->m_hasBeenParsed = false; +TExpression::TExpression(const TExpression &src) : m_imp(new Imp()) { + m_imp->m_grammar = src.m_imp->m_grammar; + m_imp->m_param = src.m_imp->m_param; + m_imp->m_text = src.m_imp->m_text; + m_imp->m_calculator = 0; + m_imp->m_isValid = src.m_imp->m_isValid; + m_imp->m_error = src.m_imp->m_error; + m_imp->m_errorPos = src.m_imp->m_errorPos; + m_imp->m_hasBeenParsed = false; } //-------------------------------------------------------------------------- -TExpression &TExpression::operator=(TExpression copy) -{ - std::swap(copy.m_imp, m_imp); - return *this; +TExpression &TExpression::operator=(TExpression copy) { + std::swap(copy.m_imp, m_imp); + return *this; } //-------------------------------------------------------------------------- -void TExpression::setGrammar(const TSyntax::Grammar *grammar) -{ - m_imp->m_grammar = grammar; - m_imp->m_hasBeenParsed = false; +void TExpression::setGrammar(const TSyntax::Grammar *grammar) { + m_imp->m_grammar = grammar; + m_imp->m_hasBeenParsed = false; } //-------------------------------------------------------------------------- -const TSyntax::Grammar *TExpression::getGrammar() const -{ - return m_imp->m_grammar; +const TSyntax::Grammar *TExpression::getGrammar() const { + return m_imp->m_grammar; } //-------------------------------------------------------------------------- -void TExpression::setText(std::string text) -{ - if (m_imp->m_text != text) { - m_imp->m_text = text; - delete m_imp->m_calculator; - m_imp->m_calculator = 0; - m_imp->m_isValid = false; - m_imp->m_hasBeenParsed = false; - m_imp->m_error = ""; - m_imp->m_errorPos = std::make_pair(0, -1); - } +void TExpression::setText(std::string text) { + if (m_imp->m_text != text) { + m_imp->m_text = text; + delete m_imp->m_calculator; + m_imp->m_calculator = 0; + m_imp->m_isValid = false; + m_imp->m_hasBeenParsed = false; + m_imp->m_error = ""; + m_imp->m_errorPos = std::make_pair(0, -1); + } } //-------------------------------------------------------------------------- -std::string TExpression::getText() const -{ - return m_imp->m_text; -} +std::string TExpression::getText() const { return m_imp->m_text; } //-------------------------------------------------------------------------- // note: unit is used by the CycleNode node only -TSyntax::Calculator *TExpression::getCalculator() -{ - if (!m_imp->m_hasBeenParsed) - parse(); - if (m_imp->m_isValid && m_imp->m_calculator) - return m_imp->m_calculator; - else - return 0; +TSyntax::Calculator *TExpression::getCalculator() { + if (!m_imp->m_hasBeenParsed) parse(); + if (m_imp->m_isValid && m_imp->m_calculator) + return m_imp->m_calculator; + else + return 0; } //-------------------------------------------------------------------------- -bool TExpression::isValid() -{ - if (!m_imp->m_hasBeenParsed) - parse(); - return m_imp->m_isValid; +bool TExpression::isValid() { + if (!m_imp->m_hasBeenParsed) parse(); + return m_imp->m_isValid; } //-------------------------------------------------------------------------- -std::string TExpression::getError() const -{ - return m_imp->m_error; -} +std::string TExpression::getError() const { return m_imp->m_error; } //-------------------------------------------------------------------------- -std::pair TExpression::getErrorPos() const -{ - return m_imp->m_errorPos; +std::pair TExpression::getErrorPos() const { + return m_imp->m_errorPos; } //-------------------------------------------------------------------------- -void TExpression::accept(TSyntax::CalculatorNodeVisitor &visitor) -{ - if (!m_imp->m_hasBeenParsed) - parse(); - if (m_imp->m_isValid && m_imp->m_calculator) - m_imp->m_calculator->accept(visitor); +void TExpression::accept(TSyntax::CalculatorNodeVisitor &visitor) { + if (!m_imp->m_hasBeenParsed) parse(); + if (m_imp->m_isValid && m_imp->m_calculator) + m_imp->m_calculator->accept(visitor); } //-------------------------------------------------------------------------- -void TExpression::parse() -{ - delete m_imp->m_calculator; - m_imp->m_calculator = 0; +void TExpression::parse() { + delete m_imp->m_calculator; + m_imp->m_calculator = 0; - m_imp->m_errorPos = std::make_pair(0, -1); - m_imp->m_error = std::string(); + m_imp->m_errorPos = std::make_pair(0, -1); + m_imp->m_error = std::string(); - if (!m_imp->m_grammar) { - m_imp->m_error = "No grammar defined"; - m_imp->m_isValid = false; - } else { - Parser parser(m_imp->m_grammar); + if (!m_imp->m_grammar) { + m_imp->m_error = "No grammar defined"; + m_imp->m_isValid = false; + } else { + Parser parser(m_imp->m_grammar); - m_imp->m_calculator = parser.parse(m_imp->m_text); + m_imp->m_calculator = parser.parse(m_imp->m_text); - if (m_imp->m_calculator) - m_imp->m_calculator->setOwnerParameter(m_imp->m_param); + if (m_imp->m_calculator) + m_imp->m_calculator->setOwnerParameter(m_imp->m_param); - m_imp->m_isValid = parser.isValid(); + m_imp->m_isValid = parser.isValid(); - if (!m_imp->m_isValid) { - m_imp->m_error = parser.getError(); - m_imp->m_errorPos = parser.getErrorPos(); - } - } + if (!m_imp->m_isValid) { + m_imp->m_error = parser.getError(); + m_imp->m_errorPos = parser.getErrorPos(); + } + } - m_imp->m_hasBeenParsed = true; + m_imp->m_hasBeenParsed = true; } //-------------------------------------------------------------------------- -void TExpression::setOwnerParameter(TDoubleParam *param) -{ - m_imp->m_param = param; +void TExpression::setOwnerParameter(TDoubleParam *param) { + m_imp->m_param = param; - if (m_imp->m_calculator) - m_imp->m_calculator->setOwnerParameter(param); + if (m_imp->m_calculator) m_imp->m_calculator->setOwnerParameter(param); } //-------------------------------------------------------------------------- -TDoubleParam *TExpression::getOwnerParameter() const -{ - return m_imp->m_param; -} +TDoubleParam *TExpression::getOwnerParameter() const { return m_imp->m_param; } //-------------------------------------------------------------------------- -bool TExpression::isCycling() const -{ - // TODO: this is a quick&dirty implementation to be replaced with a more "semantic" one - return getText().find("cycle") != std::string::npos; +bool TExpression::isCycling() const { + // TODO: this is a quick&dirty implementation to be replaced with a more + // "semantic" one + return getText().find("cycle") != std::string::npos; } diff --git a/toonz/sources/common/expressions/tgrammar.cpp b/toonz/sources/common/expressions/tgrammar.cpp index 9fbacff..bc142fc 100644 --- a/toonz/sources/common/expressions/tgrammar.cpp +++ b/toonz/sources/common/expressions/tgrammar.cpp @@ -27,8 +27,7 @@ const double PI = 4 * atan(1.0); const double toDeg(double rad) { return rad * 180.0 / PI; } const double toRad(double deg) { return deg / 180.0 * PI; } -namespace TSyntax -{ +namespace TSyntax { //=================================================================== // @@ -38,86 +37,72 @@ namespace TSyntax // //------------------------------------------------------------------- -class RandomSequence -{ - TRandom m_rnd; - std::vector m_values; +class RandomSequence { + TRandom m_rnd; + std::vector m_values; public: - RandomSequence(UINT seed) : m_rnd(seed) {} - double getValue(int i) - { - assert(i >= 0); - if (i >= (int)m_values.size()) { - m_values.reserve(i + 1); - while (i >= (int)m_values.size()) - m_values.push_back(m_rnd.getDouble()); - } - return m_values[i]; - } + RandomSequence(UINT seed) : m_rnd(seed) {} + double getValue(int i) { + assert(i >= 0); + if (i >= (int)m_values.size()) { + m_values.reserve(i + 1); + while (i >= (int)m_values.size()) m_values.push_back(m_rnd.getDouble()); + } + return m_values[i]; + } }; //------------------------------------------------------------------- -class RandomManager -{ // singleton - typedef std::map Table; - Table m_table; - RandomManager() {} -public: - ~RandomManager() - { - for (Table::iterator i = m_table.begin(); i != m_table.end(); ++i) - delete i->second; - } - static RandomManager *instance() - { - static RandomManager _instance; - return &_instance; - } - - RandomSequence *getSequence(UINT seed) - { - Table::iterator i = m_table.find(seed); - if (i == m_table.end()) { - RandomSequence *seq = new RandomSequence(seed); - m_table[seed] = seq; - return seq; - } else - return i->second; - } - - double getValue(UINT seed, double t) - { - RandomSequence *seq = getSequence(seed); - return seq->getValue(t > 0 ? tfloor(t) : 0); - } +class RandomManager { // singleton + typedef std::map Table; + Table m_table; + RandomManager() {} + +public: + ~RandomManager() { + for (Table::iterator i = m_table.begin(); i != m_table.end(); ++i) + delete i->second; + } + static RandomManager *instance() { + static RandomManager _instance; + return &_instance; + } + + RandomSequence *getSequence(UINT seed) { + Table::iterator i = m_table.find(seed); + if (i == m_table.end()) { + RandomSequence *seq = new RandomSequence(seed); + m_table[seed] = seq; + return seq; + } else + return i->second; + } + + double getValue(UINT seed, double t) { + RandomSequence *seq = getSequence(seed); + return seq->getValue(t > 0 ? tfloor(t) : 0); + } }; //=================================================================== // Calculator //------------------------------------------------------------------- -Calculator::Calculator() - : m_rootNode(0), m_param(0), m_unit(0) -{ -} +Calculator::Calculator() : m_rootNode(0), m_param(0), m_unit(0) {} //------------------------------------------------------------------- -Calculator::~Calculator() -{ - delete m_rootNode; -} +Calculator::~Calculator() { delete m_rootNode; } //------------------------------------------------------------------- -void Calculator::setRootNode(CalculatorNode *node) -{ - if (node != m_rootNode) { - delete m_rootNode; - m_rootNode = node; - } +void Calculator::setRootNode(CalculatorNode *node) { + if (node != m_rootNode) { + delete m_rootNode; + m_rootNode = node; + } } //=================================================================== @@ -125,883 +110,795 @@ void Calculator::setRootNode(CalculatorNode *node) //------------------------------------------------------------------- template -class Op0Node : public CalculatorNode -{ +class Op0Node : public CalculatorNode { public: - Op0Node(Calculator *calc) - : CalculatorNode(calc) {} + Op0Node(Calculator *calc) : CalculatorNode(calc) {} - double compute(double vars[3]) const - { - Op op; - return op(); - } + double compute(double vars[3]) const { + Op op; + return op(); + } }; //------------------------------------------------------------------- template -class Op1Node : public CalculatorNode -{ +class Op1Node : public CalculatorNode { protected: - std::auto_ptr m_a; + std::auto_ptr m_a; public: - Op1Node(Calculator *calc, CalculatorNode *a) - : CalculatorNode(calc), m_a(a) {} + Op1Node(Calculator *calc, CalculatorNode *a) : CalculatorNode(calc), m_a(a) {} - double compute(double vars[3]) const - { - Op op; - return op(m_a->compute(vars)); - } + double compute(double vars[3]) const { + Op op; + return op(m_a->compute(vars)); + } - void accept(CalculatorNodeVisitor &visitor) { m_a->accept(visitor); } + void accept(CalculatorNodeVisitor &visitor) { m_a->accept(visitor); } }; //------------------------------------------------------------------- template -class Op2Node : public CalculatorNode -{ +class Op2Node : public CalculatorNode { protected: - std::auto_ptr m_a, m_b; + std::auto_ptr m_a, m_b; public: - Op2Node(Calculator *calc, CalculatorNode *a, CalculatorNode *b) - : CalculatorNode(calc), m_a(a), m_b(b) {} + Op2Node(Calculator *calc, CalculatorNode *a, CalculatorNode *b) + : CalculatorNode(calc), m_a(a), m_b(b) {} - double compute(double vars[3]) const - { - Op op; - return op(m_a->compute(vars), m_b->compute(vars)); - } + double compute(double vars[3]) const { + Op op; + return op(m_a->compute(vars), m_b->compute(vars)); + } - void accept(CalculatorNodeVisitor &visitor) - { - m_a->accept(visitor), m_b->accept(visitor); - } + void accept(CalculatorNodeVisitor &visitor) { + m_a->accept(visitor), m_b->accept(visitor); + } }; //------------------------------------------------------------------- template -class Op3Node : public CalculatorNode -{ +class Op3Node : public CalculatorNode { protected: - std::auto_ptr m_a, m_b, m_c; + std::auto_ptr m_a, m_b, m_c; public: - Op3Node(Calculator *calc, CalculatorNode *a, CalculatorNode *b, CalculatorNode *c) - : CalculatorNode(calc), m_a(a), m_b(b), m_c(c) {} + Op3Node(Calculator *calc, CalculatorNode *a, CalculatorNode *b, + CalculatorNode *c) + : CalculatorNode(calc), m_a(a), m_b(b), m_c(c) {} - double compute(double vars[3]) const - { - Op op; - return op(m_a->compute(vars), m_b->compute(vars), m_c->compute(vars)); - } + double compute(double vars[3]) const { + Op op; + return op(m_a->compute(vars), m_b->compute(vars), m_c->compute(vars)); + } - void accept(CalculatorNodeVisitor &visitor) - { - m_a->accept(visitor), m_b->accept(visitor), m_c->accept(visitor); - } + void accept(CalculatorNodeVisitor &visitor) { + m_a->accept(visitor), m_b->accept(visitor), m_c->accept(visitor); + } }; //------------------------------------------------------------------- -class ChsNode : public CalculatorNode -{ - std::auto_ptr m_a; +class ChsNode : public CalculatorNode { + std::auto_ptr m_a; public: - ChsNode(Calculator *calc, CalculatorNode *a) : CalculatorNode(calc), m_a(a) {} + ChsNode(Calculator *calc, CalculatorNode *a) : CalculatorNode(calc), m_a(a) {} - double compute(double vars[3]) const { return -m_a->compute(vars); } - void accept(CalculatorNodeVisitor &visitor) { m_a->accept(visitor); } + double compute(double vars[3]) const { return -m_a->compute(vars); } + void accept(CalculatorNodeVisitor &visitor) { m_a->accept(visitor); } }; //------------------------------------------------------------------- -class QuestionNode : public CalculatorNode -{ - std::auto_ptr m_a, m_b, m_c; +class QuestionNode : public CalculatorNode { + std::auto_ptr m_a, m_b, m_c; public: - QuestionNode(Calculator *calc, CalculatorNode *a, CalculatorNode *b, CalculatorNode *c) - : CalculatorNode(calc), m_a(a), m_b(b), m_c(c) {} + QuestionNode(Calculator *calc, CalculatorNode *a, CalculatorNode *b, + CalculatorNode *c) + : CalculatorNode(calc), m_a(a), m_b(b), m_c(c) {} - double compute(double vars[3]) const - { - return (m_a->compute(vars) != 0) ? m_b->compute(vars) : m_c->compute(vars); - } + double compute(double vars[3]) const { + return (m_a->compute(vars) != 0) ? m_b->compute(vars) : m_c->compute(vars); + } - void accept(CalculatorNodeVisitor &visitor) - { - m_a->accept(visitor), m_b->accept(visitor), m_c->accept(visitor); - } + void accept(CalculatorNodeVisitor &visitor) { + m_a->accept(visitor), m_b->accept(visitor), m_c->accept(visitor); + } }; //------------------------------------------------------------------- -class NotNode : public CalculatorNode -{ - std::auto_ptr m_a; +class NotNode : public CalculatorNode { + std::auto_ptr m_a; public: - NotNode(Calculator *calc, CalculatorNode *a) : CalculatorNode(calc), m_a(a) {} + NotNode(Calculator *calc, CalculatorNode *a) : CalculatorNode(calc), m_a(a) {} - double compute(double vars[3]) const { return m_a->compute(vars) == 0; } - void accept(CalculatorNodeVisitor &visitor) { m_a->accept(visitor); } + double compute(double vars[3]) const { return m_a->compute(vars) == 0; } + void accept(CalculatorNodeVisitor &visitor) { m_a->accept(visitor); } }; //------------------------------------------------------------------- -class CycleNode : public CalculatorNode -{ - std::auto_ptr m_a; +class CycleNode : public CalculatorNode { + std::auto_ptr m_a; public: - CycleNode(Calculator *calc, CalculatorNode *a) : CalculatorNode(calc), m_a(a) {} + CycleNode(Calculator *calc, CalculatorNode *a) + : CalculatorNode(calc), m_a(a) {} - double compute(double vars[3]) const - { - struct locals { - static inline double compute(const TDoubleParam ¶m, double f) - { - if (param.getKeyframeCount() >= 2 && f < param.keyframeIndexToFrame(0)) { - TDoubleKeyframe kf = param.getKeyframe(0); - if (kf.m_type == TDoubleKeyframe::Expression || kf.m_type == TDoubleKeyframe::SimilarShape) - return param.getDefaultValue(); - } + double compute(double vars[3]) const { + struct locals { + static inline double compute(const TDoubleParam ¶m, double f) { + if (param.getKeyframeCount() >= 2 && + f < param.keyframeIndexToFrame(0)) { + TDoubleKeyframe kf = param.getKeyframe(0); + if (kf.m_type == TDoubleKeyframe::Expression || + kf.m_type == TDoubleKeyframe::SimilarShape) + return param.getDefaultValue(); + } - double value = param.getValue(f); - return value; - } - }; + double value = param.getValue(f); + return value; + } + }; - double delta = std::max(1.0, m_a->compute(vars)); + double delta = std::max(1.0, m_a->compute(vars)); - const TDoubleParam *ownerParam = getCalculator()->getOwnerParameter(); - if (!ownerParam) - return 0; + const TDoubleParam *ownerParam = getCalculator()->getOwnerParameter(); + if (!ownerParam) return 0; - double value = locals::compute(*ownerParam, vars[FRAME] - 1 - delta); - if (getCalculator()->getUnit()) - value = getCalculator()->getUnit()->convertTo(value); + double value = locals::compute(*ownerParam, vars[FRAME] - 1 - delta); + if (getCalculator()->getUnit()) + value = getCalculator()->getUnit()->convertTo(value); - return value; - } + return value; + } - void accept(CalculatorNodeVisitor &visitor) { m_a->accept(visitor); } + void accept(CalculatorNodeVisitor &visitor) { m_a->accept(visitor); } }; //------------------------------------------------------------------- -class RandomNode : public CalculatorNode -{ - std::auto_ptr m_seed, m_min, m_max, m_arg; - -public: - RandomNode(Calculator *calc) : CalculatorNode(calc), m_seed(0), m_min(0), m_max(0) - { - m_arg.reset(new VariableNode(calc, CalculatorNode::FRAME)); - } - - void setSeed(CalculatorNode *arg) - { - assert(m_seed.get() == 0); - m_seed.reset(arg); - } - void setMax(CalculatorNode *arg) - { - assert(m_max.get() == 0); - m_max.reset(arg); - } - void setMin(CalculatorNode *arg) - { - assert(m_min.get() == 0); - m_min.reset(arg); - } - - double compute(double vars[3]) const - { - double s = (m_seed.get() != 0) ? m_seed->compute(vars) : 0; - double r = RandomManager::instance()->getValue(s, fabs(m_arg->compute(vars))); - if (m_min.get() == 0) - if (m_max.get() == 0) - return r; - else - return m_max->compute(vars) * r; - else - return (1 - r) * m_min->compute(vars) + r * m_max->compute(vars); - } - - void accept(CalculatorNodeVisitor &visitor) - { - m_arg->accept(visitor); - if (m_seed.get()) - m_seed->accept(visitor); - if (m_min.get()) - m_min->accept(visitor); - if (m_max.get()) - m_max->accept(visitor); - } +class RandomNode : public CalculatorNode { + std::auto_ptr m_seed, m_min, m_max, m_arg; + +public: + RandomNode(Calculator *calc) + : CalculatorNode(calc), m_seed(0), m_min(0), m_max(0) { + m_arg.reset(new VariableNode(calc, CalculatorNode::FRAME)); + } + + void setSeed(CalculatorNode *arg) { + assert(m_seed.get() == 0); + m_seed.reset(arg); + } + void setMax(CalculatorNode *arg) { + assert(m_max.get() == 0); + m_max.reset(arg); + } + void setMin(CalculatorNode *arg) { + assert(m_min.get() == 0); + m_min.reset(arg); + } + + double compute(double vars[3]) const { + double s = (m_seed.get() != 0) ? m_seed->compute(vars) : 0; + double r = + RandomManager::instance()->getValue(s, fabs(m_arg->compute(vars))); + if (m_min.get() == 0) + if (m_max.get() == 0) + return r; + else + return m_max->compute(vars) * r; + else + return (1 - r) * m_min->compute(vars) + r * m_max->compute(vars); + } + + void accept(CalculatorNodeVisitor &visitor) { + m_arg->accept(visitor); + if (m_seed.get()) m_seed->accept(visitor); + if (m_min.get()) m_min->accept(visitor); + if (m_max.get()) m_max->accept(visitor); + } }; //=================================================================== // Patterns //------------------------------------------------------------------- -CalculatorNode *Pattern::popNode(std::vector &stack) const -{ - CalculatorNode *node = stack.back(); - stack.pop_back(); - return node; +CalculatorNode *Pattern::popNode(std::vector &stack) const { + CalculatorNode *node = stack.back(); + stack.pop_back(); + return node; } //=================================================================== -class NumberPattern : public Pattern -{ -public: - bool matchToken(const std::vector &previousTokens, const Token &token) const - { - return previousTokens.empty() && token.getType() == Token::Number; - } - bool isFinished(const std::vector &previousTokens, const Token &token) const - { - return previousTokens.size() == 1; - } - TokenType getTokenType(const std::vector &previousTokens, const Token &token) const - { - return Number; - } - void createNode( - Calculator *calc, - std::vector &stack, - const std::vector &tokens) const - { - assert(tokens.size() == 1); - assert(tokens[0].getType() == Token::Number); - stack.push_back(new NumberNode(calc, tokens[0].getDoubleValue())); - } +class NumberPattern : public Pattern { +public: + bool matchToken(const std::vector &previousTokens, + const Token &token) const { + return previousTokens.empty() && token.getType() == Token::Number; + } + bool isFinished(const std::vector &previousTokens, + const Token &token) const { + return previousTokens.size() == 1; + } + TokenType getTokenType(const std::vector &previousTokens, + const Token &token) const { + return Number; + } + void createNode(Calculator *calc, std::vector &stack, + const std::vector &tokens) const { + assert(tokens.size() == 1); + assert(tokens[0].getType() == Token::Number); + stack.push_back(new NumberNode(calc, tokens[0].getDoubleValue())); + } }; //------------------------------------------------------------------- -class ConstantPattern : public Pattern -{ - std::string m_constantName; - double m_value; - -public: - ConstantPattern(std::string constantName, double value, std::string description = "") - : m_constantName(constantName), m_value(value) - { - setDescription(description); - } - - std::string getFirstKeyword() const { return m_constantName; } - bool matchToken(const std::vector &previousTokens, const Token &token) const - { - return previousTokens.empty() && token.getText() == m_constantName; - } - bool isFinished(const std::vector &previousTokens, const Token &token) const - { - return previousTokens.size() == 1; - } - TokenType getTokenType(const std::vector &previousTokens, const Token &token) const - { - return Constant; - } - - void createNode( - Calculator *calc, - std::vector &stack, - const std::vector &tokens) const - { - assert(tokens.size() == 1); - stack.push_back(new NumberNode(calc, m_value)); - } +class ConstantPattern : public Pattern { + std::string m_constantName; + double m_value; + +public: + ConstantPattern(std::string constantName, double value, + std::string description = "") + : m_constantName(constantName), m_value(value) { + setDescription(description); + } + + std::string getFirstKeyword() const { return m_constantName; } + bool matchToken(const std::vector &previousTokens, + const Token &token) const { + return previousTokens.empty() && token.getText() == m_constantName; + } + bool isFinished(const std::vector &previousTokens, + const Token &token) const { + return previousTokens.size() == 1; + } + TokenType getTokenType(const std::vector &previousTokens, + const Token &token) const { + return Constant; + } + + void createNode(Calculator *calc, std::vector &stack, + const std::vector &tokens) const { + assert(tokens.size() == 1); + stack.push_back(new NumberNode(calc, m_value)); + } }; //------------------------------------------------------------------- -class VariablePattern : public Pattern -{ - std::string m_variableName; - int m_varIdx; - -public: - VariablePattern(std::string variableName, int varIdx, std::string description = "") - : m_variableName(variableName), m_varIdx(varIdx) - { - setDescription(description); - } - - std::string getFirstKeyword() const { return m_variableName; } - bool matchToken(const std::vector &previousTokens, const Token &token) const - { - return previousTokens.empty() && token.getText() == m_variableName; - } - bool isFinished(const std::vector &previousTokens, const Token &token) const - { - return previousTokens.size() == 1; - } - TokenType getTokenType(const std::vector &previousTokens, const Token &token) const - { - return Variable; - } - - void createNode( - Calculator *calc, - std::vector &stack, - const std::vector &tokens) const - { - assert(tokens.size() == 1); - assert(tokens[0].getText() == m_variableName); - stack.push_back(new VariableNode(calc, m_varIdx)); - } +class VariablePattern : public Pattern { + std::string m_variableName; + int m_varIdx; + +public: + VariablePattern(std::string variableName, int varIdx, + std::string description = "") + : m_variableName(variableName), m_varIdx(varIdx) { + setDescription(description); + } + + std::string getFirstKeyword() const { return m_variableName; } + bool matchToken(const std::vector &previousTokens, + const Token &token) const { + return previousTokens.empty() && token.getText() == m_variableName; + } + bool isFinished(const std::vector &previousTokens, + const Token &token) const { + return previousTokens.size() == 1; + } + TokenType getTokenType(const std::vector &previousTokens, + const Token &token) const { + return Variable; + } + + void createNode(Calculator *calc, std::vector &stack, + const std::vector &tokens) const { + assert(tokens.size() == 1); + assert(tokens[0].getText() == m_variableName); + stack.push_back(new VariableNode(calc, m_varIdx)); + } }; //------------------------------------------------------------------- template -class Op2Pattern : public Pattern -{ - std::string m_opName; - int m_priority; - -public: - Op2Pattern(std::string opName, int priority) - : m_opName(opName), m_priority(priority) {} - int getPriority() const { return m_priority; } - std::string getFirstKeyword() const { return m_opName; } - bool expressionExpected(const std::vector &previousTokens) const - { - return previousTokens.empty() || previousTokens.size() == 2; - } - bool matchToken(const std::vector &previousTokens, const Token &token) const - { - return previousTokens.size() == 1 && token.getText() == m_opName; - } - bool isFinished(const std::vector &previousTokens, const Token &token) const - { - return previousTokens.size() == 3; - } - TokenType getTokenType(const std::vector &previousTokens, const Token &token) const - { - return previousTokens.size() == 1 ? Operator : InternalError; - } - void createNode( - Calculator *calc, - std::vector &stack, - const std::vector &tokens) const - { - assert(tokens.size() == 3); - assert(tokens[1].getText() == m_opName); - CalculatorNode *b = popNode(stack); - CalculatorNode *a = popNode(stack); - stack.push_back(new Op2Node(calc, a, b)); - } +class Op2Pattern : public Pattern { + std::string m_opName; + int m_priority; + +public: + Op2Pattern(std::string opName, int priority) + : m_opName(opName), m_priority(priority) {} + int getPriority() const { return m_priority; } + std::string getFirstKeyword() const { return m_opName; } + bool expressionExpected(const std::vector &previousTokens) const { + return previousTokens.empty() || previousTokens.size() == 2; + } + bool matchToken(const std::vector &previousTokens, + const Token &token) const { + return previousTokens.size() == 1 && token.getText() == m_opName; + } + bool isFinished(const std::vector &previousTokens, + const Token &token) const { + return previousTokens.size() == 3; + } + TokenType getTokenType(const std::vector &previousTokens, + const Token &token) const { + return previousTokens.size() == 1 ? Operator : InternalError; + } + void createNode(Calculator *calc, std::vector &stack, + const std::vector &tokens) const { + assert(tokens.size() == 3); + assert(tokens[1].getText() == m_opName); + CalculatorNode *b = popNode(stack); + CalculatorNode *a = popNode(stack); + stack.push_back(new Op2Node(calc, a, b)); + } }; //------------------------------------------------------------------- -class UnaryMinusPattern : public Pattern -{ -public: - UnaryMinusPattern() {} - int getPriority() const { return 50; } - std::string getFirstKeyword() const { return "-"; } - - bool expressionExpected(const std::vector &previousTokens) const - { - return previousTokens.size() == 1; - } - bool matchToken(const std::vector &previousTokens, const Token &token) const - { - return previousTokens.empty() && token.getText() == "-"; - } - bool isFinished(const std::vector &previousTokens, const Token &token) const - { - return previousTokens.size() == 2; - } - TokenType getTokenType(const std::vector &previousTokens, const Token &token) const - { - return Operator; - } - - void createNode( - Calculator *calc, - std::vector &stack, - const std::vector &tokens) const - { - assert(tokens.size() == 2); - assert(tokens[0].getText() == "-"); - stack.push_back(new ChsNode(calc, popNode(stack))); - } +class UnaryMinusPattern : public Pattern { +public: + UnaryMinusPattern() {} + int getPriority() const { return 50; } + std::string getFirstKeyword() const { return "-"; } + + bool expressionExpected(const std::vector &previousTokens) const { + return previousTokens.size() == 1; + } + bool matchToken(const std::vector &previousTokens, + const Token &token) const { + return previousTokens.empty() && token.getText() == "-"; + } + bool isFinished(const std::vector &previousTokens, + const Token &token) const { + return previousTokens.size() == 2; + } + TokenType getTokenType(const std::vector &previousTokens, + const Token &token) const { + return Operator; + } + + void createNode(Calculator *calc, std::vector &stack, + const std::vector &tokens) const { + assert(tokens.size() == 2); + assert(tokens[0].getText() == "-"); + stack.push_back(new ChsNode(calc, popNode(stack))); + } }; //------------------------------------------------------------------- -class NotPattern : public Pattern -{ - std::string m_prefix; - -public: - NotPattern(std::string prefix, std::string description) : m_prefix(prefix) - { - setDescription(description); - } - int getPriority() const { return 5; } - std::string getFirstKeyword() const { return m_prefix; } - - bool expressionExpected(const std::vector &previousTokens) const - { - return previousTokens.size() == 1; - } - bool matchToken(const std::vector &previousTokens, const Token &token) const - { - return previousTokens.empty() && token.getText() == m_prefix; - } - bool isFinished(const std::vector &previousTokens, const Token &token) const - { - return previousTokens.size() == 2; - } - TokenType getTokenType(const std::vector &previousTokens, const Token &token) const - { - return Operator; - } - void createNode( - Calculator *calc, - std::vector &stack, - const std::vector &tokens) const - { - assert(tokens.size() == 2); - assert(tokens[0].getText() == m_prefix); - stack.push_back(new NotNode(calc, popNode(stack))); - } +class NotPattern : public Pattern { + std::string m_prefix; + +public: + NotPattern(std::string prefix, std::string description) : m_prefix(prefix) { + setDescription(description); + } + int getPriority() const { return 5; } + std::string getFirstKeyword() const { return m_prefix; } + + bool expressionExpected(const std::vector &previousTokens) const { + return previousTokens.size() == 1; + } + bool matchToken(const std::vector &previousTokens, + const Token &token) const { + return previousTokens.empty() && token.getText() == m_prefix; + } + bool isFinished(const std::vector &previousTokens, + const Token &token) const { + return previousTokens.size() == 2; + } + TokenType getTokenType(const std::vector &previousTokens, + const Token &token) const { + return Operator; + } + void createNode(Calculator *calc, std::vector &stack, + const std::vector &tokens) const { + assert(tokens.size() == 2); + assert(tokens[0].getText() == m_prefix); + stack.push_back(new NotNode(calc, popNode(stack))); + } }; //------------------------------------------------------------------- -class QuestionTernaryPattern : public Pattern -{ -public: - QuestionTernaryPattern() {} - int getPriority() const { return 5; } - std::string getFirstKeyword() const { return "?"; } - - bool expressionExpected(const std::vector &previousTokens) const - { - int i = (int)previousTokens.size(); - return i == 0 || i == 2 || i == 4; - } - bool matchToken(const std::vector &previousTokens, const Token &token) const - { - int i = (int)previousTokens.size(); - return i == 1 && token.getText() == "?" || i == 3 && token.getText() == ":"; - } - bool isFinished(const std::vector &previousTokens, const Token &token) const - { - return previousTokens.size() == 5; - } - TokenType getTokenType(const std::vector &previousTokens, const Token &token) const - { - int i = (int)previousTokens.size(); - return (i == 1 || i == 3) ? Operator : InternalError; - } - void createNode( - Calculator *calc, - std::vector &stack, - const std::vector &tokens) const - { - CalculatorNode *node1 = popNode(stack); - CalculatorNode *node2 = popNode(stack); - CalculatorNode *node3 = popNode(stack); - stack.push_back(new QuestionNode(calc, node3, node2, node1)); - } +class QuestionTernaryPattern : public Pattern { +public: + QuestionTernaryPattern() {} + int getPriority() const { return 5; } + std::string getFirstKeyword() const { return "?"; } + + bool expressionExpected(const std::vector &previousTokens) const { + int i = (int)previousTokens.size(); + return i == 0 || i == 2 || i == 4; + } + bool matchToken(const std::vector &previousTokens, + const Token &token) const { + int i = (int)previousTokens.size(); + return i == 1 && token.getText() == "?" || i == 3 && token.getText() == ":"; + } + bool isFinished(const std::vector &previousTokens, + const Token &token) const { + return previousTokens.size() == 5; + } + TokenType getTokenType(const std::vector &previousTokens, + const Token &token) const { + int i = (int)previousTokens.size(); + return (i == 1 || i == 3) ? Operator : InternalError; + } + void createNode(Calculator *calc, std::vector &stack, + const std::vector &tokens) const { + CalculatorNode *node1 = popNode(stack); + CalculatorNode *node2 = popNode(stack); + CalculatorNode *node3 = popNode(stack); + stack.push_back(new QuestionNode(calc, node3, node2, node1)); + } }; //------------------------------------------------------------------- -class BraketPattern : public Pattern -{ -public: - BraketPattern() {} - int getPriority() const { return 5; } - std::string getFirstKeyword() const { return "("; } - - bool expressionExpected(const std::vector &previousTokens) const - { - return previousTokens.size() == 1; - } - bool matchToken(const std::vector &previousTokens, const Token &token) const - { - return previousTokens.empty() && token.getText() == "(" || - previousTokens.size() == 2 && token.getText() == ")"; - } - bool isFinished(const std::vector &previousTokens, const Token &token) const - { - return previousTokens.size() == 3; - } - TokenType getTokenType(const std::vector &previousTokens, const Token &token) const - { - return previousTokens.size() != 1 ? Parenthesis : InternalError; - } - void createNode( - Calculator *calc, - std::vector &stack, - const std::vector &tokens) const - { - assert(tokens.size() == 3); - assert(tokens[0].getText() == "("); - assert(tokens[2].getText() == ")"); - } +class BraketPattern : public Pattern { +public: + BraketPattern() {} + int getPriority() const { return 5; } + std::string getFirstKeyword() const { return "("; } + + bool expressionExpected(const std::vector &previousTokens) const { + return previousTokens.size() == 1; + } + bool matchToken(const std::vector &previousTokens, + const Token &token) const { + return previousTokens.empty() && token.getText() == "(" || + previousTokens.size() == 2 && token.getText() == ")"; + } + bool isFinished(const std::vector &previousTokens, + const Token &token) const { + return previousTokens.size() == 3; + } + TokenType getTokenType(const std::vector &previousTokens, + const Token &token) const { + return previousTokens.size() != 1 ? Parenthesis : InternalError; + } + void createNode(Calculator *calc, std::vector &stack, + const std::vector &tokens) const { + assert(tokens.size() == 3); + assert(tokens[0].getText() == "("); + assert(tokens[2].getText() == ")"); + } }; //------------------------------------------------------------------- -class FunctionPattern : public Pattern -{ +class FunctionPattern : public Pattern { protected: - std::string m_functionName; - bool m_implicitArgAllowed; - // if m_implicitArgAllowed == true then the first argument is the frame number - // e.g. f(5) means f(frame,5) - // to use a different first argument (e.g. t*10) you have to write f(t*10;5) - - int m_minArgCount; - std::vector m_optionalArgDefaults; - -public: - FunctionPattern(std::string functionName, int minArgCount) - : m_functionName(functionName), m_implicitArgAllowed(false), m_minArgCount(minArgCount) - { - } - - void allowImplicitArg(bool allowed) { m_implicitArgAllowed = allowed; } - void addOptionalArg(double value) { m_optionalArgDefaults.push_back(value); } - - std::string getFirstKeyword() const { return m_functionName; } - bool expressionExpected(const std::vector &previousTokens) const - { - int n = (int)previousTokens.size(); - return 2 <= n && (n & 1) == 0; - } - - bool matchToken(const std::vector &previousTokens, const Token &token) const - { - int i = (int)previousTokens.size(); - std::string s = toLower(token.getText()); - if (i == 0) - return s == toLower(m_functionName); - else if (i == 1) - return s == "("; - else if ((i & 1) == 0) - return true; - else if (s == ",") - return true; - else if (s == ";") - return i == 3 && m_implicitArgAllowed; - else if (s == ")") { - int n = (i - 1) / 2; - if (previousTokens.size() > 3 && previousTokens[3].getText() == ";") - n--; - if (n < m_minArgCount || n > m_minArgCount + (int)m_optionalArgDefaults.size()) - return false; - else - return true; - } else - return false; - } - bool isFinished(const std::vector &previousTokens, const Token &token) const - { - if (previousTokens.empty()) - return false; - return m_minArgCount == 0 && previousTokens.size() == 1 && token.getText() != "(" || - previousTokens.back().getText() == ")"; - } - TokenType getTokenType(const std::vector &previousTokens, const Token &token) const - { - int i = (int)previousTokens.size(); - if (i == 0) - return Function; - else if (i == 1 || token.getText() == ")") - return Function; - else if (i == 3) - return token.getText() == ";" ? Comma : Comma; - else if (i & 1) - return Comma; - else - return InternalError; - } - - void getArgs( - std::vector &nodes, - Calculator *calc, std::vector &stack, - const std::vector &tokens) const - { - - bool implicitArgUsed = m_implicitArgAllowed && tokens.size() > 3 && tokens[3].getText() == ";"; - - // n = number of arguments to provide (mandatory + optional + implicit) - int n = m_minArgCount + (int)m_optionalArgDefaults.size() + (m_implicitArgAllowed ? 1 : 0); - - // m = number of default arguments to assign (with their default value) - int m = n - (tokens.size() - 2) / 2; - if (m_implicitArgAllowed && !implicitArgUsed) - m--; - - assert(m <= (int)m_optionalArgDefaults.size()); - if (m > (int)m_optionalArgDefaults.size()) - m = (int)m_optionalArgDefaults.size(); - - nodes.resize(n); - - // fetch arguments from the stack - int k = n - m; - if (implicitArgUsed) { - while (k > 0) - nodes[--k] = popNode(stack); - } else { - while (k > 1) - nodes[--k] = popNode(stack); - nodes[0] = new VariableNode(calc, CalculatorNode::FRAME); - } - - // add default values - for (int i = 0; i < m; i++) - nodes[n - m + i] = new NumberNode(calc, m_optionalArgDefaults[i]); - } + std::string m_functionName; + bool m_implicitArgAllowed; + // if m_implicitArgAllowed == true then the first argument is the frame number + // e.g. f(5) means f(frame,5) + // to use a different first argument (e.g. t*10) you have to write f(t*10;5) + + int m_minArgCount; + std::vector m_optionalArgDefaults; + +public: + FunctionPattern(std::string functionName, int minArgCount) + : m_functionName(functionName) + , m_implicitArgAllowed(false) + , m_minArgCount(minArgCount) {} + + void allowImplicitArg(bool allowed) { m_implicitArgAllowed = allowed; } + void addOptionalArg(double value) { m_optionalArgDefaults.push_back(value); } + + std::string getFirstKeyword() const { return m_functionName; } + bool expressionExpected(const std::vector &previousTokens) const { + int n = (int)previousTokens.size(); + return 2 <= n && (n & 1) == 0; + } + + bool matchToken(const std::vector &previousTokens, + const Token &token) const { + int i = (int)previousTokens.size(); + std::string s = toLower(token.getText()); + if (i == 0) + return s == toLower(m_functionName); + else if (i == 1) + return s == "("; + else if ((i & 1) == 0) + return true; + else if (s == ",") + return true; + else if (s == ";") + return i == 3 && m_implicitArgAllowed; + else if (s == ")") { + int n = (i - 1) / 2; + if (previousTokens.size() > 3 && previousTokens[3].getText() == ";") n--; + if (n < m_minArgCount || + n > m_minArgCount + (int)m_optionalArgDefaults.size()) + return false; + else + return true; + } else + return false; + } + bool isFinished(const std::vector &previousTokens, + const Token &token) const { + if (previousTokens.empty()) return false; + return m_minArgCount == 0 && previousTokens.size() == 1 && + token.getText() != "(" || + previousTokens.back().getText() == ")"; + } + TokenType getTokenType(const std::vector &previousTokens, + const Token &token) const { + int i = (int)previousTokens.size(); + if (i == 0) + return Function; + else if (i == 1 || token.getText() == ")") + return Function; + else if (i == 3) + return token.getText() == ";" ? Comma : Comma; + else if (i & 1) + return Comma; + else + return InternalError; + } + + void getArgs(std::vector &nodes, Calculator *calc, + std::vector &stack, + const std::vector &tokens) const { + bool implicitArgUsed = + m_implicitArgAllowed && tokens.size() > 3 && tokens[3].getText() == ";"; + + // n = number of arguments to provide (mandatory + optional + implicit) + int n = m_minArgCount + (int)m_optionalArgDefaults.size() + + (m_implicitArgAllowed ? 1 : 0); + + // m = number of default arguments to assign (with their default value) + int m = n - (tokens.size() - 2) / 2; + if (m_implicitArgAllowed && !implicitArgUsed) m--; + + assert(m <= (int)m_optionalArgDefaults.size()); + if (m > (int)m_optionalArgDefaults.size()) + m = (int)m_optionalArgDefaults.size(); + + nodes.resize(n); + + // fetch arguments from the stack + int k = n - m; + if (implicitArgUsed) { + while (k > 0) nodes[--k] = popNode(stack); + } else { + while (k > 1) nodes[--k] = popNode(stack); + nodes[0] = new VariableNode(calc, CalculatorNode::FRAME); + } + + // add default values + for (int i = 0; i < m; i++) + nodes[n - m + i] = new NumberNode(calc, m_optionalArgDefaults[i]); + } }; //------------------------------------------------------------------- template -class F0Pattern : public FunctionPattern -{ +class F0Pattern : public FunctionPattern { public: - F0Pattern(std::string functionName) : FunctionPattern(functionName, 0) {} - void createNode(Calculator *calc, std::vector &stack, - const std::vector &tokens) const - { - stack.push_back(new Op0Node(calc, m_functionName)); - } + F0Pattern(std::string functionName) : FunctionPattern(functionName, 0) {} + void createNode(Calculator *calc, std::vector &stack, + const std::vector &tokens) const { + stack.push_back(new Op0Node(calc, m_functionName)); + } }; //------------------------------------------------------------------- template -class F1Pattern : public FunctionPattern -{ +class F1Pattern : public FunctionPattern { public: - F1Pattern(std::string functionName, std::string descr = "") : FunctionPattern(functionName, 1) { setDescription(descr); } - void createNode(Calculator *calc, std::vector &stack, - const std::vector &tokens) const - { - stack.push_back(new Op1Node(calc, popNode(stack))); - } + F1Pattern(std::string functionName, std::string descr = "") + : FunctionPattern(functionName, 1) { + setDescription(descr); + } + void createNode(Calculator *calc, std::vector &stack, + const std::vector &tokens) const { + stack.push_back(new Op1Node(calc, popNode(stack))); + } }; //------------------------------------------------------------------- template -class F2Pattern : public FunctionPattern -{ +class F2Pattern : public FunctionPattern { public: - F2Pattern(std::string functionName, std::string descr = "") : FunctionPattern(functionName, 2) { setDescription(descr); } - void createNode(Calculator *calc, std::vector &stack, - const std::vector &tokens) const - { - CalculatorNode *b = popNode(stack); - CalculatorNode *a = popNode(stack); - stack.push_back(new Op2Node(calc, a, b)); - } + F2Pattern(std::string functionName, std::string descr = "") + : FunctionPattern(functionName, 2) { + setDescription(descr); + } + void createNode(Calculator *calc, std::vector &stack, + const std::vector &tokens) const { + CalculatorNode *b = popNode(stack); + CalculatorNode *a = popNode(stack); + stack.push_back(new Op2Node(calc, a, b)); + } }; //------------------------------------------------------------------- template -class F3Pattern : public FunctionPattern -{ +class F3Pattern : public FunctionPattern { public: - F3Pattern(std::string functionName, std::string descr = "") : FunctionPattern(functionName, 3) { setDescription(descr); } - void createNode(Calculator *calc, std::vector &stack, - const std::vector &tokens) const - { - CalculatorNode *c = popNode(stack); - CalculatorNode *b = popNode(stack); - CalculatorNode *a = popNode(stack); - stack.push_back(new Op3Node(calc, a, b, c)); - } + F3Pattern(std::string functionName, std::string descr = "") + : FunctionPattern(functionName, 3) { + setDescription(descr); + } + void createNode(Calculator *calc, std::vector &stack, + const std::vector &tokens) const { + CalculatorNode *c = popNode(stack); + CalculatorNode *b = popNode(stack); + CalculatorNode *a = popNode(stack); + stack.push_back(new Op3Node(calc, a, b, c)); + } }; //------------------------------------------------------------------- template -class Fs2Pattern : public FunctionPattern -{ +class Fs2Pattern : public FunctionPattern { public: - Fs2Pattern(std::string functionName, std::string description) - : FunctionPattern(functionName, 1) - { - allowImplicitArg(true); - setDescription(description); - } - void createNode(Calculator *calc, std::vector &stack, - const std::vector &tokens) const - { - - std::vector nodes; - getArgs(nodes, calc, stack, tokens); - stack.push_back(new Op2Node(calc, nodes[0], nodes[1])); - } + Fs2Pattern(std::string functionName, std::string description) + : FunctionPattern(functionName, 1) { + allowImplicitArg(true); + setDescription(description); + } + void createNode(Calculator *calc, std::vector &stack, + const std::vector &tokens) const { + std::vector nodes; + getArgs(nodes, calc, stack, tokens); + stack.push_back(new Op2Node(calc, nodes[0], nodes[1])); + } }; //------------------------------------------------------------------- template -class Fs3Pattern : public FunctionPattern -{ -public: - Fs3Pattern(std::string functionName, double defVal, std::string descr) - : FunctionPattern(functionName, 1) - { - allowImplicitArg(true); - addOptionalArg(defVal); - setDescription(descr); - } - void createNode(Calculator *calc, std::vector &stack, - const std::vector &tokens) const - { - - std::vector nodes; - getArgs(nodes, calc, stack, tokens); - stack.push_back(new Op3Node(calc, nodes[0], nodes[1], nodes[2])); - } +class Fs3Pattern : public FunctionPattern { +public: + Fs3Pattern(std::string functionName, double defVal, std::string descr) + : FunctionPattern(functionName, 1) { + allowImplicitArg(true); + addOptionalArg(defVal); + setDescription(descr); + } + void createNode(Calculator *calc, std::vector &stack, + const std::vector &tokens) const { + std::vector nodes; + getArgs(nodes, calc, stack, tokens); + stack.push_back(new Op3Node(calc, nodes[0], nodes[1], nodes[2])); + } }; //------------------------------------------------------------------- -class CyclePattern : public FunctionPattern -{ +class CyclePattern : public FunctionPattern { public: - CyclePattern(std::string functionName) : FunctionPattern(functionName, 1) - { - setDescription("cycle(period)\nCycles the transitions of the period previous frames to the selected range"); - } - void createNode(Calculator *calc, std::vector &stack, - const std::vector &tokens) const - { - CalculatorNode *a = popNode(stack); - stack.push_back(new CycleNode(calc, a)); - } + CyclePattern(std::string functionName) : FunctionPattern(functionName, 1) { + setDescription( + "cycle(period)\nCycles the transitions of the period previous frames " + "to the selected range"); + } + void createNode(Calculator *calc, std::vector &stack, + const std::vector &tokens) const { + CalculatorNode *a = popNode(stack); + stack.push_back(new CycleNode(calc, a)); + } }; //------------------------------------------------------------------- -class RandomPattern : public FunctionPattern -{ - bool m_seed; - -public: - RandomPattern(std::string functionName, bool seed, std::string description) - : FunctionPattern(functionName, seed ? 1 : 0), m_seed(seed) - { - allowImplicitArg(true); - addOptionalArg(0); - addOptionalArg(0); - setDescription(description); - } - void createNode(Calculator *calc, std::vector &stack, - const std::vector &tokens) const - { - int n = ((int)tokens.size() - 1) / 2; - if (m_seed) - n--; - RandomNode *randomNode = new RandomNode(calc); - if (n > 0) { - randomNode->setMax(popNode(stack)); - if (n > 1) - randomNode->setMin(popNode(stack)); - } - if (m_seed) - randomNode->setSeed(popNode(stack)); - stack.push_back(randomNode); - } +class RandomPattern : public FunctionPattern { + bool m_seed; + +public: + RandomPattern(std::string functionName, bool seed, std::string description) + : FunctionPattern(functionName, seed ? 1 : 0), m_seed(seed) { + allowImplicitArg(true); + addOptionalArg(0); + addOptionalArg(0); + setDescription(description); + } + void createNode(Calculator *calc, std::vector &stack, + const std::vector &tokens) const { + int n = ((int)tokens.size() - 1) / 2; + if (m_seed) n--; + RandomNode *randomNode = new RandomNode(calc); + if (n > 0) { + randomNode->setMax(popNode(stack)); + if (n > 1) randomNode->setMin(popNode(stack)); + } + if (m_seed) randomNode->setSeed(popNode(stack)); + stack.push_back(randomNode); + } }; //=================================================================== -class PatternTable -{ - std::map m_kTable; - std::vector m_uTable; - Grammar::Position m_position; - -public: - PatternTable(Grammar::Position position) : m_position(position) {} - - ~PatternTable() - { - for (std::map::iterator - it = m_kTable.begin(); - it != m_kTable.end(); ++it) - delete it->second; - for (std::vector::iterator - it = m_uTable.begin(); - it != m_uTable.end(); ++it) - delete *it; - } - - void addPattern(Pattern *pattern) - { - std::string keyword = pattern->getFirstKeyword(); - if (keyword != "") { - // first keyword should be unique - assert(m_kTable.count(keyword) == 0); - m_kTable[keyword] = pattern; - } else - m_uTable.push_back(pattern); - } - - const Pattern *getPattern(const Token &token) const - { - std::vector tokens; - if (m_position == Grammar::ExpressionEnd) - tokens.push_back(Token()); - if (token.getType() == Token::Punct || token.getType() == Token::Ident) { - std::string keyword = token.getText(); - std::map::const_iterator it = m_kTable.find(keyword); - if (it != m_kTable.end()) { - Pattern *pattern = it->second; - if (pattern->matchToken(tokens, token)) { - return pattern; - } - } - } - for (int i = 0; i < (int)m_uTable.size(); i++) { - Pattern *pattern = m_uTable[i]; - if (pattern->matchToken(tokens, token)) { - return pattern; - } - } - return 0; - } - - void getSuggestions(Grammar::Suggestions &suggestions) const - { - std::map::const_iterator it; - for (it = m_kTable.begin(); it != m_kTable.end(); ++it) { - suggestions.push_back(std::make_pair(it->first, it->second->getDescription())); - } - for (int i = 0; i < (int)m_uTable.size(); i++) { - std::vector keywords; - m_uTable[i]->getAcceptableKeywords(keywords); - for (int j = 0; j < (int)keywords.size(); j++) - suggestions.push_back(std::make_pair(keywords[j], m_uTable[i]->getDescription())); - } - } +class PatternTable { + std::map m_kTable; + std::vector m_uTable; + Grammar::Position m_position; + +public: + PatternTable(Grammar::Position position) : m_position(position) {} + + ~PatternTable() { + for (std::map::iterator it = m_kTable.begin(); + it != m_kTable.end(); ++it) + delete it->second; + for (std::vector::iterator it = m_uTable.begin(); + it != m_uTable.end(); ++it) + delete *it; + } + + void addPattern(Pattern *pattern) { + std::string keyword = pattern->getFirstKeyword(); + if (keyword != "") { + // first keyword should be unique + assert(m_kTable.count(keyword) == 0); + m_kTable[keyword] = pattern; + } else + m_uTable.push_back(pattern); + } + + const Pattern *getPattern(const Token &token) const { + std::vector tokens; + if (m_position == Grammar::ExpressionEnd) tokens.push_back(Token()); + if (token.getType() == Token::Punct || token.getType() == Token::Ident) { + std::string keyword = token.getText(); + std::map::const_iterator it = + m_kTable.find(keyword); + if (it != m_kTable.end()) { + Pattern *pattern = it->second; + if (pattern->matchToken(tokens, token)) { + return pattern; + } + } + } + for (int i = 0; i < (int)m_uTable.size(); i++) { + Pattern *pattern = m_uTable[i]; + if (pattern->matchToken(tokens, token)) { + return pattern; + } + } + return 0; + } + + void getSuggestions(Grammar::Suggestions &suggestions) const { + std::map::const_iterator it; + for (it = m_kTable.begin(); it != m_kTable.end(); ++it) { + suggestions.push_back( + std::make_pair(it->first, it->second->getDescription())); + } + for (int i = 0; i < (int)m_uTable.size(); i++) { + std::vector keywords; + m_uTable[i]->getAcceptableKeywords(keywords); + for (int j = 0; j < (int)keywords.size(); j++) + suggestions.push_back( + std::make_pair(keywords[j], m_uTable[i]->getDescription())); + } + } }; //=================================================================== @@ -1010,344 +907,343 @@ public: // //------------------------------------------------------------------- -class Pow -{ +class Pow { public: - double operator()(double x, double y) const { return pow(x, y); } + double operator()(double x, double y) const { return pow(x, y); } }; -// class Mod {public: double operator()(double x, double y) const {return (int)x % (int)y;} }; -class Sin -{ +// class Mod {public: double operator()(double x, double y) const {return +// (int)x % (int)y;} }; +class Sin { public: - double operator()(double x) const { return sin(toRad(x)); } + double operator()(double x) const { return sin(toRad(x)); } }; -class Cos -{ +class Cos { public: - double operator()(double x) const { return cos(toRad(x)); } + double operator()(double x) const { return cos(toRad(x)); } }; -class Tan -{ +class Tan { public: - double operator()(double x) const { return tan(toRad(x)); } + double operator()(double x) const { return tan(toRad(x)); } }; -class Sinh -{ +class Sinh { public: - double operator()(double x) const { return sinh(toRad(x)); } + double operator()(double x) const { return sinh(toRad(x)); } }; -class Cosh -{ +class Cosh { public: - double operator()(double x) const { return cosh(toRad(x)); } + double operator()(double x) const { return cosh(toRad(x)); } }; -class Tanh -{ +class Tanh { public: - double operator()(double x) const { return tanh(toRad(x)); } + double operator()(double x) const { return tanh(toRad(x)); } }; -class Atan -{ +class Atan { public: - double operator()(double x) const { return toDeg(atan(x)); } + double operator()(double x) const { return toDeg(atan(x)); } }; -class Atan2 -{ +class Atan2 { public: - double operator()(double x, double y) const { return toDeg(atan2(x, y)); } + double operator()(double x, double y) const { return toDeg(atan2(x, y)); } }; -class Log -{ +class Log { public: - double operator()(double x) const { return log(x); } + double operator()(double x) const { return log(x); } }; -class Exp -{ +class Exp { public: - double operator()(double x) const { return exp(x); } + double operator()(double x) const { return exp(x); } }; -class Floor -{ +class Floor { public: - double operator()(double x) const { return tfloor(x); } + double operator()(double x) const { return tfloor(x); } }; -class Ceil -{ +class Ceil { public: - double operator()(double x) const { return tceil(x); } + double operator()(double x) const { return tceil(x); } }; -class Round -{ +class Round { public: - double operator()(double x) const { return tround(x); } + double operator()(double x) const { return tround(x); } }; -class Abs -{ +class Abs { public: - double operator()(double x) const { return fabs(x); } + double operator()(double x) const { return fabs(x); } }; -class Sign -{ +class Sign { public: - double operator()(double x) const { return x > 0 ? 1 : x < 0 ? -1 : 0; } + double operator()(double x) const { return x > 0 ? 1 : x < 0 ? -1 : 0; } }; -class Sqrt -{ +class Sqrt { public: - double operator()(double x) const { return x >= 0.0 ? sqrt(x) : 0; } + double operator()(double x) const { return x >= 0.0 ? sqrt(x) : 0; } }; -class Sqr -{ +class Sqr { public: - double operator()(double x) const { return x * x; } + double operator()(double x) const { return x * x; } }; -class Crop -{ +class Crop { public: - double operator()(double x, double a, double b) const { return tcrop(x, a, b); } + double operator()(double x, double a, double b) const { + return tcrop(x, a, b); + } }; -class Step -{ +class Step { public: - double operator()(double x, double y) const { return x < y ? 0 : 1; } + double operator()(double x, double y) const { return x < y ? 0 : 1; } }; -class Mod -{ +class Mod { public: - double operator()(double x, double y) const - { - if (y == 0.0) - return 0; - return x - y * floor(x / y); - } + double operator()(double x, double y) const { + if (y == 0.0) return 0; + return x - y * floor(x / y); + } }; -class Min -{ +class Min { public: - double operator()(double x, double y) const { return x < y ? x : y; } + double operator()(double x, double y) const { return x < y ? x : y; } }; -class Max -{ +class Max { public: - double operator()(double x, double y) const { return x > y ? x : y; } + double operator()(double x, double y) const { return x > y ? x : y; } }; -class Gt -{ +class Gt { public: - double operator()(double x, double y) const { return x > y ? 1 : 0; } + double operator()(double x, double y) const { return x > y ? 1 : 0; } }; -class Ge -{ +class Ge { public: - double operator()(double x, double y) const { return x >= y ? 1 : 0; } + double operator()(double x, double y) const { return x >= y ? 1 : 0; } }; -class Lt -{ +class Lt { public: - double operator()(double x, double y) const { return x < y ? 1 : 0; } + double operator()(double x, double y) const { return x < y ? 1 : 0; } }; -class Le -{ +class Le { public: - double operator()(double x, double y) const { return x <= y ? 1 : 0; } + double operator()(double x, double y) const { return x <= y ? 1 : 0; } }; -class Ne -{ +class Ne { public: - double operator()(double x, double y) const { return x != y ? 1 : 0; } + double operator()(double x, double y) const { return x != y ? 1 : 0; } }; -class Eq -{ +class Eq { public: - double operator()(double x, double y) const { return x == y ? 1 : 0; } + double operator()(double x, double y) const { return x == y ? 1 : 0; } }; -class And -{ +class And { public: - double operator()(double x, double y) const { return (x != 0) && (y != 0) ? 1 : 0; } + double operator()(double x, double y) const { + return (x != 0) && (y != 0) ? 1 : 0; + } }; -class Or -{ +class Or { public: - double operator()(double x, double y) const { return (x != 0) || (y != 0) ? 1 : 0; } + double operator()(double x, double y) const { + return (x != 0) || (y != 0) ? 1 : 0; + } }; -class Not -{ +class Not { public: - double operator()(double x) const { return x == 0; } + double operator()(double x) const { return x == 0; } }; -class Smoothstep -{ +class Smoothstep { public: - double operator()(double v, double min, double max) const - { - if (v <= min) - return 0; - else if (v >= max) - return 1; - double t = (v - min) / (max - min); - return -2 * t * t * t + 3 * t * t; - } + double operator()(double v, double min, double max) const { + if (v <= min) + return 0; + else if (v >= max) + return 1; + double t = (v - min) / (max - min); + return -2 * t * t * t + 3 * t * t; + } }; -class Pulse -{ +class Pulse { public: - double operator()(double x, double x0, double length) const - { - // double length=5.0; - double b = (.69315 * 4.0) / (length * length); - x -= x0; - return exp(-x * x * b); - } + double operator()(double x, double x0, double length) const { + // double length=5.0; + double b = (.69315 * 4.0) / (length * length); + x -= x0; + return exp(-x * x * b); + } }; -class Saw -{ +class Saw { public: - double operator()(double x, double length, double height) const - { - if (length <= 0.0) - return 0.0; - if (height <= 0.0) - height = length; - double q = x / length; - return height * (q - floor(q)); - } + double operator()(double x, double length, double height) const { + if (length <= 0.0) return 0.0; + if (height <= 0.0) height = length; + double q = x / length; + return height * (q - floor(q)); + } }; -class Wave -{ +class Wave { public: - double operator()(double x, double length) const - { - if (length <= 0.0) - return 0.0; - return sin(x * 2 * PI / length); - } + double operator()(double x, double length) const { + if (length <= 0.0) return 0.0; + return sin(x * 2 * PI / length); + } }; //=================================================================== -class Grammar::Imp -{ -public: - PatternTable m_prePatterns, m_postPatterns; - - Imp() - : m_prePatterns(Grammar::ExpressionStart), m_postPatterns(Grammar::ExpressionEnd) - { - } - ~Imp() {} -}; - -Grammar::Grammar() - : m_imp(new Imp()) -{ - addPattern(new NumberPattern()); - addPattern(new ConstantPattern("pi", PI, "3.14159265...")); - addPattern(new VariablePattern("t", CalculatorNode::T, "ranges from 0.0 to 1.0 along the transition")); - const std::string f_desc = "the current frame number"; - addPattern(new VariablePattern("f", CalculatorNode::FRAME, f_desc)); - addPattern(new VariablePattern("frame", CalculatorNode::FRAME, f_desc)); - const std::string r_desc = "the current frame number, relative to the transition"; - addPattern(new VariablePattern("r", CalculatorNode::RFRAME, r_desc)); - addPattern(new VariablePattern("rframe", CalculatorNode::RFRAME, r_desc)); - addPattern(new Op2Pattern>("+", 10)); - addPattern(new Op2Pattern>("*", 20)); - addPattern(new Op2Pattern("^", 30)); - addPattern(new Op2Pattern>("-", 10)); - addPattern(new Op2Pattern>("/", 20)); - addPattern(new Op2Pattern("%", 8)); - addPattern(new Op2Pattern(">", 6)); - addPattern(new Op2Pattern(">=", 6)); - addPattern(new Op2Pattern("<", 6)); - addPattern(new Op2Pattern("<=", 6)); - addPattern(new Op2Pattern("==", 6)); - addPattern(new Op2Pattern("!=", 6)); - addPattern(new Op2Pattern("&&", 3)); - addPattern(new Op2Pattern("||", 2)); - addPattern(new Op2Pattern("and", 3)); - addPattern(new Op2Pattern("or", 2)); - addPattern(new NotPattern("!", "not")); - addPattern(new NotPattern("not", "")); - addPattern(new UnaryMinusPattern()); - addPattern(new BraketPattern()); - addPattern(new QuestionTernaryPattern()); - addPattern(new F1Pattern("sin", "sin(degree)")); - addPattern(new F1Pattern("cos", "cos(degree)")); - addPattern(new F1Pattern("tan", "tan(degree)")); - addPattern(new F1Pattern("sinh", "sinh(degree)\nHyperbolic sine")); - addPattern(new F1Pattern("cosh", "cosh(degree)\nHyperbolic cosine")); - addPattern(new F1Pattern("tanh", "tanh(degree)\nHyperbolic tangent")); - addPattern(new F1Pattern("atan", "atan(x)\nArctangent : the inverse of tan()")); - addPattern(new F2Pattern("atan2", "atan2(y,x)\nThe counter-clockwise angle in degree between the x-axis and the point(x,y)")); - addPattern(new F1Pattern("log", "log(x)\nThe natural logarithm of x (base e)")); - addPattern(new F1Pattern("exp", "exp(x)\nThe base-e exponential of x")); - addPattern(new F1Pattern("floor", "floor(x)\nThe greatest integer <= x")); - const std::string ceil_desc = "The smallest integer >= x"; - addPattern(new F1Pattern("ceil", "ceil(x)\n" + ceil_desc)); - addPattern(new F1Pattern("ceiling", "ceiling(x)\n" + ceil_desc)); - addPattern(new F1Pattern("round", "round(x)\nThe integer nearest to x")); - addPattern(new F1Pattern("abs", "abs(x)\nThe absolute value of x")); - addPattern(new F1Pattern("sign", "sign(x)\n-1 if x<0, 1 if x>0 and 0 if x=0")); - const std::string sqrt_desc = "Square root of x"; - addPattern(new F1Pattern("sqrt", "sqrt(x)\n" + sqrt_desc)); - addPattern(new F1Pattern("sqr", "sqr(x)\n" + sqrt_desc)); - addPattern(new F3Pattern("crop", "crop(x,a,b)\na if xb, x if x in [a,b]")); - addPattern(new F3Pattern("clamp", "clamp(x,a,b)\na if xb, x if x in [a,b]")); - addPattern(new F2Pattern("min", "min(a,b)")); - addPattern(new F2Pattern("max", "max(a,b)")); - addPattern(new F2Pattern("step", "min(x,x0)\n0 if x=x0")); - addPattern(new F3Pattern("smoothstep", "smoothstep(x,x0)\n0 if x=x0\nas step, but with smooth transition")); - const std::string pulse_desc = "Generates a bump ranging from 0.0 to 1.0 set at position pos"; - addPattern(new Fs3Pattern("pulse", 0.5, "pulse(pos)\npulse(pos,length)\npulse(arg; pos)\npulse(arg;pos,length)\n" + pulse_desc)); - addPattern(new Fs3Pattern("bump", 0.5, "bump(pos)\nbump(pos,length)\nbump(arg; pos)\nbump(arg;pos,length)\n" + pulse_desc)); - const std::string saw_desc = "Generates a periodic sawtooth shaped curve"; - addPattern(new Fs3Pattern("sawtooth", 0.0, "sawtooth(length)\nsawtooth(length, height)\nsawtooth(arg; length)\nsawtooth(arg; length, height)\n" + saw_desc)); - addPattern(new Fs3Pattern("saw", 0.0, "saw(length)\nsaw(length, height)\nsaw(arg; length)\nsaw(arg; length, height)\n" + saw_desc)); - addPattern(new Fs2Pattern("wave", "wave(_length)\nwave(_arg;_length)\nsame as sin(f*180/length)")); - const std::string rnd_desc = "Generates random number between min and max"; - addPattern(new RandomPattern("random", false, "random = random(0,1)\nrandom(max) = random(0,max)\nrandom(min,max)\n" + rnd_desc)); - addPattern(new RandomPattern("rnd", false, "rnd = rnd(0,1)\nrnd(max) = rnd(0,max)\nrnd(min,max)\n" + rnd_desc)); - const std::string rnd_s_desc = rnd_desc + "; seed select different random sequences"; - addPattern(new RandomPattern("random_s", true, "random_s(seed) = random_s(seed, 0,1)\nrandom_s(seed,max) = random_s(seed, 0,max)\nrandom_s(seed,min,max)\n" + rnd_s_desc)); - addPattern(new RandomPattern("rnd_s", true, "rnd_s(seed) = rnd_s(seed, 0,1)\nrnd_s(seed,max) = rnd_s(seed, 0,max)\nrnd_s(seed,min,max)\n" + rnd_s_desc)); - - addPattern(new CyclePattern("cycle")); +class Grammar::Imp { +public: + PatternTable m_prePatterns, m_postPatterns; + + Imp() + : m_prePatterns(Grammar::ExpressionStart) + , m_postPatterns(Grammar::ExpressionEnd) {} + ~Imp() {} +}; + +Grammar::Grammar() : m_imp(new Imp()) { + addPattern(new NumberPattern()); + addPattern(new ConstantPattern("pi", PI, "3.14159265...")); + addPattern(new VariablePattern( + "t", CalculatorNode::T, "ranges from 0.0 to 1.0 along the transition")); + const std::string f_desc = "the current frame number"; + addPattern(new VariablePattern("f", CalculatorNode::FRAME, f_desc)); + addPattern(new VariablePattern("frame", CalculatorNode::FRAME, f_desc)); + const std::string r_desc = + "the current frame number, relative to the transition"; + addPattern(new VariablePattern("r", CalculatorNode::RFRAME, r_desc)); + addPattern(new VariablePattern("rframe", CalculatorNode::RFRAME, r_desc)); + addPattern(new Op2Pattern>("+", 10)); + addPattern(new Op2Pattern>("*", 20)); + addPattern(new Op2Pattern("^", 30)); + addPattern(new Op2Pattern>("-", 10)); + addPattern(new Op2Pattern>("/", 20)); + addPattern(new Op2Pattern("%", 8)); + addPattern(new Op2Pattern(">", 6)); + addPattern(new Op2Pattern(">=", 6)); + addPattern(new Op2Pattern("<", 6)); + addPattern(new Op2Pattern("<=", 6)); + addPattern(new Op2Pattern("==", 6)); + addPattern(new Op2Pattern("!=", 6)); + addPattern(new Op2Pattern("&&", 3)); + addPattern(new Op2Pattern("||", 2)); + addPattern(new Op2Pattern("and", 3)); + addPattern(new Op2Pattern("or", 2)); + addPattern(new NotPattern("!", "not")); + addPattern(new NotPattern("not", "")); + addPattern(new UnaryMinusPattern()); + addPattern(new BraketPattern()); + addPattern(new QuestionTernaryPattern()); + addPattern(new F1Pattern("sin", "sin(degree)")); + addPattern(new F1Pattern("cos", "cos(degree)")); + addPattern(new F1Pattern("tan", "tan(degree)")); + addPattern(new F1Pattern("sinh", "sinh(degree)\nHyperbolic sine")); + addPattern(new F1Pattern("cosh", "cosh(degree)\nHyperbolic cosine")); + addPattern(new F1Pattern("tanh", "tanh(degree)\nHyperbolic tangent")); + addPattern(new F1Pattern("atan", + "atan(x)\nArctangent : the inverse of tan()")); + addPattern(new F2Pattern("atan2", + "atan2(y,x)\nThe counter-clockwise angle in " + "degree between the x-axis and the " + "point(x,y)")); + addPattern( + new F1Pattern("log", "log(x)\nThe natural logarithm of x (base e)")); + addPattern(new F1Pattern("exp", "exp(x)\nThe base-e exponential of x")); + addPattern( + new F1Pattern("floor", "floor(x)\nThe greatest integer <= x")); + const std::string ceil_desc = "The smallest integer >= x"; + addPattern(new F1Pattern("ceil", "ceil(x)\n" + ceil_desc)); + addPattern(new F1Pattern("ceiling", "ceiling(x)\n" + ceil_desc)); + addPattern( + new F1Pattern("round", "round(x)\nThe integer nearest to x")); + addPattern(new F1Pattern("abs", "abs(x)\nThe absolute value of x")); + addPattern( + new F1Pattern("sign", "sign(x)\n-1 if x<0, 1 if x>0 and 0 if x=0")); + const std::string sqrt_desc = "Square root of x"; + addPattern(new F1Pattern("sqrt", "sqrt(x)\n" + sqrt_desc)); + addPattern(new F1Pattern("sqr", "sqr(x)\n" + sqrt_desc)); + addPattern(new F3Pattern( + "crop", "crop(x,a,b)\na if xb, x if x in [a,b]")); + addPattern(new F3Pattern( + "clamp", "clamp(x,a,b)\na if xb, x if x in [a,b]")); + addPattern(new F2Pattern("min", "min(a,b)")); + addPattern(new F2Pattern("max", "max(a,b)")); + addPattern(new F2Pattern("step", "min(x,x0)\n0 if x=x0")); + addPattern(new F3Pattern("smoothstep", + "smoothstep(x,x0)\n0 if x=x0\nas step, but with smooth " + "transition")); + const std::string pulse_desc = + "Generates a bump ranging from 0.0 to 1.0 set at position pos"; + addPattern(new Fs3Pattern("pulse", 0.5, + "pulse(pos)\npulse(pos,length)\npulse(arg; " + "pos)\npulse(arg;pos,length)\n" + + pulse_desc)); + addPattern(new Fs3Pattern( + "bump", 0.5, + "bump(pos)\nbump(pos,length)\nbump(arg; pos)\nbump(arg;pos,length)\n" + + pulse_desc)); + const std::string saw_desc = "Generates a periodic sawtooth shaped curve"; + addPattern(new Fs3Pattern("sawtooth", 0.0, + "sawtooth(length)\nsawtooth(length, " + "height)\nsawtooth(arg; " + "length)\nsawtooth(arg; length, height)\n" + + saw_desc)); + addPattern(new Fs3Pattern("saw", 0.0, + "saw(length)\nsaw(length, height)\nsaw(arg; " + "length)\nsaw(arg; length, height)\n" + + saw_desc)); + addPattern(new Fs2Pattern( + "wave", "wave(_length)\nwave(_arg;_length)\nsame as sin(f*180/length)")); + const std::string rnd_desc = "Generates random number between min and max"; + addPattern(new RandomPattern( + "random", false, + "random = random(0,1)\nrandom(max) = random(0,max)\nrandom(min,max)\n" + + rnd_desc)); + addPattern(new RandomPattern( + "rnd", false, + "rnd = rnd(0,1)\nrnd(max) = rnd(0,max)\nrnd(min,max)\n" + rnd_desc)); + const std::string rnd_s_desc = + rnd_desc + "; seed select different random sequences"; + addPattern(new RandomPattern("random_s", true, + "random_s(seed) = random_s(seed, " + "0,1)\nrandom_s(seed,max) = random_s(seed, " + "0,max)\nrandom_s(seed,min,max)\n" + + rnd_s_desc)); + addPattern(new RandomPattern("rnd_s", true, + "rnd_s(seed) = rnd_s(seed, " + "0,1)\nrnd_s(seed,max) = rnd_s(seed, " + "0,max)\nrnd_s(seed,min,max)\n" + + rnd_s_desc)); + + addPattern(new CyclePattern("cycle")); } -Grammar::~Grammar() -{ -} +Grammar::~Grammar() {} -void Grammar::addPattern(Pattern *pattern) -{ - std::vector noTokens; - if (pattern->expressionExpected(noTokens)) - m_imp->m_postPatterns.addPattern(pattern); - else - m_imp->m_prePatterns.addPattern(pattern); +void Grammar::addPattern(Pattern *pattern) { + std::vector noTokens; + if (pattern->expressionExpected(noTokens)) + m_imp->m_postPatterns.addPattern(pattern); + else + m_imp->m_prePatterns.addPattern(pattern); } -const Pattern *Grammar::getPattern(Position position, const Token &token) const -{ - Pattern *pattern = 0; - if (position == ExpressionStart) - return m_imp->m_prePatterns.getPattern(token); - else - return m_imp->m_postPatterns.getPattern(token); +const Pattern *Grammar::getPattern(Position position, + const Token &token) const { + Pattern *pattern = 0; + if (position == ExpressionStart) + return m_imp->m_prePatterns.getPattern(token); + else + return m_imp->m_postPatterns.getPattern(token); } -void Grammar::getSuggestions(Grammar::Suggestions &suggestions, Position position) const -{ - if (position == ExpressionStart) - return m_imp->m_prePatterns.getSuggestions(suggestions); - else - return m_imp->m_postPatterns.getSuggestions(suggestions); +void Grammar::getSuggestions(Grammar::Suggestions &suggestions, + Position position) const { + if (position == ExpressionStart) + return m_imp->m_prePatterns.getSuggestions(suggestions); + else + return m_imp->m_postPatterns.getSuggestions(suggestions); } //=================================================================== -} // namespace TSyntax +} // namespace TSyntax diff --git a/toonz/sources/common/expressions/tparser.cpp b/toonz/sources/common/expressions/tparser.cpp index 2b586e3..f7f5b00 100644 --- a/toonz/sources/common/expressions/tparser.cpp +++ b/toonz/sources/common/expressions/tparser.cpp @@ -7,344 +7,319 @@ #include -namespace TSyntax -{ +namespace TSyntax { //------------------------------------------------------------------- // RunningPattern //------------------------------------------------------------------- -class RunningPattern -{ +class RunningPattern { public: - std::vector m_tokens; - const Pattern *m_pattern; - - RunningPattern(const Pattern *pattern) : m_pattern(pattern) {} - - int getPriority() const { return m_pattern->getPriority(); } - bool isFinished(const Token &token) const { return m_pattern->isFinished(m_tokens, token); } - bool isComplete(const Token &token) const { return m_pattern->isComplete(m_tokens, token); } - bool expressionExpected() const { return m_pattern->expressionExpected(m_tokens); } - bool matchToken(const Token &token) const { return m_pattern->matchToken(m_tokens, token); } - void advance() - { - assert(!isFinished(Token())); - m_tokens.push_back(Token()); - } - void advance(const Token &token) - { - assert(!isFinished(token)); - m_tokens.push_back(token); - } - TokenType getTokenType(const Token &token) const { return m_pattern->getTokenType(m_tokens, token); } - - void createNode(Calculator *calc, std::vector &stack) - { - m_pattern->createNode(calc, stack, m_tokens); - } + std::vector m_tokens; + const Pattern *m_pattern; + + RunningPattern(const Pattern *pattern) : m_pattern(pattern) {} + + int getPriority() const { return m_pattern->getPriority(); } + bool isFinished(const Token &token) const { + return m_pattern->isFinished(m_tokens, token); + } + bool isComplete(const Token &token) const { + return m_pattern->isComplete(m_tokens, token); + } + bool expressionExpected() const { + return m_pattern->expressionExpected(m_tokens); + } + bool matchToken(const Token &token) const { + return m_pattern->matchToken(m_tokens, token); + } + void advance() { + assert(!isFinished(Token())); + m_tokens.push_back(Token()); + } + void advance(const Token &token) { + assert(!isFinished(token)); + m_tokens.push_back(token); + } + TokenType getTokenType(const Token &token) const { + return m_pattern->getTokenType(m_tokens, token); + } + + void createNode(Calculator *calc, std::vector &stack) { + m_pattern->createNode(calc, stack, m_tokens); + } }; //------------------------------------------------------------------- // Parser::Imp //------------------------------------------------------------------- -class Parser::Imp -{ +class Parser::Imp { public: - const Grammar *m_grammar; - Tokenizer m_tokenizer; - std::string m_errorString; - bool m_isValid; - Calculator *m_calculator; - std::vector m_patternStack; - std::vector m_nodeStack; - std::vector m_syntaxTokens; - Grammar::Position m_position; - // Pattern *m_lastPattern; - - Imp(const Grammar *grammar) - : m_grammar(grammar), m_errorString(""), m_isValid(false), m_calculator(0), m_position(Grammar::ExpressionStart) - { - } - ~Imp() - { - clearPointerContainer(m_nodeStack); - delete m_calculator; - } - - void pushSyntaxToken(TokenType type); - bool parseExpression(bool checkOnly); - void flushPatterns(int minPriority, int minIndex, bool checkOnly); - bool checkSyntax(std::vector &tokens); + const Grammar *m_grammar; + Tokenizer m_tokenizer; + std::string m_errorString; + bool m_isValid; + Calculator *m_calculator; + std::vector m_patternStack; + std::vector m_nodeStack; + std::vector m_syntaxTokens; + Grammar::Position m_position; + // Pattern *m_lastPattern; + + Imp(const Grammar *grammar) + : m_grammar(grammar) + , m_errorString("") + , m_isValid(false) + , m_calculator(0) + , m_position(Grammar::ExpressionStart) {} + ~Imp() { + clearPointerContainer(m_nodeStack); + delete m_calculator; + } + + void pushSyntaxToken(TokenType type); + bool parseExpression(bool checkOnly); + void flushPatterns(int minPriority, int minIndex, bool checkOnly); + bool checkSyntax(std::vector &tokens); }; //------------------------------------------------------------------- // Parser //------------------------------------------------------------------- -Parser::Parser(const Grammar *grammar) - : m_imp(new Imp(grammar)) -{ -} +Parser::Parser(const Grammar *grammar) : m_imp(new Imp(grammar)) {} //------------------------------------------------------------------- -Parser::~Parser() -{ -} +Parser::~Parser() {} //------------------------------------------------------------------- -void Parser::Imp::flushPatterns(int minPriority, int minIndex, bool checkOnly) -{ - while ((int)m_patternStack.size() > minIndex && m_patternStack.back().getPriority() >= minPriority) { - if (!checkOnly) - m_patternStack.back().createNode(m_calculator, m_nodeStack); - m_patternStack.pop_back(); - } +void Parser::Imp::flushPatterns(int minPriority, int minIndex, bool checkOnly) { + while ((int)m_patternStack.size() > minIndex && + m_patternStack.back().getPriority() >= minPriority) { + if (!checkOnly) m_patternStack.back().createNode(m_calculator, m_nodeStack); + m_patternStack.pop_back(); + } } //------------------------------------------------------------------- -void Parser::Imp::pushSyntaxToken(TokenType type) -{ - SyntaxToken syntaxToken; - Token token = m_tokenizer.getToken(); - syntaxToken.m_pos = token.getPos(); - syntaxToken.m_length = token.getPos1() - token.getPos() + 1; - syntaxToken.m_type = type; - m_syntaxTokens.push_back(syntaxToken); +void Parser::Imp::pushSyntaxToken(TokenType type) { + SyntaxToken syntaxToken; + Token token = m_tokenizer.getToken(); + syntaxToken.m_pos = token.getPos(); + syntaxToken.m_length = token.getPos1() - token.getPos() + 1; + syntaxToken.m_type = type; + m_syntaxTokens.push_back(syntaxToken); } //------------------------------------------------------------------- -bool Parser::Imp::parseExpression(bool checkOnly) -{ - if (!m_grammar) - return false; - int stackMinIndex = m_patternStack.size(); - int count = 0; - Grammar::Position position = Grammar::ExpressionStart; - m_position = position; - // warning: parseExpression() is called recursively. m_position is used after parseExpression() - // for diagnostic and suggestions. position is used in the actual parsing - - bool expressionExpected = true; - while (!m_tokenizer.eos()) { - // token, position -> pattern - const Pattern *pattern = m_grammar->getPattern(position, m_tokenizer.getToken()); - if (!pattern) { - // no pattern found for the next token - if (position == Grammar::ExpressionEnd) { - // already found an expression - flushPatterns(-1, stackMinIndex, checkOnly); - return true; - } else { - // syntax error : expression not found - if (checkOnly) - pushSyntaxToken(UnexpectedToken); - - m_errorString = "Unexpected token"; - return false; - } - } - // pattern found: start scanning it - RunningPattern runningPattern(pattern); - if (position == Grammar::ExpressionEnd) // patterns of the form " ...." - runningPattern.advance(); - - // eat the first token - if (checkOnly) - pushSyntaxToken(runningPattern.getTokenType(m_tokenizer.getToken())); - runningPattern.advance(m_tokenizer.getToken()); - m_tokenizer.nextToken(); - expressionExpected = false; - - while (!runningPattern.isFinished(m_tokenizer.getToken())) { - if (runningPattern.expressionExpected()) { - // expression expected - runningPattern.advance(); - if (runningPattern.isFinished(m_tokenizer.getToken())) { - // pattern ended with an expression - expressionExpected = true; - break; - } - // parse a sub expression - if (!parseExpression(checkOnly)) { - return false; - } - } else { - // "terminal" expected - if (m_tokenizer.eos()) { - // EOS - if (runningPattern.isComplete(Token())) - break; - if (checkOnly) - pushSyntaxToken(Eos); - - m_errorString = "Uncompleted syntax"; - return false; - } - if (!runningPattern.matchToken(m_tokenizer.getToken())) { - // token mismatch - if (runningPattern.isComplete(m_tokenizer.getToken())) - break; - if (checkOnly) - pushSyntaxToken(Mismatch); - m_errorString = "Syntax error"; - return false; - } - // token matched - if (checkOnly) - pushSyntaxToken(runningPattern.getTokenType(m_tokenizer.getToken())); - runningPattern.advance(m_tokenizer.getToken()); - m_tokenizer.nextToken(); - } - } - - // pattern ended - if (expressionExpected) { - // pattern terminated with an expression - if (position == Grammar::ExpressionEnd) { - // "E op . E" - flushPatterns(runningPattern.getPriority(), stackMinIndex, checkOnly); - m_patternStack.push_back(runningPattern); - } else { - // "op . E" - m_patternStack.push_back(runningPattern); - } - m_position = position = Grammar::ExpressionStart; - } else { - // pattern terminates with a keyword - if (position == Grammar::ExpressionEnd) { - // "E op ." - flushPatterns(runningPattern.getPriority(), stackMinIndex, checkOnly); - } else { - // "leaf .", "f(E) .", "(E) ." - } - if (!checkOnly) - runningPattern.createNode(m_calculator, m_nodeStack); - count++; - m_position = position = Grammar::ExpressionEnd; - } - } - if (count == 0 || expressionExpected) { - - m_errorString = "Expression expected"; - return false; - } - flushPatterns(-1, stackMinIndex, checkOnly); - return true; +bool Parser::Imp::parseExpression(bool checkOnly) { + if (!m_grammar) return false; + int stackMinIndex = m_patternStack.size(); + int count = 0; + Grammar::Position position = Grammar::ExpressionStart; + m_position = position; + // warning: parseExpression() is called recursively. m_position is used after + // parseExpression() + // for diagnostic and suggestions. position is used in the actual parsing + + bool expressionExpected = true; + while (!m_tokenizer.eos()) { + // token, position -> pattern + const Pattern *pattern = + m_grammar->getPattern(position, m_tokenizer.getToken()); + if (!pattern) { + // no pattern found for the next token + if (position == Grammar::ExpressionEnd) { + // already found an expression + flushPatterns(-1, stackMinIndex, checkOnly); + return true; + } else { + // syntax error : expression not found + if (checkOnly) pushSyntaxToken(UnexpectedToken); + + m_errorString = "Unexpected token"; + return false; + } + } + // pattern found: start scanning it + RunningPattern runningPattern(pattern); + if (position == + Grammar::ExpressionEnd) // patterns of the form " ...." + runningPattern.advance(); + + // eat the first token + if (checkOnly) + pushSyntaxToken(runningPattern.getTokenType(m_tokenizer.getToken())); + runningPattern.advance(m_tokenizer.getToken()); + m_tokenizer.nextToken(); + expressionExpected = false; + + while (!runningPattern.isFinished(m_tokenizer.getToken())) { + if (runningPattern.expressionExpected()) { + // expression expected + runningPattern.advance(); + if (runningPattern.isFinished(m_tokenizer.getToken())) { + // pattern ended with an expression + expressionExpected = true; + break; + } + // parse a sub expression + if (!parseExpression(checkOnly)) { + return false; + } + } else { + // "terminal" expected + if (m_tokenizer.eos()) { + // EOS + if (runningPattern.isComplete(Token())) break; + if (checkOnly) pushSyntaxToken(Eos); + + m_errorString = "Uncompleted syntax"; + return false; + } + if (!runningPattern.matchToken(m_tokenizer.getToken())) { + // token mismatch + if (runningPattern.isComplete(m_tokenizer.getToken())) break; + if (checkOnly) pushSyntaxToken(Mismatch); + m_errorString = "Syntax error"; + return false; + } + // token matched + if (checkOnly) + pushSyntaxToken(runningPattern.getTokenType(m_tokenizer.getToken())); + runningPattern.advance(m_tokenizer.getToken()); + m_tokenizer.nextToken(); + } + } + + // pattern ended + if (expressionExpected) { + // pattern terminated with an expression + if (position == Grammar::ExpressionEnd) { + // "E op . E" + flushPatterns(runningPattern.getPriority(), stackMinIndex, checkOnly); + m_patternStack.push_back(runningPattern); + } else { + // "op . E" + m_patternStack.push_back(runningPattern); + } + m_position = position = Grammar::ExpressionStart; + } else { + // pattern terminates with a keyword + if (position == Grammar::ExpressionEnd) { + // "E op ." + flushPatterns(runningPattern.getPriority(), stackMinIndex, checkOnly); + } else { + // "leaf .", "f(E) .", "(E) ." + } + if (!checkOnly) runningPattern.createNode(m_calculator, m_nodeStack); + count++; + m_position = position = Grammar::ExpressionEnd; + } + } + if (count == 0 || expressionExpected) { + m_errorString = "Expression expected"; + return false; + } + flushPatterns(-1, stackMinIndex, checkOnly); + return true; } //------------------------------------------------------------------- -Calculator *Parser::parse(std::string text) -{ - m_imp->m_tokenizer.setBuffer(text); - clearPointerContainer(m_imp->m_nodeStack); - m_imp->m_errorString = ""; - m_imp->m_isValid = false; - m_imp->m_calculator = new Calculator(); - bool ret = m_imp->parseExpression(false); - if (ret && !m_imp->m_nodeStack.empty()) { - m_imp->m_calculator->setRootNode(m_imp->m_nodeStack.back()); - m_imp->m_nodeStack.pop_back(); - m_imp->m_isValid = true; - } else { - delete m_imp->m_calculator; - m_imp->m_calculator = 0; - } - clearPointerContainer(m_imp->m_nodeStack); - Calculator *calculator = m_imp->m_calculator; - m_imp->m_calculator = 0; - return calculator; +Calculator *Parser::parse(std::string text) { + m_imp->m_tokenizer.setBuffer(text); + clearPointerContainer(m_imp->m_nodeStack); + m_imp->m_errorString = ""; + m_imp->m_isValid = false; + m_imp->m_calculator = new Calculator(); + bool ret = m_imp->parseExpression(false); + if (ret && !m_imp->m_nodeStack.empty()) { + m_imp->m_calculator->setRootNode(m_imp->m_nodeStack.back()); + m_imp->m_nodeStack.pop_back(); + m_imp->m_isValid = true; + } else { + delete m_imp->m_calculator; + m_imp->m_calculator = 0; + } + clearPointerContainer(m_imp->m_nodeStack); + Calculator *calculator = m_imp->m_calculator; + m_imp->m_calculator = 0; + return calculator; } //------------------------------------------------------------------- -Parser::SyntaxStatus Parser::checkSyntax(std::vector &tokens, std::string text) -{ - m_imp->m_tokenizer.setBuffer(text); - if (m_imp->m_tokenizer.eos()) - return Incomplete; - bool ret = m_imp->parseExpression(true); - tokens = m_imp->m_syntaxTokens; - if (ret && m_imp->m_tokenizer.eos()) - return Correct; - if (tokens.empty()) - return Incomplete; - SyntaxToken &lastToken = tokens.back(); - if (lastToken.m_type == Eos) - return Incomplete; - - int k = lastToken.m_pos + lastToken.m_length; - if (k >= (int)text.length()) { - if (lastToken.m_type < Unknown) { - lastToken.m_type = Unknown; - } - return ExtraIgnored; - } - - SyntaxToken extraIgnored; - extraIgnored.m_type = Unknown; - extraIgnored.m_pos = k; - extraIgnored.m_length = text.length() - k; - tokens.push_back(extraIgnored); - - return Error; +Parser::SyntaxStatus Parser::checkSyntax(std::vector &tokens, + std::string text) { + m_imp->m_tokenizer.setBuffer(text); + if (m_imp->m_tokenizer.eos()) return Incomplete; + bool ret = m_imp->parseExpression(true); + tokens = m_imp->m_syntaxTokens; + if (ret && m_imp->m_tokenizer.eos()) return Correct; + if (tokens.empty()) return Incomplete; + SyntaxToken &lastToken = tokens.back(); + if (lastToken.m_type == Eos) return Incomplete; + + int k = lastToken.m_pos + lastToken.m_length; + if (k >= (int)text.length()) { + if (lastToken.m_type < Unknown) { + lastToken.m_type = Unknown; + } + return ExtraIgnored; + } + + SyntaxToken extraIgnored; + extraIgnored.m_type = Unknown; + extraIgnored.m_pos = k; + extraIgnored.m_length = text.length() - k; + tokens.push_back(extraIgnored); + + return Error; } //------------------------------------------------------------------- -void Parser::getSuggestions(Grammar::Suggestions &suggestions, std::string text) -{ - std::vector tokens; - Parser::SyntaxStatus status = checkSyntax(tokens, text); - suggestions.clear(); - if (status == Correct || status == Incomplete || status == ExtraIgnored) - m_imp->m_grammar->getSuggestions(suggestions, m_imp->m_position); +void Parser::getSuggestions(Grammar::Suggestions &suggestions, + std::string text) { + std::vector tokens; + Parser::SyntaxStatus status = checkSyntax(tokens, text); + suggestions.clear(); + if (status == Correct || status == Incomplete || status == ExtraIgnored) + m_imp->m_grammar->getSuggestions(suggestions, m_imp->m_position); } //------------------------------------------------------------------- -std::string Parser::getCurrentPatternString(std::string text) -{ - return "ohime"; +std::string Parser::getCurrentPatternString(std::string text) { + return "ohime"; } //------------------------------------------------------------------- -bool Parser::isValid() const -{ - return m_imp->m_isValid; -} +bool Parser::isValid() const { return m_imp->m_isValid; } //------------------------------------------------------------------- -std::string Parser::getText() const -{ - return m_imp->m_tokenizer.getBuffer(); -} +std::string Parser::getText() const { return m_imp->m_tokenizer.getBuffer(); } //------------------------------------------------------------------- -std::string Parser::getError() const -{ - return m_imp->m_errorString; -} +std::string Parser::getError() const { return m_imp->m_errorString; } //------------------------------------------------------------------- -std::pair Parser::getErrorPos() const -{ - if (m_imp->m_errorString == "") - return std::make_pair(0, -1); - Token token = m_imp->m_tokenizer.getToken(); - return std::make_pair(token.getPos(), token.getPos1()); +std::pair Parser::getErrorPos() const { + if (m_imp->m_errorString == "") return std::make_pair(0, -1); + Token token = m_imp->m_tokenizer.getToken(); + return std::make_pair(token.getPos(), token.getPos1()); } //------------------------------------------------------------------- -} // namespace TSyntax +} // namespace TSyntax diff --git a/toonz/sources/common/expressions/ttokenizer.cpp b/toonz/sources/common/expressions/ttokenizer.cpp index a8bac29..1c39fe1 100644 --- a/toonz/sources/common/expressions/ttokenizer.cpp +++ b/toonz/sources/common/expressions/ttokenizer.cpp @@ -3,204 +3,168 @@ #include "ttokenizer.h" #include -namespace TSyntax -{ +namespace TSyntax { -int Token::getIntValue() const -{ - return QString::fromStdString(getText()).toInt(); +int Token::getIntValue() const { + return QString::fromStdString(getText()).toInt(); } -double Token::getDoubleValue() const -{ - return QString::fromStdString(getText()).toDouble(); +double Token::getDoubleValue() const { + return QString::fromStdString(getText()).toDouble(); } //=================================================================== -Tokenizer::Tokenizer() - : m_buffer(), m_index(0) -{ -} +Tokenizer::Tokenizer() : m_buffer(), m_index(0) {} //------------------------------------------------------------------- -Tokenizer::Tokenizer(std::string buffer) - : m_buffer(), m_index(0) -{ - setBuffer(buffer); +Tokenizer::Tokenizer(std::string buffer) : m_buffer(), m_index(0) { + setBuffer(buffer); } //=================================================================== -Tokenizer::~Tokenizer() -{ -} +Tokenizer::~Tokenizer() {} //------------------------------------------------------------------- -void Tokenizer::setBuffer(std::string buffer) -{ - m_buffer = buffer + '\0'; - m_index = 0; - m_tokens.clear(); - - bool stringBlock = false; - - int i = 0; - const char *s = &m_buffer[0]; - for (;;) { - while (isascii(s[i]) && isspace(s[i])) - i++; - - int j = i; - - if (s[i] == '\0') { - m_tokens.push_back(Token("", Token::Eos, j)); - break; - } - - if (s[i] == '"') { - stringBlock = !stringBlock; - m_tokens.push_back(Token("\"", Token::Punct, j)); - - ++i; - continue; - } - - std::string token; - - if (stringBlock) { - // string block - read mercilessly until either another '"' or EOS - token = std::string(1, s[i++]); - - while (s[i] != '"' && s[i] != '\0') - token.append(1, s[i++]); - - m_tokens.push_back(Token(token, Token::Ident, j)); - } else if (isascii(s[i]) && isalpha(s[i]) || s[i] == '_') { - // ident - token = std::string(1, s[i++]); - - while (isascii(s[i]) && (isalpha(s[i]) || s[i] == '_' || isdigit(s[i]))) - token.append(1, s[i++]); - - m_tokens.push_back(Token(token, Token::Ident, j)); - } else if (isascii(s[i]) && isdigit(s[i]) || s[i] == '.') { - // number - while (isascii(s[i]) && isdigit(s[i])) - token.append(1, s[i++]); - - if (s[i] == '.') { - token.append(1, s[i++]); - - while (isascii(s[i]) && isdigit(s[i])) - token.append(1, s[i++]); - - if ((s[i] == 'e' || s[i] == 'E') && - (isascii(s[i + 1]) && isdigit(s[i + 1]) || - (s[i + 1] == '-' || s[i + 1] == '+') && - isascii(s[i + 2]) && isdigit(s[i + 2]))) { - token.append(1, s[i++]); - - if (s[i] == '-' || s[i] == '+') - token.append(1, s[i++]); - - while (isascii(s[i]) && isdigit(s[i])) - token.append(1, s[i++]); - } - } - m_tokens.push_back(Token(token, Token::Number, j)); - } else { - // punct. - if (s[i + 1] != '\0') { - token = std::string(s + i, 2); - - const std::string ss[] = { - "==", "!=", ">=", "<=", "||", "&&"}; - - const int m = tArrayCount(ss); - if (std::find(ss, ss + m, token) != ss + m) - i += 2; - else - token = std::string(1, s[i++]); - } else - token = std::string(1, s[i++]); - - m_tokens.push_back(Token(token, Token::Punct, j)); - } - } +void Tokenizer::setBuffer(std::string buffer) { + m_buffer = buffer + '\0'; + m_index = 0; + m_tokens.clear(); + + bool stringBlock = false; + + int i = 0; + const char *s = &m_buffer[0]; + for (;;) { + while (isascii(s[i]) && isspace(s[i])) i++; + + int j = i; + + if (s[i] == '\0') { + m_tokens.push_back(Token("", Token::Eos, j)); + break; + } + + if (s[i] == '"') { + stringBlock = !stringBlock; + m_tokens.push_back(Token("\"", Token::Punct, j)); + + ++i; + continue; + } + + std::string token; + + if (stringBlock) { + // string block - read mercilessly until either another '"' or EOS + token = std::string(1, s[i++]); + + while (s[i] != '"' && s[i] != '\0') token.append(1, s[i++]); + + m_tokens.push_back(Token(token, Token::Ident, j)); + } else if (isascii(s[i]) && isalpha(s[i]) || s[i] == '_') { + // ident + token = std::string(1, s[i++]); + + while (isascii(s[i]) && (isalpha(s[i]) || s[i] == '_' || isdigit(s[i]))) + token.append(1, s[i++]); + + m_tokens.push_back(Token(token, Token::Ident, j)); + } else if (isascii(s[i]) && isdigit(s[i]) || s[i] == '.') { + // number + while (isascii(s[i]) && isdigit(s[i])) token.append(1, s[i++]); + + if (s[i] == '.') { + token.append(1, s[i++]); + + while (isascii(s[i]) && isdigit(s[i])) token.append(1, s[i++]); + + if ((s[i] == 'e' || s[i] == 'E') && + (isascii(s[i + 1]) && isdigit(s[i + 1]) || + (s[i + 1] == '-' || s[i + 1] == '+') && isascii(s[i + 2]) && + isdigit(s[i + 2]))) { + token.append(1, s[i++]); + + if (s[i] == '-' || s[i] == '+') token.append(1, s[i++]); + + while (isascii(s[i]) && isdigit(s[i])) token.append(1, s[i++]); + } + } + m_tokens.push_back(Token(token, Token::Number, j)); + } else { + // punct. + if (s[i + 1] != '\0') { + token = std::string(s + i, 2); + + const std::string ss[] = {"==", "!=", ">=", "<=", "||", "&&"}; + + const int m = tArrayCount(ss); + if (std::find(ss, ss + m, token) != ss + m) + i += 2; + else + token = std::string(1, s[i++]); + } else + token = std::string(1, s[i++]); + + m_tokens.push_back(Token(token, Token::Punct, j)); + } + } } //------------------------------------------------------------------- -int Tokenizer::getTokenCount() const -{ - return m_tokens.size(); -} +int Tokenizer::getTokenCount() const { return m_tokens.size(); } //------------------------------------------------------------------- -const Token &Tokenizer::getToken(int index) const -{ - assert(0 <= index && index < getTokenCount()); - return m_tokens[index]; +const Token &Tokenizer::getToken(int index) const { + assert(0 <= index && index < getTokenCount()); + return m_tokens[index]; } //------------------------------------------------------------------- -void Tokenizer::reset() -{ - m_index = 0; -} +void Tokenizer::reset() { m_index = 0; } //------------------------------------------------------------------- -const Token &Tokenizer::getToken() -{ - return getToken(m_index); -} +const Token &Tokenizer::getToken() { return getToken(m_index); } //------------------------------------------------------------------- -Token Tokenizer::nextToken() -{ - Token token = getToken(); - if (m_index + 1 < getTokenCount()) - m_index++; - return token; +Token Tokenizer::nextToken() { + Token token = getToken(); + if (m_index + 1 < getTokenCount()) m_index++; + return token; } //------------------------------------------------------------------- -bool Tokenizer::eos() const -{ - return m_index + 1 == getTokenCount(); -} +bool Tokenizer::eos() const { return m_index + 1 == getTokenCount(); } //------------------------------------------------------------------- -Token Tokenizer::getTokenFromPos(int pos) const -{ - int len = m_buffer.length(); - if (pos < 0 || pos >= len) - return Token(pos); - int x = 0; - for (int i = 0; i < getTokenCount(); i++) { - const Token &token = getToken(i); - int y = token.getPos(); - if (pos < y) { - assert(x < y); - return Token(x, y - 1); - } - x = y + (int)token.getText().length(); - if (pos < x) - return token; - } - assert(x < len); - return Token(x, len - 1); +Token Tokenizer::getTokenFromPos(int pos) const { + int len = m_buffer.length(); + if (pos < 0 || pos >= len) return Token(pos); + int x = 0; + for (int i = 0; i < getTokenCount(); i++) { + const Token &token = getToken(i); + int y = token.getPos(); + if (pos < y) { + assert(x < y); + return Token(x, y - 1); + } + x = y + (int)token.getText().length(); + if (pos < x) return token; + } + assert(x < len); + return Token(x, len - 1); } //=================================================================== -} // TSyntax +} // TSyntax diff --git a/toonz/sources/common/psdlib/psd.cpp b/toonz/sources/common/psdlib/psd.cpp index b778bae..fb5452f 100644 --- a/toonz/sources/common/psdlib/psd.cpp +++ b/toonz/sources/common/psdlib/psd.cpp @@ -10,18 +10,22 @@ #include "tpixelutils.h" /* - The entire content of this file is ridden with LEAKS. A bug has been filed, will hopefully + The entire content of this file is ridden with LEAKS. A bug has been filed, + will hopefully be dealt with ASAP. - L'intero contenuto del file e' pieno di LEAK. Ho inserito la cosa in Bugilla e non ho potuto - fare altro sotto rilascio. Non solo, il codice dei distruttori e' SBAGLIATO - l'ho esplicitamente + L'intero contenuto del file e' pieno di LEAK. Ho inserito la cosa in Bugilla e + non ho potuto + fare altro sotto rilascio. Non solo, il codice dei distruttori e' SBAGLIATO - + l'ho esplicitamente disabilitato, tanto non era chiamato cmq. E' da rifare usando SMART POINTERS (boost::scoped_ptr<> o tcg::unique_ptr<>, o std::unique_ptr<> se facciamo l'upgrade del compilatore). - Da osservare che anche il campo FILE in TPSDReader leaka se viene sganciata un'eccezione... + Da osservare che anche il campo FILE in TPSDReader leaka se viene sganciata + un'eccezione... */ #define LEVEL_NAME_INDEX_SEP "@" @@ -29,1269 +33,1297 @@ //----forward declarations std::string buildErrorString(int error); -void readChannel(FILE *f, TPSDLayerInfo *li, - TPSDChannelInfo *chan, int channels, - TPSDHeaderInfo *h); +void readChannel(FILE *f, TPSDLayerInfo *li, TPSDChannelInfo *chan, + int channels, TPSDHeaderInfo *h); void readLongData(FILE *f, struct dictentry *parent, TPSDLayerInfo *li); void readByteData(FILE *f, struct dictentry *parent, TPSDLayerInfo *li); void readKey(FILE *f, struct dictentry *parent, TPSDLayerInfo *li); void readLayer16(FILE *f, struct dictentry *parent, TPSDLayerInfo *li); //----end forward declarations -char swapByte(unsigned char src) -{ - unsigned char out = 0; - for (int i = 0; i < 8; ++i) { - out = out << 1; - out |= (src & 1); - src = src >> 1; - } - return out; +char swapByte(unsigned char src) { + unsigned char out = 0; + for (int i = 0; i < 8; ++i) { + out = out << 1; + out |= (src & 1); + src = src >> 1; + } + return out; } -TPSDReader::TPSDReader(const TFilePath &path) : m_shrinkX(1), - m_shrinkY(1), - m_region(TRect()) -{ - m_layerId = 0; - QString name = path.getName().c_str(); - name.append(path.getDottedType().c_str()); - int sepPos = name.indexOf("#"); - int dotPos = name.indexOf(".", sepPos); - name.remove(sepPos, dotPos - sepPos); - m_path = path.getParentDir() + TFilePath(name.toStdString()); - //m_path = path; - QMutexLocker sl(&m_mutex); - openFile(); - if (!doInfo()) { - fclose(m_file); - throw TImageException(m_path, "Do PSD INFO ERROR"); - } - fclose(m_file); +TPSDReader::TPSDReader(const TFilePath &path) + : m_shrinkX(1), m_shrinkY(1), m_region(TRect()) { + m_layerId = 0; + QString name = path.getName().c_str(); + name.append(path.getDottedType().c_str()); + int sepPos = name.indexOf("#"); + int dotPos = name.indexOf(".", sepPos); + name.remove(sepPos, dotPos - sepPos); + m_path = path.getParentDir() + TFilePath(name.toStdString()); + // m_path = path; + QMutexLocker sl(&m_mutex); + openFile(); + if (!doInfo()) { + fclose(m_file); + throw TImageException(m_path, "Do PSD INFO ERROR"); + } + fclose(m_file); } -TPSDReader::~TPSDReader() -{ - /*for(int i=0; i 64 || m_headerInfo.rows <= 0 || - m_headerInfo.cols <= 0 || m_headerInfo.depth < 0 || m_headerInfo.depth > 32 || m_headerInfo.mode < 0) { - throw TImageException(m_path, "Reading PSD Header Info error"); - return false; - } - } else { - throw TImageException(m_path, "PSD Version not supported"); - return false; - } - } else { - throw TImageException(m_path, "Cannot read Header"); - return false; - } - return true; +bool TPSDReader::doHeaderInfo() { + fread(m_headerInfo.sig, 1, 4, m_file); + m_headerInfo.version = read2UBytes(m_file); + read4Bytes(m_file); + read2Bytes(m_file); // reserved[6]; + m_headerInfo.channels = read2UBytes(m_file); + m_headerInfo.rows = read4Bytes(m_file); + m_headerInfo.cols = read4Bytes(m_file); + m_headerInfo.depth = read2UBytes(m_file); + m_headerInfo.mode = read2UBytes(m_file); + + if (!feof(m_file) && !memcmp(m_headerInfo.sig, "8BPS", 4)) { + if (m_headerInfo.version == 1) { + if (m_headerInfo.channels <= 0 || m_headerInfo.channels > 64 || + m_headerInfo.rows <= 0 || m_headerInfo.cols <= 0 || + m_headerInfo.depth < 0 || m_headerInfo.depth > 32 || + m_headerInfo.mode < 0) { + throw TImageException(m_path, "Reading PSD Header Info error"); + return false; + } + } else { + throw TImageException(m_path, "PSD Version not supported"); + return false; + } + } else { + throw TImageException(m_path, "Cannot read Header"); + return false; + } + return true; } // Read Color Mode Data Block -bool TPSDReader::doColorModeData() -{ - m_headerInfo.colormodepos = ftell(m_file); - skipBlock(m_file); //skip "color mode data" - return true; +bool TPSDReader::doColorModeData() { + m_headerInfo.colormodepos = ftell(m_file); + skipBlock(m_file); // skip "color mode data" + return true; } // Read Image Resources Block -bool TPSDReader::doImageResources() -{ - //skipBlock(m_file); //skip "image resources" - long len = read4Bytes(m_file); // lunghezza del blocco Image resources - while (len > 0) { - char type[4], name[0x100]; - int id, namelen; - long size; - fread(type, 1, 4, m_file); - id = read2Bytes(m_file); - namelen = fgetc(m_file); - fread(name, 1, NEXT2(1 + namelen) - 1, m_file); - name[namelen] = 0; - size = read4Bytes(m_file); - if (id == 1005) // ResolutionInfo - { - psdByte savepos = ftell(m_file); - long hres, vres; - double hresd, vresd; - hresd = FIXDPI(hres = read4Bytes(m_file)); - read2Bytes(m_file); - read2Bytes(m_file); - vresd = FIXDPI(vres = read4Bytes(m_file)); - m_headerInfo.vres = vresd; - m_headerInfo.hres = hresd; - fseek(m_file, savepos, SEEK_SET); - } - len -= 4 + 2 + NEXT2(1 + namelen) + 4 + NEXT2(size); - fseek(m_file, NEXT2(size), SEEK_CUR); // skip resource block data - } - if (len != 0) - return false; - return true; +bool TPSDReader::doImageResources() { + // skipBlock(m_file); //skip "image resources" + long len = read4Bytes(m_file); // lunghezza del blocco Image resources + while (len > 0) { + char type[4], name[0x100]; + int id, namelen; + long size; + fread(type, 1, 4, m_file); + id = read2Bytes(m_file); + namelen = fgetc(m_file); + fread(name, 1, NEXT2(1 + namelen) - 1, m_file); + name[namelen] = 0; + size = read4Bytes(m_file); + if (id == 1005) // ResolutionInfo + { + psdByte savepos = ftell(m_file); + long hres, vres; + double hresd, vresd; + hresd = FIXDPI(hres = read4Bytes(m_file)); + read2Bytes(m_file); + read2Bytes(m_file); + vresd = FIXDPI(vres = read4Bytes(m_file)); + m_headerInfo.vres = vresd; + m_headerInfo.hres = hresd; + fseek(m_file, savepos, SEEK_SET); + } + len -= 4 + 2 + NEXT2(1 + namelen) + 4 + NEXT2(size); + fseek(m_file, NEXT2(size), SEEK_CUR); // skip resource block data + } + if (len != 0) return false; + return true; } // Read Layer Info Block (Layers Number and merged alpha) -bool TPSDReader::doLayerAndMaskInfo() -{ - psdByte layerlen; - - m_headerInfo.layersCount = 0; - m_headerInfo.lmilen = read4Bytes(m_file); - m_headerInfo.lmistart = ftell(m_file); - if (m_headerInfo.lmilen) { - // process layer info section - layerlen = read4Bytes(m_file); - m_headerInfo.linfoBlockEmpty = false; - m_headerInfo.mergedalpha = 0; - if (layerlen) { - doLayersInfo(); - } else { - //WARNING: layer info section empty - } - } else { - //WARNING: layer & mask info section empty - } - return true; +bool TPSDReader::doLayerAndMaskInfo() { + psdByte layerlen; + + m_headerInfo.layersCount = 0; + m_headerInfo.lmilen = read4Bytes(m_file); + m_headerInfo.lmistart = ftell(m_file); + if (m_headerInfo.lmilen) { + // process layer info section + layerlen = read4Bytes(m_file); + m_headerInfo.linfoBlockEmpty = false; + m_headerInfo.mergedalpha = 0; + if (layerlen) { + doLayersInfo(); + } else { + // WARNING: layer info section empty + } + } else { + // WARNING: layer & mask info section empty + } + return true; } // Read Layers Information Block // It is called by doLayerAndMaskInfo() -bool TPSDReader::doLayersInfo() -{ - m_headerInfo.layersCount = read2Bytes(m_file); - m_headerInfo.linfoBlockEmpty = false; - m_headerInfo.mergedalpha = m_headerInfo.layersCount < 0; - if (m_headerInfo.mergedalpha > 0) { - m_headerInfo.layersCount = -m_headerInfo.layersCount; - } - if (!m_headerInfo.linfoBlockEmpty) { - m_headerInfo.linfo = (TPSDLayerInfo *)mymalloc(m_headerInfo.layersCount * sizeof(struct TPSDLayerInfo)); - int i = 0; - for (i = 0; i < m_headerInfo.layersCount; i++) { - readLayerInfo(i); - } - } - return true; +bool TPSDReader::doLayersInfo() { + m_headerInfo.layersCount = read2Bytes(m_file); + m_headerInfo.linfoBlockEmpty = false; + m_headerInfo.mergedalpha = m_headerInfo.layersCount < 0; + if (m_headerInfo.mergedalpha > 0) { + m_headerInfo.layersCount = -m_headerInfo.layersCount; + } + if (!m_headerInfo.linfoBlockEmpty) { + m_headerInfo.linfo = (TPSDLayerInfo *)mymalloc( + m_headerInfo.layersCount * sizeof(struct TPSDLayerInfo)); + int i = 0; + for (i = 0; i < m_headerInfo.layersCount; i++) { + readLayerInfo(i); + } + } + return true; } -bool TPSDReader::readLayerInfo(int i) -{ - psdByte chlen, extralen, extrastart; - int j, chid, namelen; - TPSDLayerInfo *li = m_headerInfo.linfo + i; - - // process layer record - li->top = read4Bytes(m_file); - li->left = read4Bytes(m_file); - li->bottom = read4Bytes(m_file); - li->right = read4Bytes(m_file); - li->channels = read2UBytes(m_file); - - if (li->bottom < li->top || li->right < li->left || li->channels > 64) // sanity ck - { - // qualcosa è andato storto, skippo il livello - fseek(m_file, 6 * li->channels + 12, SEEK_CUR); - skipBlock(m_file); // skip "layer info: extra data"; - } else { - li->chan = (TPSDChannelInfo *)mymalloc(li->channels * sizeof(struct TPSDChannelInfo)); - li->chindex = (int *)mymalloc((li->channels + 2) * sizeof(int)); - li->chindex += 2; // - - for (j = -2; j < li->channels; ++j) - li->chindex[j] = -1; - - // fetch info on each of the layer's channels - for (j = 0; j < li->channels; ++j) { - chid = li->chan[j].id = read2Bytes(m_file); - chlen = li->chan[j].length = read4Bytes(m_file); - - if (chid >= -2 && chid < li->channels) - li->chindex[chid] = j; - else { - //WARNING: unexpected channel id - } - } - - fread(li->blend.sig, 1, 4, m_file); - fread(li->blend.key, 1, 4, m_file); - li->blend.opacity = fgetc(m_file); - li->blend.clipping = fgetc(m_file); - li->blend.flags = fgetc(m_file); - fgetc(m_file); // padding - - extralen = read4Bytes(m_file); - extrastart = ftell(m_file); - - // layer mask data - if ((li->mask.size = read4Bytes(m_file))) { - li->mask.top = read4Bytes(m_file); - li->mask.left = read4Bytes(m_file); - li->mask.bottom = read4Bytes(m_file); - li->mask.right = read4Bytes(m_file); - li->mask.default_colour = fgetc(m_file); - li->mask.flags = fgetc(m_file); - fseek(m_file, li->mask.size - 18, SEEK_CUR); // skip remainder - li->mask.rows = li->mask.bottom - li->mask.top; - li->mask.cols = li->mask.right - li->mask.left; - } else { - //no layer mask data - } - - skipBlock(m_file); // skip "layer blending ranges"; - - // layer name - li->nameno = (char *)malloc(16); - sprintf(li->nameno, "layer%d", i + 1); - namelen = fgetc(m_file); - li->name = (char *)mymalloc(NEXT4(namelen + 1)); - fread(li->name, 1, NEXT4(namelen + 1) - 1, m_file); - li->name[namelen] = 0; - if (namelen) { - if (li->name[0] == '.') - li->name[0] = '_'; - } - - // process layer's 'additional info' - - li->additionalpos = ftell(m_file); - li->additionallen = extrastart + extralen - li->additionalpos; - doExtraData(li, li->additionallen); - - // leave file positioned at end of layer's data - fseek(m_file, extrastart + extralen, SEEK_SET); - } - return true; +bool TPSDReader::readLayerInfo(int i) { + psdByte chlen, extralen, extrastart; + int j, chid, namelen; + TPSDLayerInfo *li = m_headerInfo.linfo + i; + + // process layer record + li->top = read4Bytes(m_file); + li->left = read4Bytes(m_file); + li->bottom = read4Bytes(m_file); + li->right = read4Bytes(m_file); + li->channels = read2UBytes(m_file); + + if (li->bottom < li->top || li->right < li->left || + li->channels > 64) // sanity ck + { + // qualcosa è andato storto, skippo il livello + fseek(m_file, 6 * li->channels + 12, SEEK_CUR); + skipBlock(m_file); // skip "layer info: extra data"; + } else { + li->chan = (TPSDChannelInfo *)mymalloc(li->channels * + sizeof(struct TPSDChannelInfo)); + li->chindex = (int *)mymalloc((li->channels + 2) * sizeof(int)); + li->chindex += 2; // + + for (j = -2; j < li->channels; ++j) li->chindex[j] = -1; + + // fetch info on each of the layer's channels + for (j = 0; j < li->channels; ++j) { + chid = li->chan[j].id = read2Bytes(m_file); + chlen = li->chan[j].length = read4Bytes(m_file); + + if (chid >= -2 && chid < li->channels) + li->chindex[chid] = j; + else { + // WARNING: unexpected channel id + } + } + + fread(li->blend.sig, 1, 4, m_file); + fread(li->blend.key, 1, 4, m_file); + li->blend.opacity = fgetc(m_file); + li->blend.clipping = fgetc(m_file); + li->blend.flags = fgetc(m_file); + fgetc(m_file); // padding + + extralen = read4Bytes(m_file); + extrastart = ftell(m_file); + + // layer mask data + if ((li->mask.size = read4Bytes(m_file))) { + li->mask.top = read4Bytes(m_file); + li->mask.left = read4Bytes(m_file); + li->mask.bottom = read4Bytes(m_file); + li->mask.right = read4Bytes(m_file); + li->mask.default_colour = fgetc(m_file); + li->mask.flags = fgetc(m_file); + fseek(m_file, li->mask.size - 18, SEEK_CUR); // skip remainder + li->mask.rows = li->mask.bottom - li->mask.top; + li->mask.cols = li->mask.right - li->mask.left; + } else { + // no layer mask data + } + + skipBlock(m_file); // skip "layer blending ranges"; + + // layer name + li->nameno = (char *)malloc(16); + sprintf(li->nameno, "layer%d", i + 1); + namelen = fgetc(m_file); + li->name = (char *)mymalloc(NEXT4(namelen + 1)); + fread(li->name, 1, NEXT4(namelen + 1) - 1, m_file); + li->name[namelen] = 0; + if (namelen) { + if (li->name[0] == '.') li->name[0] = '_'; + } + + // process layer's 'additional info' + + li->additionalpos = ftell(m_file); + li->additionallen = extrastart + extralen - li->additionalpos; + doExtraData(li, li->additionallen); + + // leave file positioned at end of layer's data + fseek(m_file, extrastart + extralen, SEEK_SET); + } + return true; } -void TPSDReader::doImage(TRasterP &rasP, int layerId) -{ - m_layerId = layerId; - int layerIndex = getLayerInfoIndexById(layerId); - TPSDLayerInfo *li = getLayerInfo(layerIndex); - psdByte imageDataEnd; - // retrieve start data pos - psdByte startPos = ftell(m_file); - if (m_headerInfo.layersCount > 0) { - struct TPSDLayerInfo *lilast = &m_headerInfo.linfo[m_headerInfo.layersCount - 1]; - startPos = lilast->additionalpos + lilast->additionallen; - } - if (layerIndex > 0) { - for (int j = 0; j < layerIndex; j++) { - struct TPSDLayerInfo *liprev = &m_headerInfo.linfo[j]; - for (int ch = 0; ch < liprev->channels; ch++) { - startPos += liprev->chan[ch].length; - } - } - } - fseek(m_file, startPos, SEEK_SET); - - long pixw = li ? li->right - li->left : m_headerInfo.cols; - long pixh = li ? li->bottom - li->top : m_headerInfo.rows; - int channels = li ? li->channels : m_headerInfo.channels; - - if (li == NULL) - fseek(m_file, m_headerInfo.lmistart + m_headerInfo.lmilen, SEEK_SET); - - psdPixel rows = pixh; - psdPixel cols = pixw; - - int ch = 0; - psdByte **rowpos; - - rowpos = (psdByte **)mymalloc(channels * sizeof(psdByte *)); - - for (ch = 0; ch < channels; ++ch) { - psdPixel chrows = li && !m_headerInfo.linfoBlockEmpty && li->chan[ch].id == -2 ? li->mask.rows : rows; - rowpos[ch] = (psdByte *)mymalloc((chrows + 1) * sizeof(psdByte)); - } - - int tnzchannels = 0; - - int depth = m_headerInfo.depth; - switch (m_headerInfo.mode) { - //default: // multichannel, cmyk, lab etc - // split = 1; - case ModeBitmap: - case ModeGrayScale: - case ModeGray16: - case ModeDuotone: - case ModeDuotone16: - tnzchannels = 1; - // check if there is an alpha channel, or if merged data has alpha - if (li ? li->chindex[-1] != -1 : channels > 1 && m_headerInfo.mergedalpha) { - tnzchannels = 2; - } - break; - case ModeIndexedColor: - tnzchannels = 1; - break; - case ModeRGBColor: - case ModeRGB48: - tnzchannels = 3; - if (li ? li->chindex[-1] != -1 : channels > 3 && m_headerInfo.mergedalpha) { - tnzchannels = 4; - } - break; - default: - tnzchannels = channels; - //assert(0); - break; - } - - if (!li || m_headerInfo.linfoBlockEmpty) { // merged channel - TPSDChannelInfo *mergedChans = (TPSDChannelInfo *)mymalloc(channels * sizeof(struct TPSDChannelInfo)); - - readChannel(m_file, NULL, mergedChans, channels, &m_headerInfo); - imageDataEnd = ftell(m_file); - readImageData(rasP, NULL, mergedChans, tnzchannels, rows, cols); - free(mergedChans); - } else { - for (ch = 0; ch < channels; ++ch) { - readChannel(m_file, li, li->chan + ch, 1, &m_headerInfo); - } - imageDataEnd = ftell(m_file); - readImageData(rasP, li, li->chan, tnzchannels, rows, cols); - } - fseek(m_file, imageDataEnd, SEEK_SET); - - for (ch = 0; ch < channels; ++ch) - free(rowpos[ch]); - free(rowpos); +void TPSDReader::doImage(TRasterP &rasP, int layerId) { + m_layerId = layerId; + int layerIndex = getLayerInfoIndexById(layerId); + TPSDLayerInfo *li = getLayerInfo(layerIndex); + psdByte imageDataEnd; + // retrieve start data pos + psdByte startPos = ftell(m_file); + if (m_headerInfo.layersCount > 0) { + struct TPSDLayerInfo *lilast = + &m_headerInfo.linfo[m_headerInfo.layersCount - 1]; + startPos = lilast->additionalpos + lilast->additionallen; + } + if (layerIndex > 0) { + for (int j = 0; j < layerIndex; j++) { + struct TPSDLayerInfo *liprev = &m_headerInfo.linfo[j]; + for (int ch = 0; ch < liprev->channels; ch++) { + startPos += liprev->chan[ch].length; + } + } + } + fseek(m_file, startPos, SEEK_SET); + + long pixw = li ? li->right - li->left : m_headerInfo.cols; + long pixh = li ? li->bottom - li->top : m_headerInfo.rows; + int channels = li ? li->channels : m_headerInfo.channels; + + if (li == NULL) + fseek(m_file, m_headerInfo.lmistart + m_headerInfo.lmilen, SEEK_SET); + + psdPixel rows = pixh; + psdPixel cols = pixw; + + int ch = 0; + psdByte **rowpos; + + rowpos = (psdByte **)mymalloc(channels * sizeof(psdByte *)); + + for (ch = 0; ch < channels; ++ch) { + psdPixel chrows = + li && !m_headerInfo.linfoBlockEmpty && li->chan[ch].id == -2 + ? li->mask.rows + : rows; + rowpos[ch] = (psdByte *)mymalloc((chrows + 1) * sizeof(psdByte)); + } + + int tnzchannels = 0; + + int depth = m_headerInfo.depth; + switch (m_headerInfo.mode) { + // default: // multichannel, cmyk, lab etc + // split = 1; + case ModeBitmap: + case ModeGrayScale: + case ModeGray16: + case ModeDuotone: + case ModeDuotone16: + tnzchannels = 1; + // check if there is an alpha channel, or if merged data has alpha + if (li ? li->chindex[-1] != -1 : channels > 1 && m_headerInfo.mergedalpha) { + tnzchannels = 2; + } + break; + case ModeIndexedColor: + tnzchannels = 1; + break; + case ModeRGBColor: + case ModeRGB48: + tnzchannels = 3; + if (li ? li->chindex[-1] != -1 : channels > 3 && m_headerInfo.mergedalpha) { + tnzchannels = 4; + } + break; + default: + tnzchannels = channels; + // assert(0); + break; + } + + if (!li || m_headerInfo.linfoBlockEmpty) { // merged channel + TPSDChannelInfo *mergedChans = + (TPSDChannelInfo *)mymalloc(channels * sizeof(struct TPSDChannelInfo)); + + readChannel(m_file, NULL, mergedChans, channels, &m_headerInfo); + imageDataEnd = ftell(m_file); + readImageData(rasP, NULL, mergedChans, tnzchannels, rows, cols); + free(mergedChans); + } else { + for (ch = 0; ch < channels; ++ch) { + readChannel(m_file, li, li->chan + ch, 1, &m_headerInfo); + } + imageDataEnd = ftell(m_file); + readImageData(rasP, li, li->chan, tnzchannels, rows, cols); + } + fseek(m_file, imageDataEnd, SEEK_SET); + + for (ch = 0; ch < channels; ++ch) free(rowpos[ch]); + free(rowpos); } -void TPSDReader::load(TRasterImageP &img, int layerId) -{ - QMutexLocker sl(&m_mutex); - TPSDLayerInfo *li = NULL; - int layerIndex = 0; - if (layerId > 0) { - layerIndex = getLayerInfoIndexById(layerId); - li = getLayerInfo(layerIndex); - } - if (layerId < 0) - throw TImageException(m_path, "Layer ID not exists"); - - if (m_headerInfo.mode == 4 || m_headerInfo.depth == 32) { - img = TRasterImageP(); - return; - } - - try { - TRasterP rasP; - openFile(); - doImage(rasP, layerId); - fclose(m_file); - /* - // do savebox - long sbx0 = li ? li->left : 0; - long sby0 = li ? m_headerInfo.rows-li->bottom : 0; - long sbx1 = li ? li->right - 1 : m_headerInfo.cols - 1; - long sby1 = li ? m_headerInfo.rows - li->top - 1 : m_headerInfo.rows - 1; - TRect layerSaveBox; - layerSaveBox = TRect(sbx0,sby0,sbx1,sby1); - TRect imageRect = TRect(0,0,m_headerInfo.cols-1,m_headerInfo.rows-1); - // E' possibile che il layer sia in parte o tutto al di fuori della'immagine - // in questo caso considero solo la parte visibile, cioè che rientra nell'immagine. - // Se è tutta fuori restutuisco TRasterImageP() - layerSaveBox *= imageRect; - - if(layerSaveBox== TRect()) { - img = TRasterImageP(); - return; - } */ - - if (!rasP) { - img = TRasterImageP(); - return; - } // Happens if layer image has 0 rows and (or?) - // cols (dont ask me why, but I've seen it) - TRect layerSaveBox = m_layersSavebox[layerId]; - TRect savebox(layerSaveBox); - TDimension imgSize(rasP->getLx(), rasP->getLy()); - assert(TRect(imgSize).contains(savebox)); - - if (TRasterGR8P ras = rasP) { - TPixelGR8 bgColor; - ras->fillOutside(savebox, bgColor); - img = TRasterImageP(ras); - } else if (TRaster32P ras = rasP) { - TPixel32 bgColor(0, 0, 0, 0); - if (savebox != TRect()) - ras->fillOutside(savebox, bgColor); - else - ras->fill(bgColor); - img = TRasterImageP(ras); - } else if ((TRaster64P)rasP) { - TRaster32P raux(rasP->getLx(), rasP->getLy()); - TRop::convert(raux, rasP); - TPixel32 bgColor(0, 0, 0, 0); - raux->fillOutside(savebox, bgColor); - img = TRasterImageP(raux); - } else { - throw TImageException(m_path, "Invalid Raster"); - } - img->setDpi(m_headerInfo.hres, m_headerInfo.vres); - img->setSavebox(savebox); - } catch (...) { - } +void TPSDReader::load(TRasterImageP &img, int layerId) { + QMutexLocker sl(&m_mutex); + TPSDLayerInfo *li = NULL; + int layerIndex = 0; + if (layerId > 0) { + layerIndex = getLayerInfoIndexById(layerId); + li = getLayerInfo(layerIndex); + } + if (layerId < 0) throw TImageException(m_path, "Layer ID not exists"); + + if (m_headerInfo.mode == 4 || m_headerInfo.depth == 32) { + img = TRasterImageP(); + return; + } + + try { + TRasterP rasP; + openFile(); + doImage(rasP, layerId); + fclose(m_file); + /* + // do savebox + long sbx0 = li ? li->left : 0; + long sby0 = li ? m_headerInfo.rows-li->bottom : 0; + long sbx1 = li ? li->right - 1 : m_headerInfo.cols - 1; + long sby1 = li ? m_headerInfo.rows - li->top - 1 : m_headerInfo.rows - 1; + TRect layerSaveBox; + layerSaveBox = TRect(sbx0,sby0,sbx1,sby1); + TRect imageRect = TRect(0,0,m_headerInfo.cols-1,m_headerInfo.rows-1); + // E' possibile che il layer sia in parte o tutto al di fuori della'immagine + // in questo caso considero solo la parte visibile, cioè che rientra + nell'immagine. + // Se è tutta fuori restutuisco TRasterImageP() + layerSaveBox *= imageRect; + + if(layerSaveBox== TRect()) { + img = TRasterImageP(); + return; + } */ + + if (!rasP) { + img = TRasterImageP(); + return; + } // Happens if layer image has 0 rows and (or?) + // cols (dont ask me why, but I've seen it) + TRect layerSaveBox = m_layersSavebox[layerId]; + TRect savebox(layerSaveBox); + TDimension imgSize(rasP->getLx(), rasP->getLy()); + assert(TRect(imgSize).contains(savebox)); + + if (TRasterGR8P ras = rasP) { + TPixelGR8 bgColor; + ras->fillOutside(savebox, bgColor); + img = TRasterImageP(ras); + } else if (TRaster32P ras = rasP) { + TPixel32 bgColor(0, 0, 0, 0); + if (savebox != TRect()) + ras->fillOutside(savebox, bgColor); + else + ras->fill(bgColor); + img = TRasterImageP(ras); + } else if ((TRaster64P)rasP) { + TRaster32P raux(rasP->getLx(), rasP->getLy()); + TRop::convert(raux, rasP); + TPixel32 bgColor(0, 0, 0, 0); + raux->fillOutside(savebox, bgColor); + img = TRasterImageP(raux); + } else { + throw TImageException(m_path, "Invalid Raster"); + } + img->setDpi(m_headerInfo.hres, m_headerInfo.vres); + img->setSavebox(savebox); + } catch (...) { + } } -int TPSDReader::getLayerInfoIndexById(int layerId) -{ - int layerIndex = -1; - for (int i = 0; i < m_headerInfo.layersCount; i++) { - TPSDLayerInfo *litemp = m_headerInfo.linfo + i; - if (litemp->layerId == layerId) { - layerIndex = i; - break; - } - } - if (layerIndex < 0 && layerId != 0) - throw TImageException(m_path, "Layer ID not exists"); - return layerIndex; +int TPSDReader::getLayerInfoIndexById(int layerId) { + int layerIndex = -1; + for (int i = 0; i < m_headerInfo.layersCount; i++) { + TPSDLayerInfo *litemp = m_headerInfo.linfo + i; + if (litemp->layerId == layerId) { + layerIndex = i; + break; + } + } + if (layerIndex < 0 && layerId != 0) + throw TImageException(m_path, "Layer ID not exists"); + return layerIndex; } -TPSDLayerInfo *TPSDReader::getLayerInfo(int index) -{ - if (index < 0 || index >= m_headerInfo.layersCount) - return NULL; - return m_headerInfo.linfo + index; +TPSDLayerInfo *TPSDReader::getLayerInfo(int index) { + if (index < 0 || index >= m_headerInfo.layersCount) return NULL; + return m_headerInfo.linfo + index; } -TPSDHeaderInfo TPSDReader::getPSDHeaderInfo() -{ - return m_headerInfo; +TPSDHeaderInfo TPSDReader::getPSDHeaderInfo() { return m_headerInfo; } + +void TPSDReader::readImageData(TRasterP &rasP, TPSDLayerInfo *li, + TPSDChannelInfo *chan, int chancount, + psdPixel rows, psdPixel cols) { + int channels = li ? li->channels : m_headerInfo.channels; + + short depth = m_headerInfo.depth; + + psdByte savepos = ftell(m_file); + if (rows == 0 || cols == 0) return; + psdPixel j; + + unsigned char *inrows[4], *rledata; + + int ch, map[4]; + + rledata = (unsigned char *)mymalloc(chan->rowbytes * 2); + + for (ch = 0; ch < chancount; ++ch) { + inrows[ch] = (unsigned char *)mymalloc(chan->rowbytes); + map[ch] = li && chancount > 1 ? li->chindex[ch] : ch; + } + + // find the alpha channel, if needed + if (li && (chancount == 2 || chancount == 4)) { // grey+alpha + if (li->chindex[-1] == -1) { + // WARNING no alpha found?; + } else + map[chancount - 1] = li->chindex[-1]; + } + + // region dimensions with shrink + // x0 e x1 non tengono conto dello shrink. + int x0 = 0; + int x1 = m_headerInfo.cols - 1; + int y0 = 0; + int y1 = m_headerInfo.rows - 1; + + if (!m_region.isEmpty()) { + x0 = m_region.getP00().x; + // se x0 è fuori dalle dimensioni dell'immagine ritorna un'immagine vuota + if (x0 >= m_headerInfo.cols) { + free(rledata); + return; + } + x1 = x0 + m_region.getLx() - 1; + // controllo che x1 rimanga all'interno dell'immagine + if (x1 >= m_headerInfo.cols) x1 = m_headerInfo.cols - 1; + y0 = m_region.getP00().y; + // se y0 è fuori dalle dimensioni dell'immagine ritorna un'immagine vuota + if (y0 >= m_headerInfo.rows) { + free(rledata); + return; + } + y1 = y0 + m_region.getLy() - 1; + // controllo che y1 rimanga all'interno dell'immagine + if (y1 >= m_headerInfo.rows) y1 = m_headerInfo.rows - 1; + } + if (m_shrinkX > x1 - x0) m_shrinkX = x1 - x0; + if (m_shrinkY > y1 - y0) m_shrinkY = y1 - y0; + assert(m_shrinkX > 0 && m_shrinkY > 0); + if (m_shrinkX > 1) { + x1 -= (x1 - x0) % m_shrinkX; + } + if (m_shrinkY > 1) { + y1 -= (y1 - y0) % m_shrinkY; + } + assert(x0 <= x1 && y0 <= y1); + + TDimension imgSize((x1 - x0) / m_shrinkX + 1, (y1 - y0) / m_shrinkY + 1); + if (depth == 1 && chancount == 1) { + rasP = TRasterGR8P(imgSize); + } else if (depth == 8 && chancount > 1) { + rasP = TRaster32P(imgSize); + } else if (m_headerInfo.depth == 8 && chancount == 1) { + rasP = TRasterGR8P(imgSize); + } else if (m_headerInfo.depth == 16 && chancount == 1 && + m_headerInfo.mergedalpha) { + rasP = TRasterGR8P(imgSize); + } else if (m_headerInfo.depth == 16) { + rasP = TRaster64P(imgSize); + } + + // do savebox + // calcolo la savebox in coordinate dell'immagine + long sbx0 = li ? li->left - x0 : 0; + long sby0 = li ? m_headerInfo.rows - li->bottom - y0 : 0; + long sbx1 = li ? li->right - 1 - x0 : x1 - x0; + long sby1 = li ? m_headerInfo.rows - li->top - 1 - y0 : y1 - y0; + + TRect layerSaveBox; + layerSaveBox = TRect(sbx0, sby0, sbx1, sby1); + + TRect imageRect; + if (!m_region.isEmpty()) + imageRect = TRect(0, 0, m_region.getLx() - 1, m_region.getLy() - 1); + else + imageRect = TRect(0, 0, m_headerInfo.cols - 1, m_headerInfo.rows - 1); + // E' possibile che il layer sia in parte o tutto al di fuori della'immagine + // in questo caso considero solo la parte visibile, cioè che rientra + // nell'immagine. + // Se è tutta fuori restutuisco TRasterImageP() + layerSaveBox *= imageRect; + + if (layerSaveBox == TRect() || layerSaveBox.isEmpty()) { + free(rledata); + return; + } + // Estraggo da rasP solo il rettangolo che si interseca con il livello + // corrente + // stando attento a prendere i pixel giusti. + int firstXPixIndexOfLayer = layerSaveBox.getP00().x - 1 + m_shrinkX - + (abs(layerSaveBox.getP00().x - 1) % m_shrinkX); + int lrx0 = firstXPixIndexOfLayer / m_shrinkX; + int firstLineIndexOfLayer = layerSaveBox.getP00().y - 1 + m_shrinkY - + (abs(layerSaveBox.getP00().y - 1) % m_shrinkY); + int lry0 = firstLineIndexOfLayer / m_shrinkY; + int lrx1 = + (layerSaveBox.getP11().x - abs(layerSaveBox.getP11().x % m_shrinkX)) / + m_shrinkX; + int lry1 = + (layerSaveBox.getP11().y - abs(layerSaveBox.getP11().y % m_shrinkY)) / + m_shrinkY; + TRect layerSaveBox2 = TRect(lrx0, lry0, lrx1, lry1); + if (layerSaveBox2.isEmpty()) return; + assert(TRect(imgSize).contains(layerSaveBox2)); + if (li) + m_layersSavebox[li->layerId] = layerSaveBox2; + else + m_layersSavebox[0] = layerSaveBox2; + TRasterP smallRas = rasP->extract(layerSaveBox2); + assert(smallRas); + if (!smallRas) return; + // Trovo l'indice di colonna del primo pixel del livello che deve essere letto + // L'indice è riferito al livello. + int colOffset = firstXPixIndexOfLayer - layerSaveBox.getP00().x; + assert(colOffset >= 0); + // Trovo l'indice della prima riga del livello che deve essere letta + // L'indice è riferito al livello. + // Nota che nel file photoshop le righe sono memorizzate dall'ultima alla + // prima. + int rowOffset = abs(sby1) % m_shrinkY; + int rowCount = rowOffset; + // if(m_shrinkY==3) rowCount--; + for (j = 0; j < smallRas->getLy(); j++) { + for (ch = 0; ch < chancount; ++ch) { + /* get row data */ + if (map[ch] < 0 || map[ch] > chancount) { + // warn("bad map[%d]=%d, skipping a channel", i, map[i]); + memset(inrows[ch], 0, chan->rowbytes); // zero out the row + } else + readrow(m_file, chan + map[ch], rowCount, inrows[ch], rledata); + } + // se la riga corrente non rientra nell'immagine salto la copia + if (sby1 - rowCount < 0 || sby1 - rowCount > m_headerInfo.rows - 1) { + rowCount += m_shrinkY; + continue; + } + if (depth == 1 && chancount == 1) { + if (!(layerSaveBox.getP00().x - sbx0 >= 0 && + layerSaveBox.getP00().x - sbx0 + smallRas->getLx() / 8 - 1 < + chan->rowbytes)) + throw TImageException( + m_path, "Unable to read image with this depth and channels values"); + smallRas->lock(); + unsigned char *rawdata = + (unsigned char *)smallRas->getRawData(0, smallRas->getLy() - j - 1); + TPixelGR8 *pix = (TPixelGR8 *)rawdata; + int colCount = colOffset; + for (int k = 0; k < smallRas->getLx(); k += 8) { + char value = ~inrows[0][layerSaveBox.getP00().x - sbx0 + colCount]; + pix[k].setValue(value); + pix[k + 1].setValue(value); + pix[k + 2].setValue(value); + pix[k + 3].setValue(value); + pix[k + 4].setValue(value); + pix[k + 5].setValue(value); + pix[k + 6].setValue(value); + pix[k + 7].setValue(value); + colCount += m_shrinkX; + } + smallRas->unlock(); + } else if (depth == 8 && chancount > 1) { + if (!(layerSaveBox.getP00().x - sbx0 >= 0 && + layerSaveBox.getP00().x - sbx0 + smallRas->getLx() - 1 < + chan->rowbytes)) + throw TImageException( + m_path, "Unable to read image with this depth and channels values"); + smallRas->lock(); + unsigned char *rawdata = + (unsigned char *)smallRas->getRawData(0, smallRas->getLy() - j - 1); + TPixel32 *pix = (TPixel32 *)rawdata; + int colCount = colOffset; + for (int k = 0; k < smallRas->getLx(); k++) { + if (chancount >= 3) { + pix[k].r = inrows[0][layerSaveBox.getP00().x - sbx0 + colCount]; + pix[k].g = inrows[1][layerSaveBox.getP00().x - sbx0 + colCount]; + pix[k].b = inrows[2][layerSaveBox.getP00().x - sbx0 + colCount]; + if (chancount == 4) // RGB + alpha + pix[k].m = inrows[3][layerSaveBox.getP00().x - sbx0 + colCount]; + else + pix[k].m = 255; + } else if (chancount <= 2) // gray + alpha + { + pix[k].r = inrows[0][layerSaveBox.getP00().x - sbx0 + colCount]; + pix[k].g = inrows[0][layerSaveBox.getP00().x - sbx0 + colCount]; + pix[k].b = inrows[0][layerSaveBox.getP00().x - sbx0 + colCount]; + if (chancount == 2) + pix[k].m = inrows[1][layerSaveBox.getP00().x - sbx0 + colCount]; + else + pix[k].m = 255; + } + colCount += m_shrinkX; + } + + smallRas->unlock(); + } else if (m_headerInfo.depth == 8 && chancount == 1) { + if (!(layerSaveBox.getP00().x - sbx0 >= 0 && + layerSaveBox.getP00().x - sbx0 + smallRas->getLx() - 1 < + chan->rowbytes)) + throw TImageException( + m_path, "Unable to read image with this depth and channels values"); + smallRas->lock(); + unsigned char *rawdata = + (unsigned char *)smallRas->getRawData(0, smallRas->getLy() - j - 1); + + TPixelGR8 *pix = (TPixelGR8 *)rawdata; + int colCount = colOffset; + for (int k = 0; k < smallRas->getLx(); k++) { + pix[k].setValue(inrows[0][layerSaveBox.getP00().x - sbx0 + colCount]); + colCount += m_shrinkX; + } + smallRas->unlock(); + } else if (m_headerInfo.depth == 16 && chancount == 1 && + m_headerInfo.mergedalpha) // mergedChannels + { + if (!(layerSaveBox.getP00().x - sbx0 >= 0 && + layerSaveBox.getP00().x - sbx0 + smallRas->getLx() - 1 < + chan->rowbytes)) + throw TImageException( + m_path, "Unable to read image with this depth and channels values"); + smallRas->lock(); + unsigned char *rawdata = + (unsigned char *)smallRas->getRawData(0, smallRas->getLy() - j - 1); + TPixelGR8 *pix = (TPixelGR8 *)rawdata; + int colCount = colOffset; + for (int k = 0; k < smallRas->getLx(); k++) { + pix[k].setValue(inrows[0][layerSaveBox.getP00().x - sbx0 + colCount]); + colCount += m_shrinkX; + } + smallRas->unlock(); + } else if (m_headerInfo.depth == 16) { + if (!(layerSaveBox.getP00().x - sbx0 >= 0 && + layerSaveBox.getP00().x - sbx0 + smallRas->getLx() - 1 < + chan->rowbytes)) + throw TImageException( + m_path, "Unable to read image with this depth and channels values"); + smallRas->lock(); + unsigned short *rawdata = + (unsigned short *)smallRas->getRawData(0, smallRas->getLy() - j - 1); + TPixel64 *pix = (TPixel64 *)rawdata; + int colCount = colOffset; + for (int k = 0; k < smallRas->getLx(); k++) { + if (chancount >= 3) { + pix[k].r = swapShort( + ((psdUint16 *) + inrows[0])[layerSaveBox.getP00().x - sbx0 + colCount]); + pix[k].g = swapShort( + ((psdUint16 *) + inrows[1])[layerSaveBox.getP00().x - sbx0 + colCount]); + pix[k].b = swapShort( + ((psdUint16 *) + inrows[2])[layerSaveBox.getP00().x - sbx0 + colCount]); + } else if (chancount <= 2) { + pix[k].r = swapShort( + ((psdUint16 *) + inrows[0])[layerSaveBox.getP00().x - sbx0 + colCount]); + pix[k].g = swapShort( + ((psdUint16 *) + inrows[0])[layerSaveBox.getP00().x - sbx0 + colCount]); + pix[k].b = swapShort( + ((psdUint16 *) + inrows[0])[layerSaveBox.getP00().x - sbx0 + colCount]); + if (chancount == 2) + pix[k].m = swapShort( + ((psdUint16 *) + inrows[1])[layerSaveBox.getP00().x - sbx0 + colCount]); + } + if (chancount == 4) { + pix[k].m = swapShort( + ((psdUint16 *) + inrows[3])[layerSaveBox.getP00().x - sbx0 + colCount]); + } else + pix[k].m = 0xffff; + colCount += m_shrinkX; + } + smallRas->unlock(); + } else { + throw TImageException( + m_path, "Unable to read image with this depth and channels values"); + } + rowCount += m_shrinkY; + } + fseek(m_file, savepos, SEEK_SET); // restoring filepos + + free(rledata); + for (ch = 0; ch < chancount; ++ch) free(inrows[ch]); } -void TPSDReader::readImageData(TRasterP &rasP, TPSDLayerInfo *li, TPSDChannelInfo *chan, - int chancount, psdPixel rows, psdPixel cols) -{ - int channels = li ? li->channels : m_headerInfo.channels; - - short depth = m_headerInfo.depth; - - psdByte savepos = ftell(m_file); - if (rows == 0 || cols == 0) - return; - psdPixel j; - - unsigned char *inrows[4], *rledata; - - int ch, map[4]; - - rledata = (unsigned char *)mymalloc(chan->rowbytes * 2); - - for (ch = 0; ch < chancount; ++ch) { - inrows[ch] = (unsigned char *)mymalloc(chan->rowbytes); - map[ch] = li && chancount > 1 ? li->chindex[ch] : ch; - } - - // find the alpha channel, if needed - if (li && (chancount == 2 || chancount == 4)) { // grey+alpha - if (li->chindex[-1] == -1) { - //WARNING no alpha found?; - } else - map[chancount - 1] = li->chindex[-1]; - } - - // region dimensions with shrink - // x0 e x1 non tengono conto dello shrink. - int x0 = 0; - int x1 = m_headerInfo.cols - 1; - int y0 = 0; - int y1 = m_headerInfo.rows - 1; - - if (!m_region.isEmpty()) { - x0 = m_region.getP00().x; - // se x0 è fuori dalle dimensioni dell'immagine ritorna un'immagine vuota - if (x0 >= m_headerInfo.cols) { - free(rledata); - return; - } - x1 = x0 + m_region.getLx() - 1; - // controllo che x1 rimanga all'interno dell'immagine - if (x1 >= m_headerInfo.cols) - x1 = m_headerInfo.cols - 1; - y0 = m_region.getP00().y; - // se y0 è fuori dalle dimensioni dell'immagine ritorna un'immagine vuota - if (y0 >= m_headerInfo.rows) { - free(rledata); - return; - } - y1 = y0 + m_region.getLy() - 1; - // controllo che y1 rimanga all'interno dell'immagine - if (y1 >= m_headerInfo.rows) - y1 = m_headerInfo.rows - 1; - } - if (m_shrinkX > x1 - x0) - m_shrinkX = x1 - x0; - if (m_shrinkY > y1 - y0) - m_shrinkY = y1 - y0; - assert(m_shrinkX > 0 && m_shrinkY > 0); - if (m_shrinkX > 1) { - x1 -= (x1 - x0) % m_shrinkX; - } - if (m_shrinkY > 1) { - y1 -= (y1 - y0) % m_shrinkY; - } - assert(x0 <= x1 && y0 <= y1); - - TDimension imgSize((x1 - x0) / m_shrinkX + 1, (y1 - y0) / m_shrinkY + 1); - if (depth == 1 && chancount == 1) { - rasP = TRasterGR8P(imgSize); - } else if (depth == 8 && chancount > 1) { - rasP = TRaster32P(imgSize); - } else if (m_headerInfo.depth == 8 && chancount == 1) { - rasP = TRasterGR8P(imgSize); - } else if (m_headerInfo.depth == 16 && chancount == 1 && m_headerInfo.mergedalpha) { - rasP = TRasterGR8P(imgSize); - } else if (m_headerInfo.depth == 16) { - rasP = TRaster64P(imgSize); - } - - // do savebox - // calcolo la savebox in coordinate dell'immagine - long sbx0 = li ? li->left - x0 : 0; - long sby0 = li ? m_headerInfo.rows - li->bottom - y0 : 0; - long sbx1 = li ? li->right - 1 - x0 : x1 - x0; - long sby1 = li ? m_headerInfo.rows - li->top - 1 - y0 : y1 - y0; - - TRect layerSaveBox; - layerSaveBox = TRect(sbx0, sby0, sbx1, sby1); - - TRect imageRect; - if (!m_region.isEmpty()) - imageRect = TRect(0, 0, m_region.getLx() - 1, m_region.getLy() - 1); - else - imageRect = TRect(0, 0, m_headerInfo.cols - 1, m_headerInfo.rows - 1); - // E' possibile che il layer sia in parte o tutto al di fuori della'immagine - // in questo caso considero solo la parte visibile, cioè che rientra nell'immagine. - // Se è tutta fuori restutuisco TRasterImageP() - layerSaveBox *= imageRect; - - if (layerSaveBox == TRect() || layerSaveBox.isEmpty()) { - free(rledata); - return; - } - // Estraggo da rasP solo il rettangolo che si interseca con il livello corrente - // stando attento a prendere i pixel giusti. - int firstXPixIndexOfLayer = layerSaveBox.getP00().x - 1 + m_shrinkX - (abs(layerSaveBox.getP00().x - 1) % m_shrinkX); - int lrx0 = firstXPixIndexOfLayer / m_shrinkX; - int firstLineIndexOfLayer = layerSaveBox.getP00().y - 1 + m_shrinkY - (abs(layerSaveBox.getP00().y - 1) % m_shrinkY); - int lry0 = firstLineIndexOfLayer / m_shrinkY; - int lrx1 = (layerSaveBox.getP11().x - abs(layerSaveBox.getP11().x % m_shrinkX)) / m_shrinkX; - int lry1 = (layerSaveBox.getP11().y - abs(layerSaveBox.getP11().y % m_shrinkY)) / m_shrinkY; - TRect layerSaveBox2 = TRect(lrx0, lry0, lrx1, lry1); - if (layerSaveBox2.isEmpty()) - return; - assert(TRect(imgSize).contains(layerSaveBox2)); - if (li) - m_layersSavebox[li->layerId] = layerSaveBox2; - else - m_layersSavebox[0] = layerSaveBox2; - TRasterP smallRas = rasP->extract(layerSaveBox2); - assert(smallRas); - if (!smallRas) - return; - // Trovo l'indice di colonna del primo pixel del livello che deve essere letto - // L'indice è riferito al livello. - int colOffset = firstXPixIndexOfLayer - layerSaveBox.getP00().x; - assert(colOffset >= 0); - // Trovo l'indice della prima riga del livello che deve essere letta - // L'indice è riferito al livello. - // Nota che nel file photoshop le righe sono memorizzate dall'ultima alla prima. - int rowOffset = abs(sby1) % m_shrinkY; - int rowCount = rowOffset; - //if(m_shrinkY==3) rowCount--; - for (j = 0; j < smallRas->getLy(); j++) { - for (ch = 0; ch < chancount; ++ch) { - /* get row data */ - if (map[ch] < 0 || map[ch] > chancount) { - //warn("bad map[%d]=%d, skipping a channel", i, map[i]); - memset(inrows[ch], 0, chan->rowbytes); // zero out the row - } else - readrow(m_file, chan + map[ch], rowCount, inrows[ch], rledata); - } - // se la riga corrente non rientra nell'immagine salto la copia - if (sby1 - rowCount < 0 || sby1 - rowCount > m_headerInfo.rows - 1) { - rowCount += m_shrinkY; - continue; - } - if (depth == 1 && chancount == 1) { - if (!(layerSaveBox.getP00().x - sbx0 >= 0 && layerSaveBox.getP00().x - sbx0 + smallRas->getLx() / 8 - 1 < chan->rowbytes)) - throw TImageException(m_path, "Unable to read image with this depth and channels values"); - smallRas->lock(); - unsigned char *rawdata = (unsigned char *)smallRas->getRawData(0, smallRas->getLy() - j - 1); - TPixelGR8 *pix = (TPixelGR8 *)rawdata; - int colCount = colOffset; - for (int k = 0; k < smallRas->getLx(); k += 8) { - char value = ~inrows[0][layerSaveBox.getP00().x - sbx0 + colCount]; - pix[k].setValue(value); - pix[k + 1].setValue(value); - pix[k + 2].setValue(value); - pix[k + 3].setValue(value); - pix[k + 4].setValue(value); - pix[k + 5].setValue(value); - pix[k + 6].setValue(value); - pix[k + 7].setValue(value); - colCount += m_shrinkX; - } - smallRas->unlock(); - } else if (depth == 8 && chancount > 1) { - if (!(layerSaveBox.getP00().x - sbx0 >= 0 && layerSaveBox.getP00().x - sbx0 + smallRas->getLx() - 1 < chan->rowbytes)) - throw TImageException(m_path, "Unable to read image with this depth and channels values"); - smallRas->lock(); - unsigned char *rawdata = (unsigned char *)smallRas->getRawData(0, smallRas->getLy() - j - 1); - TPixel32 *pix = (TPixel32 *)rawdata; - int colCount = colOffset; - for (int k = 0; k < smallRas->getLx(); k++) { - if (chancount >= 3) { - pix[k].r = inrows[0][layerSaveBox.getP00().x - sbx0 + colCount]; - pix[k].g = inrows[1][layerSaveBox.getP00().x - sbx0 + colCount]; - pix[k].b = inrows[2][layerSaveBox.getP00().x - sbx0 + colCount]; - if (chancount == 4) // RGB + alpha - pix[k].m = inrows[3][layerSaveBox.getP00().x - sbx0 + colCount]; - else - pix[k].m = 255; - } else if (chancount <= 2) // gray + alpha - { - pix[k].r = inrows[0][layerSaveBox.getP00().x - sbx0 + colCount]; - pix[k].g = inrows[0][layerSaveBox.getP00().x - sbx0 + colCount]; - pix[k].b = inrows[0][layerSaveBox.getP00().x - sbx0 + colCount]; - if (chancount == 2) - pix[k].m = inrows[1][layerSaveBox.getP00().x - sbx0 + colCount]; - else - pix[k].m = 255; - } - colCount += m_shrinkX; - } - - smallRas->unlock(); - } else if (m_headerInfo.depth == 8 && chancount == 1) { - if (!(layerSaveBox.getP00().x - sbx0 >= 0 && layerSaveBox.getP00().x - sbx0 + smallRas->getLx() - 1 < chan->rowbytes)) - throw TImageException(m_path, "Unable to read image with this depth and channels values"); - smallRas->lock(); - unsigned char *rawdata = (unsigned char *)smallRas->getRawData(0, smallRas->getLy() - j - 1); - - TPixelGR8 *pix = (TPixelGR8 *)rawdata; - int colCount = colOffset; - for (int k = 0; k < smallRas->getLx(); k++) { - pix[k].setValue(inrows[0][layerSaveBox.getP00().x - sbx0 + colCount]); - colCount += m_shrinkX; - } - smallRas->unlock(); - } else if (m_headerInfo.depth == 16 && chancount == 1 && m_headerInfo.mergedalpha) // mergedChannels - { - if (!(layerSaveBox.getP00().x - sbx0 >= 0 && layerSaveBox.getP00().x - sbx0 + smallRas->getLx() - 1 < chan->rowbytes)) - throw TImageException(m_path, "Unable to read image with this depth and channels values"); - smallRas->lock(); - unsigned char *rawdata = (unsigned char *)smallRas->getRawData(0, smallRas->getLy() - j - 1); - TPixelGR8 *pix = (TPixelGR8 *)rawdata; - int colCount = colOffset; - for (int k = 0; k < smallRas->getLx(); k++) { - pix[k].setValue(inrows[0][layerSaveBox.getP00().x - sbx0 + colCount]); - colCount += m_shrinkX; - } - smallRas->unlock(); - } else if (m_headerInfo.depth == 16) { - if (!(layerSaveBox.getP00().x - sbx0 >= 0 && layerSaveBox.getP00().x - sbx0 + smallRas->getLx() - 1 < chan->rowbytes)) - throw TImageException(m_path, "Unable to read image with this depth and channels values"); - smallRas->lock(); - unsigned short *rawdata = (unsigned short *)smallRas->getRawData(0, smallRas->getLy() - j - 1); - TPixel64 *pix = (TPixel64 *)rawdata; - int colCount = colOffset; - for (int k = 0; k < smallRas->getLx(); k++) { - if (chancount >= 3) { - pix[k].r = swapShort(((psdUint16 *)inrows[0])[layerSaveBox.getP00().x - sbx0 + colCount]); - pix[k].g = swapShort(((psdUint16 *)inrows[1])[layerSaveBox.getP00().x - sbx0 + colCount]); - pix[k].b = swapShort(((psdUint16 *)inrows[2])[layerSaveBox.getP00().x - sbx0 + colCount]); - } else if (chancount <= 2) { - pix[k].r = swapShort(((psdUint16 *)inrows[0])[layerSaveBox.getP00().x - sbx0 + colCount]); - pix[k].g = swapShort(((psdUint16 *)inrows[0])[layerSaveBox.getP00().x - sbx0 + colCount]); - pix[k].b = swapShort(((psdUint16 *)inrows[0])[layerSaveBox.getP00().x - sbx0 + colCount]); - if (chancount == 2) - pix[k].m = swapShort(((psdUint16 *)inrows[1])[layerSaveBox.getP00().x - sbx0 + colCount]); - } - if (chancount == 4) { - pix[k].m = swapShort(((psdUint16 *)inrows[3])[layerSaveBox.getP00().x - sbx0 + colCount]); - } else - pix[k].m = 0xffff; - colCount += m_shrinkX; - } - smallRas->unlock(); - } else { - throw TImageException(m_path, "Unable to read image with this depth and channels values"); - } - rowCount += m_shrinkY; - } - fseek(m_file, savepos, SEEK_SET); // restoring filepos - - free(rledata); - for (ch = 0; ch < chancount; ++ch) - free(inrows[ch]); +void TPSDReader::doExtraData(TPSDLayerInfo *li, psdByte length) { + static struct dictentry extradict[] = { + // v4.0 + {0, "levl", "LEVELS", "Levels", NULL /*adj_levels*/}, + {0, "curv", "CURVES", "Curves", NULL /*adj_curves*/}, + {0, "brit", "BRIGHTNESSCONTRAST", "Brightness/contrast", NULL}, + {0, "blnc", "COLORBALANCE", "Color balance", NULL}, + {0, "hue ", "HUESATURATION4", "Old Hue/saturation, Photoshop 4.0", + NULL /*adj_huesat4*/}, + {0, "hue2", "HUESATURATION5", "New Hue/saturation, Photoshop 5.0", + NULL /*adj_huesat5*/}, + {0, "selc", "SELECTIVECOLOR", "Selective color", NULL /*adj_selcol*/}, + {0, "thrs", "THRESHOLD", "Threshold", NULL}, + {0, "nvrt", "INVERT", "Invert", NULL}, + {0, "post", "POSTERIZE", "Posterize", NULL}, + // v5.0 + {0, "lrFX", "EFFECT", "Effects layer", NULL /*ed_layereffects*/}, + {0, "tySh", "TYPETOOL5", "Type tool (5.0)", NULL /*ed_typetool*/}, + {0, "luni", "-UNICODENAME", "Unicode layer name", + NULL /*ed_unicodename*/}, + {0, "lyid", "-LAYERID", "Layer ID", + readLongData}, // '-' prefix means keep tag value on one line + // v6.0 + {0, "lfx2", "OBJECTEFFECT", "Object based effects layer", + NULL /*ed_objecteffects*/}, + {0, "Patt", "PATTERN", "Pattern", NULL}, + {0, "Pat2", "PATTERNCS", "Pattern (CS)", NULL}, + {0, "Anno", "ANNOTATION", "Annotation", NULL /*ed_annotation*/}, + {0, "clbl", "-BLENDCLIPPING", "Blend clipping", readByteData}, + {0, "infx", "-BLENDINTERIOR", "Blend interior", readByteData}, + {0, "knko", "-KNOCKOUT", "Knockout", readByteData}, + {0, "lspf", "-PROTECTED", "Protected", readLongData}, + {0, "lclr", "SHEETCOLOR", "Sheet color", NULL}, + {0, "fxrp", "-REFERENCEPOINT", "Reference point", + NULL /*ed_referencepoint*/}, + {0, "grdm", "GRADIENT", "Gradient", NULL}, + {0, "lsct", "-SECTION", "Section divider", readLongData}, // CS doc + {0, "SoCo", "SOLIDCOLORSHEET", "Solid color sheet", + NULL /*ed_versdesc*/}, // CS doc + {0, "PtFl", "PATTERNFILL", "Pattern fill", + NULL /*ed_versdesc*/}, // CS doc + {0, "GdFl", "GRADIENTFILL", "Gradient fill", + NULL /*ed_versdesc*/}, // CS doc + {0, "vmsk", "VECTORMASK", "Vector mask", NULL}, // CS doc + {0, "TySh", "TYPETOOL6", "Type tool (6.0)", + NULL /*ed_typetool*/}, // CS doc + {0, "ffxi", "-FOREIGNEFFECTID", "Foreign effect ID", + readLongData}, // CS doc (this is probably a key too, who knows) + {0, "lnsr", "-LAYERNAMESOURCE", "Layer name source", + readKey}, // CS doc (who knew this was a signature? docs fail again - + // and what do the values mean?) + {0, "shpa", "PATTERNDATA", "Pattern data", NULL}, // CS doc + {0, "shmd", "METADATASETTING", "Metadata setting", + NULL /*ed_metadata*/}, // CS doc + {0, "brst", "BLENDINGRESTRICTIONS", "Channel blending restrictions", + NULL}, // CS doc + // v7.0 + {0, "lyvr", "-LAYERVERSION", "Layer version", readLongData}, // CS doc + {0, "tsly", "-TRANSPARENCYSHAPES", "Transparency shapes layer", + readByteData}, // CS doc + {0, "lmgm", "-LAYERMASKASGLOBALMASK", "Layer mask as global mask", + readByteData}, // CS doc + {0, "vmgm", "-VECTORMASKASGLOBALMASK", "Vector mask as global mask", + readByteData}, // CS doc + // CS + {0, "mixr", "CHANNELMIXER", "Channel mixer", NULL}, // CS doc + {0, "phfl", "PHOTOFILTER", "Photo Filter", NULL}, // CS doc + + {0, "Lr16", "LAYER16", "Layer 16", readLayer16}, + {0, NULL, NULL, NULL, NULL}}; + + while (length >= 12) { + psdByte block = sigkeyblock(m_file, extradict, li); + if (!block) { + // warn("bad signature in layer's extra data, skipping the rest"); + break; + } + length -= block; + } } -void TPSDReader::doExtraData(TPSDLayerInfo *li, psdByte length) -{ - static struct dictentry extradict[] = { - // v4.0 - {0, "levl", "LEVELS", "Levels", NULL /*adj_levels*/}, - {0, "curv", "CURVES", "Curves", NULL /*adj_curves*/}, - {0, "brit", "BRIGHTNESSCONTRAST", "Brightness/contrast", NULL}, - {0, "blnc", "COLORBALANCE", "Color balance", NULL}, - {0, "hue ", "HUESATURATION4", "Old Hue/saturation, Photoshop 4.0", NULL /*adj_huesat4*/}, - {0, "hue2", "HUESATURATION5", "New Hue/saturation, Photoshop 5.0", NULL /*adj_huesat5*/}, - {0, "selc", "SELECTIVECOLOR", "Selective color", NULL /*adj_selcol*/}, - {0, "thrs", "THRESHOLD", "Threshold", NULL}, - {0, "nvrt", "INVERT", "Invert", NULL}, - {0, "post", "POSTERIZE", "Posterize", NULL}, - // v5.0 - {0, "lrFX", "EFFECT", "Effects layer", NULL /*ed_layereffects*/}, - {0, "tySh", "TYPETOOL5", "Type tool (5.0)", NULL /*ed_typetool*/}, - {0, "luni", "-UNICODENAME", "Unicode layer name", NULL /*ed_unicodename*/}, - {0, "lyid", "-LAYERID", "Layer ID", readLongData}, // '-' prefix means keep tag value on one line - // v6.0 - {0, "lfx2", "OBJECTEFFECT", "Object based effects layer", NULL /*ed_objecteffects*/}, - {0, "Patt", "PATTERN", "Pattern", NULL}, - {0, "Pat2", "PATTERNCS", "Pattern (CS)", NULL}, - {0, "Anno", "ANNOTATION", "Annotation", NULL /*ed_annotation*/}, - {0, "clbl", "-BLENDCLIPPING", "Blend clipping", readByteData}, - {0, "infx", "-BLENDINTERIOR", "Blend interior", readByteData}, - {0, "knko", "-KNOCKOUT", "Knockout", readByteData}, - {0, "lspf", "-PROTECTED", "Protected", readLongData}, - {0, "lclr", "SHEETCOLOR", "Sheet color", NULL}, - {0, "fxrp", "-REFERENCEPOINT", "Reference point", NULL /*ed_referencepoint*/}, - {0, "grdm", "GRADIENT", "Gradient", NULL}, - {0, "lsct", "-SECTION", "Section divider", readLongData}, // CS doc - {0, "SoCo", "SOLIDCOLORSHEET", "Solid color sheet", NULL /*ed_versdesc*/}, // CS doc - {0, "PtFl", "PATTERNFILL", "Pattern fill", NULL /*ed_versdesc*/}, // CS doc - {0, "GdFl", "GRADIENTFILL", "Gradient fill", NULL /*ed_versdesc*/}, // CS doc - {0, "vmsk", "VECTORMASK", "Vector mask", NULL}, // CS doc - {0, "TySh", "TYPETOOL6", "Type tool (6.0)", NULL /*ed_typetool*/}, // CS doc - {0, "ffxi", "-FOREIGNEFFECTID", "Foreign effect ID", readLongData}, // CS doc (this is probably a key too, who knows) - {0, "lnsr", "-LAYERNAMESOURCE", "Layer name source", readKey}, // CS doc (who knew this was a signature? docs fail again - and what do the values mean?) - {0, "shpa", "PATTERNDATA", "Pattern data", NULL}, // CS doc - {0, "shmd", "METADATASETTING", "Metadata setting", NULL /*ed_metadata*/}, // CS doc - {0, "brst", "BLENDINGRESTRICTIONS", "Channel blending restrictions", NULL}, // CS doc - // v7.0 - {0, "lyvr", "-LAYERVERSION", "Layer version", readLongData}, // CS doc - {0, "tsly", "-TRANSPARENCYSHAPES", "Transparency shapes layer", readByteData}, // CS doc - {0, "lmgm", "-LAYERMASKASGLOBALMASK", "Layer mask as global mask", readByteData}, // CS doc - {0, "vmgm", "-VECTORMASKASGLOBALMASK", "Vector mask as global mask", readByteData}, // CS doc - // CS - {0, "mixr", "CHANNELMIXER", "Channel mixer", NULL}, // CS doc - {0, "phfl", "PHOTOFILTER", "Photo Filter", NULL}, // CS doc - - {0, "Lr16", "LAYER16", "Layer 16", readLayer16}, - {0, NULL, NULL, NULL, NULL}}; - - while (length >= 12) { - psdByte block = sigkeyblock(m_file, extradict, li); - if (!block) { - //warn("bad signature in layer's extra data, skipping the rest"); - break; - } - length -= block; - } +struct dictentry *TPSDReader::findbykey(FILE *f, struct dictentry *parent, + char *key, TPSDLayerInfo *li) { + struct dictentry *d; + + for (d = parent; d->key; ++d) + if (!memcmp(key, d->key, 4)) { + // char *tagname = d->tag + (d->tag[0] == '-'); + // fprintf(stderr, "matched tag %s\n", d->tag); + if (d->func) { + psdByte savepos = ftell(f); + // int oneline = d->tag[0] == '-'; + // char *tagname = d->tag + oneline; + if (memcmp(key, "Lr16", 4) == 0) { + doLayersInfo(); + } else + d->func(f, d, li); // parse contents of this datum + fseek(f, savepos, SEEK_SET); + } else { + // there is no function to parse this block. + // because tag is empty in this case, we only need to consider + // parent's one-line-ness. + } + return d; + } + return NULL; } -struct dictentry *TPSDReader::findbykey(FILE *f, struct dictentry *parent, char *key, TPSDLayerInfo *li) -{ - struct dictentry *d; - - for (d = parent; d->key; ++d) - if (!memcmp(key, d->key, 4)) { - //char *tagname = d->tag + (d->tag[0] == '-'); - //fprintf(stderr, "matched tag %s\n", d->tag); - if (d->func) { - psdByte savepos = ftell(f); - //int oneline = d->tag[0] == '-'; - //char *tagname = d->tag + oneline; - if (memcmp(key, "Lr16", 4) == 0) { - doLayersInfo(); - } else - d->func(f, d, li); // parse contents of this datum - fseek(f, savepos, SEEK_SET); - } else { - // there is no function to parse this block. - // because tag is empty in this case, we only need to consider - // parent's one-line-ness. - } - return d; - } - return NULL; -} - -int TPSDReader::sigkeyblock(FILE *f, struct dictentry *dict, TPSDLayerInfo *li) -{ - char sig[4], key[4]; - long len; - struct dictentry *d; - - fread(sig, 1, 4, f); - fread(key, 1, 4, f); - len = read4Bytes(f); - if (!memcmp(sig, "8BIM", 4)) { - if (dict && (d = findbykey(f, dict, key, li)) && !d->func) { - // there is no function to parse this block - //UNQUIET(" (data: %s)\n", d->desc); - } - fseek(f, len, SEEK_CUR); - return len + 12; // return number of bytes consumed - } - return 0; // bad signature +int TPSDReader::sigkeyblock(FILE *f, struct dictentry *dict, + TPSDLayerInfo *li) { + char sig[4], key[4]; + long len; + struct dictentry *d; + + fread(sig, 1, 4, f); + fread(key, 1, 4, f); + len = read4Bytes(f); + if (!memcmp(sig, "8BIM", 4)) { + if (dict && (d = findbykey(f, dict, key, li)) && !d->func) { + // there is no function to parse this block + // UNQUIET(" (data: %s)\n", d->desc); + } + fseek(f, len, SEEK_CUR); + return len + 12; // return number of bytes consumed + } + return 0; // bad signature } //---------------------------- Utility functions -std::string buildErrorString(int error) -{ - std::string message = ""; - switch (error) { - case 0: - message = "NO Error Found"; - break; - case 1: - message = "Reading File Error"; - break; - case 2: - message = "Opening File Error"; - break; - default: - message = "Unknown Error"; - } - return message; +std::string buildErrorString(int error) { + std::string message = ""; + switch (error) { + case 0: + message = "NO Error Found"; + break; + case 1: + message = "Reading File Error"; + break; + case 2: + message = "Opening File Error"; + break; + default: + message = "Unknown Error"; + } + return message; } void readChannel(FILE *f, TPSDLayerInfo *li, - TPSDChannelInfo *chan, //channel info array - int channels, - TPSDHeaderInfo *h) -{ - int comp, ch; - psdByte pos, chpos, rb; - unsigned char *zipdata; - psdPixel count, last, j; - chpos = ftell(f); - - if (li) { - - // If this is a layer mask, the pixel size is a special case - if (chan->id == -2) { - chan->rows = li->mask.rows; - chan->cols = li->mask.cols; - } else { - // channel has dimensions of the layer - chan->rows = li->bottom - li->top; - chan->cols = li->right - li->left; - } - } else { - // merged image, has dimensions of PSD - chan->rows = h->rows; - chan->cols = h->cols; - } - - // Compute image row bytes - rb = ((long)chan->cols * h->depth + 7) / 8; - - // Read compression type - comp = read2UBytes(f); - - // Prepare compressed data for later access: - pos = chpos + 2; - - // skip rle counts, leave pos pointing to first compressed image row - if (comp == RLECOMP) - pos += (channels * chan->rows) << h->version; - - for (ch = 0; ch < channels; ++ch) { - if (!li) - chan[ch].id = ch; - chan[ch].rowbytes = rb; - chan[ch].comptype = comp; - chan[ch].rows = chan->rows; - chan[ch].cols = chan->cols; - chan[ch].filepos = pos; - - if (!chan->rows) - continue; - - // For RLE, we read the row count array and compute file positions. - // For ZIP, read and decompress whole channel. - switch (comp) { - case RAWDATA: - pos += chan->rowbytes * chan->rows; - break; - - case RLECOMP: - /* accumulate RLE counts, to make array of row start positions */ - chan[ch].rowpos = (psdByte *)mymalloc((chan[ch].rows + 1) * sizeof(psdByte)); - last = chan[ch].rowbytes; - for (j = 0; j < chan[ch].rows && !feof(f); ++j) { - count = h->version == 1 ? read2UBytes(f) : (unsigned long)read4Bytes(f); - - if (count > 2 * chan[ch].rowbytes) // this would be impossible - count = last; // make a guess, to help recover - last = count; - - chan[ch].rowpos[j] = pos; - pos += count; - } - if (j < chan[ch].rows) { - // fatal error couldn't read RLE counts - } - chan[ch].rowpos[j] = pos; /* = end of last row */ - break; - - case ZIPWITHOUTPREDICTION: - case ZIPWITHPREDICTION: - if (li) { - pos += chan->length - 2; - - zipdata = (unsigned char *)mymalloc(chan->length); - count = fread(zipdata, 1, chan->length - 2, f); - //if(count < chan->length - 2) - // alwayswarn("ZIP data short: wanted %d bytes, got %d", chan->length, count); - - chan->unzipdata = (unsigned char *)mymalloc(chan->rows * chan->rowbytes); - if (comp == ZIPWITHOUTPREDICTION) - psdUnzipWithoutPrediction(zipdata, count, chan->unzipdata, - chan->rows * chan->rowbytes); - else - psdUnzipWithPrediction(zipdata, count, chan->unzipdata, - chan->rows * chan->rowbytes, - chan->cols, h->depth); - - free(zipdata); - } else { - // WARNING cannot process ZIP compression outside layer - } - break; - default: { - // BAD COMPRESSION TYPE - } - if (li) - fseek(f, chan->length - 2, SEEK_CUR); - break; - } - } - - //if(li && pos != chpos + chan->length) - // alwayswarn("# channel data is %ld bytes, but length = %ld\n", - // pos - chpos, chan->length); - - // set at the end of channel's data - fseek(f, pos, SEEK_SET); + TPSDChannelInfo *chan, // channel info array + int channels, TPSDHeaderInfo *h) { + int comp, ch; + psdByte pos, chpos, rb; + unsigned char *zipdata; + psdPixel count, last, j; + chpos = ftell(f); + + if (li) { + // If this is a layer mask, the pixel size is a special case + if (chan->id == -2) { + chan->rows = li->mask.rows; + chan->cols = li->mask.cols; + } else { + // channel has dimensions of the layer + chan->rows = li->bottom - li->top; + chan->cols = li->right - li->left; + } + } else { + // merged image, has dimensions of PSD + chan->rows = h->rows; + chan->cols = h->cols; + } + + // Compute image row bytes + rb = ((long)chan->cols * h->depth + 7) / 8; + + // Read compression type + comp = read2UBytes(f); + + // Prepare compressed data for later access: + pos = chpos + 2; + + // skip rle counts, leave pos pointing to first compressed image row + if (comp == RLECOMP) pos += (channels * chan->rows) << h->version; + + for (ch = 0; ch < channels; ++ch) { + if (!li) chan[ch].id = ch; + chan[ch].rowbytes = rb; + chan[ch].comptype = comp; + chan[ch].rows = chan->rows; + chan[ch].cols = chan->cols; + chan[ch].filepos = pos; + + if (!chan->rows) continue; + + // For RLE, we read the row count array and compute file positions. + // For ZIP, read and decompress whole channel. + switch (comp) { + case RAWDATA: + pos += chan->rowbytes * chan->rows; + break; + + case RLECOMP: + /* accumulate RLE counts, to make array of row start positions */ + chan[ch].rowpos = + (psdByte *)mymalloc((chan[ch].rows + 1) * sizeof(psdByte)); + last = chan[ch].rowbytes; + for (j = 0; j < chan[ch].rows && !feof(f); ++j) { + count = h->version == 1 ? read2UBytes(f) : (unsigned long)read4Bytes(f); + + if (count > 2 * chan[ch].rowbytes) // this would be impossible + count = last; // make a guess, to help recover + last = count; + + chan[ch].rowpos[j] = pos; + pos += count; + } + if (j < chan[ch].rows) { + // fatal error couldn't read RLE counts + } + chan[ch].rowpos[j] = pos; /* = end of last row */ + break; + + case ZIPWITHOUTPREDICTION: + case ZIPWITHPREDICTION: + if (li) { + pos += chan->length - 2; + + zipdata = (unsigned char *)mymalloc(chan->length); + count = fread(zipdata, 1, chan->length - 2, f); + // if(count < chan->length - 2) + // alwayswarn("ZIP data short: wanted %d bytes, got %d", + //chan->length, count); + + chan->unzipdata = + (unsigned char *)mymalloc(chan->rows * chan->rowbytes); + if (comp == ZIPWITHOUTPREDICTION) + psdUnzipWithoutPrediction(zipdata, count, chan->unzipdata, + chan->rows * chan->rowbytes); + else + psdUnzipWithPrediction(zipdata, count, chan->unzipdata, + chan->rows * chan->rowbytes, chan->cols, + h->depth); + + free(zipdata); + } else { + // WARNING cannot process ZIP compression outside layer + } + break; + default: { + // BAD COMPRESSION TYPE + } + if (li) fseek(f, chan->length - 2, SEEK_CUR); + break; + } + } + + // if(li && pos != chpos + chan->length) + // alwayswarn("# channel data is %ld bytes, but length = %ld\n", + // pos - chpos, chan->length); + + // set at the end of channel's data + fseek(f, pos, SEEK_SET); } -void readLongData(FILE *f, struct dictentry *parent, TPSDLayerInfo *li) -{ - unsigned long id = read4Bytes(f); - if (strcmp(parent->key, "lyid") == 0) - li->layerId = id; - else if (strcmp(parent->key, "lspf") == 0) - li->protect = id; - else if (strcmp(parent->key, "lsct") == 0) - li->section = id; - else if (strcmp(parent->key, "ffxi") == 0) - li->foreignEffectID = id; - else if (strcmp(parent->key, "lyvr") == 0) - li->layerVersion = id; +void readLongData(FILE *f, struct dictentry *parent, TPSDLayerInfo *li) { + unsigned long id = read4Bytes(f); + if (strcmp(parent->key, "lyid") == 0) + li->layerId = id; + else if (strcmp(parent->key, "lspf") == 0) + li->protect = id; + else if (strcmp(parent->key, "lsct") == 0) + li->section = id; + else if (strcmp(parent->key, "ffxi") == 0) + li->foreignEffectID = id; + else if (strcmp(parent->key, "lyvr") == 0) + li->layerVersion = id; } -void readByteData(FILE *f, struct dictentry *parent, TPSDLayerInfo *li) -{ - int id = fgetc(f); - if (strcmp(parent->key, "clbl") == 0) - li->blendClipping = id; - else if (strcmp(parent->key, "infx") == 0) - li->blendInterior = id; - else if (strcmp(parent->key, "knko") == 0) - li->knockout = id; - else if (strcmp(parent->key, "tsly") == 0) - li->transparencyShapes = id; - else if (strcmp(parent->key, "lmgm") == 0) - li->layerMaskAsGlobalMask = id; - else if (strcmp(parent->key, "vmgm") == 0) - li->vectorMaskAsGlobalMask = id; +void readByteData(FILE *f, struct dictentry *parent, TPSDLayerInfo *li) { + int id = fgetc(f); + if (strcmp(parent->key, "clbl") == 0) + li->blendClipping = id; + else if (strcmp(parent->key, "infx") == 0) + li->blendInterior = id; + else if (strcmp(parent->key, "knko") == 0) + li->knockout = id; + else if (strcmp(parent->key, "tsly") == 0) + li->transparencyShapes = id; + else if (strcmp(parent->key, "lmgm") == 0) + li->layerMaskAsGlobalMask = id; + else if (strcmp(parent->key, "vmgm") == 0) + li->vectorMaskAsGlobalMask = id; } -void readKey(FILE *f, struct dictentry *parent, TPSDLayerInfo *li) -{ - static char key[5]; - if (fread(key, 1, 4, f) == 4) - key[4] = 0; - else - key[0] = 0; // or return NULL? +void readKey(FILE *f, struct dictentry *parent, TPSDLayerInfo *li) { + static char key[5]; + if (fread(key, 1, 4, f) == 4) + key[4] = 0; + else + key[0] = 0; // or return NULL? - if (strcmp(parent->key, "lnsr") == 0) - li->layerNameSource = key; + if (strcmp(parent->key, "lnsr") == 0) li->layerNameSource = key; } -void readLayer16(FILE *f, struct dictentry *parent, TPSDLayerInfo *li) -{ - //struct psd_header h2 = *psd_header; // a kind of 'nested' set of layers; don't alter main PSD header +void readLayer16(FILE *f, struct dictentry *parent, TPSDLayerInfo *li) { + // struct psd_header h2 = *psd_header; // a kind of 'nested' set of layers; + // don't alter main PSD header - // overwrite main PSD header, mainly because of the 'merged alpha' flag + // overwrite main PSD header, mainly because of the 'merged alpha' flag - // I *think* they mean us to respect the one in Lr16 because in my test data, - // the main layer count is zero, so cannot convey this information. - //dolayerinfo(f, psd_header); - //processlayers(f, psd_header); + // I *think* they mean us to respect the one in Lr16 because in my test data, + // the main layer count is zero, so cannot convey this information. + // dolayerinfo(f, psd_header); + // processlayers(f, psd_header); } //---------------------------- END Utility functions // TPSD PARSER -TPSDParser::TPSDParser(const TFilePath &path) -{ - m_path = path; - QString name = path.getName().c_str(); - name.append(path.getDottedType().c_str()); - int sepPos = name.indexOf("#"); - int dotPos = name.indexOf(".", sepPos); - name.remove(sepPos, dotPos - sepPos); - TFilePath psdpath = m_path.getParentDir() + TFilePath(name.toStdString()); - m_psdreader = new TPSDReader(psdpath); - doLevels(); -} - -TPSDParser::~TPSDParser() -{ - delete m_psdreader; +TPSDParser::TPSDParser(const TFilePath &path) { + m_path = path; + QString name = path.getName().c_str(); + name.append(path.getDottedType().c_str()); + int sepPos = name.indexOf("#"); + int dotPos = name.indexOf(".", sepPos); + name.remove(sepPos, dotPos - sepPos); + TFilePath psdpath = m_path.getParentDir() + TFilePath(name.toStdString()); + m_psdreader = new TPSDReader(psdpath); + doLevels(); } -void TPSDParser::doLevels() -{ - QString path = m_path.getName().c_str(); - QStringList list = path.split("#"); - m_levels.clear(); - if (list.size() > 1) { - TPSDHeaderInfo psdheader = m_psdreader->getPSDHeaderInfo(); - if (list.contains("frames") && list.at(0) != "frames") { - int firstLayerId = 0; - Level level; - for (int i = 0; i < psdheader.layersCount; i++) { - TPSDLayerInfo *li = m_psdreader->getLayerInfo(i); - long width = li->right - li->left; - long height = li->bottom - li->top; - if (width > 0 && height > 0) { - assert(li->layerId >= 0); - if (i == 0) - firstLayerId = li->layerId; - level.addFrame(li->layerId); - } - } - // non ha importanza quale layerId assegno, l'importante è che esista - level.setLayerId(0); - if (psdheader.layersCount == 0) - level.addFrame(firstLayerId); // succede nel caso in cui la psd non ha blocco layerInfo - m_levels.push_back(level); - } else if (list.size() == 3) { - if (list.at(2) == "group") { - int folderTagOpen = 0; - int scavenge = 0; - for (int i = 0; i < psdheader.layersCount; i++) { - TPSDLayerInfo *li = m_psdreader->getLayerInfo(i); - long width = li->right - li->left; - long height = li->bottom - li->top; - if (width > 0 && height > 0 && folderTagOpen == 0) { - assert(li->layerId >= 0); - Level level(li->name, li->layerId); - level.addFrame(li->layerId); - m_levels.push_back(level); - scavenge = 0; - } else { - if (width != 0 && height != 0) { - m_levels[m_levels.size() - 1 - (scavenge - folderTagOpen)].addFrame(li->layerId); - } else { - if (strcmp(li->name, "") == 0 || strcmp(li->name, "") == 0) { - assert(li->layerId >= 0); - Level level(li->name, li->layerId, true); - m_levels.push_back(level); - folderTagOpen++; - scavenge = folderTagOpen; - } else if (li->section > 0 && li->section <= 3) // vedi specifiche psd - { - assert(li->layerId >= 0); - m_levels[m_levels.size() - 1 - (scavenge - folderTagOpen)].setName(li->name); - m_levels[m_levels.size() - 1 - (scavenge - folderTagOpen)].setLayerId(li->layerId); - folderTagOpen--; - if (folderTagOpen > 0) - m_levels[m_levels.size() - 1 - (scavenge - folderTagOpen)].addFrame(li->layerId, true); - } - } - } - } - if (psdheader.layersCount == 0) // succede nel caso in cui la psd non ha blocco layerInfo - { - Level level; - level.setLayerId(0); - level.addFrame(0); - m_levels.push_back(level); - } - } else - throw TImageException(m_path, "PSD code name error"); - } else if (list.size() == 2) // each psd layer is a tlevel - { - TPSDHeaderInfo psdheader = m_psdreader->getPSDHeaderInfo(); - for (int i = 0; i < psdheader.layersCount; i++) { - TPSDLayerInfo *li = m_psdreader->getLayerInfo(i); - long width = li->right - li->left; - long height = li->bottom - li->top; - if (width > 0 && height > 0) { - assert(li->layerId >= 0); - Level level(li->name, li->layerId); - level.addFrame(li->layerId); - m_levels.push_back(level); - } - } - if (psdheader.layersCount == 0) // succede nel caso in cui la psd non ha blocco layerInfo - { - Level level; - level.setLayerId(0); - level.addFrame(0); - m_levels.push_back(level); - } - } else - throw TImageException(m_path, "PSD code name error"); - } else // list.size()==1. float - { - Level level; - level.setName(m_path.getName()); - level.addFrame(0); - m_levels.push_back(level); - } +TPSDParser::~TPSDParser() { delete m_psdreader; } + +void TPSDParser::doLevels() { + QString path = m_path.getName().c_str(); + QStringList list = path.split("#"); + m_levels.clear(); + if (list.size() > 1) { + TPSDHeaderInfo psdheader = m_psdreader->getPSDHeaderInfo(); + if (list.contains("frames") && list.at(0) != "frames") { + int firstLayerId = 0; + Level level; + for (int i = 0; i < psdheader.layersCount; i++) { + TPSDLayerInfo *li = m_psdreader->getLayerInfo(i); + long width = li->right - li->left; + long height = li->bottom - li->top; + if (width > 0 && height > 0) { + assert(li->layerId >= 0); + if (i == 0) firstLayerId = li->layerId; + level.addFrame(li->layerId); + } + } + // non ha importanza quale layerId assegno, l'importante è che esista + level.setLayerId(0); + if (psdheader.layersCount == 0) + level.addFrame(firstLayerId); // succede nel caso in cui la psd non ha + // blocco layerInfo + m_levels.push_back(level); + } else if (list.size() == 3) { + if (list.at(2) == "group") { + int folderTagOpen = 0; + int scavenge = 0; + for (int i = 0; i < psdheader.layersCount; i++) { + TPSDLayerInfo *li = m_psdreader->getLayerInfo(i); + long width = li->right - li->left; + long height = li->bottom - li->top; + if (width > 0 && height > 0 && folderTagOpen == 0) { + assert(li->layerId >= 0); + Level level(li->name, li->layerId); + level.addFrame(li->layerId); + m_levels.push_back(level); + scavenge = 0; + } else { + if (width != 0 && height != 0) { + m_levels[m_levels.size() - 1 - (scavenge - folderTagOpen)] + .addFrame(li->layerId); + } else { + if (strcmp(li->name, "") == 0 || + strcmp(li->name, "") == 0) { + assert(li->layerId >= 0); + Level level(li->name, li->layerId, true); + m_levels.push_back(level); + folderTagOpen++; + scavenge = folderTagOpen; + } else if (li->section > 0 && + li->section <= 3) // vedi specifiche psd + { + assert(li->layerId >= 0); + m_levels[m_levels.size() - 1 - (scavenge - folderTagOpen)] + .setName(li->name); + m_levels[m_levels.size() - 1 - (scavenge - folderTagOpen)] + .setLayerId(li->layerId); + folderTagOpen--; + if (folderTagOpen > 0) + m_levels[m_levels.size() - 1 - (scavenge - folderTagOpen)] + .addFrame(li->layerId, true); + } + } + } + } + if (psdheader.layersCount == + 0) // succede nel caso in cui la psd non ha blocco layerInfo + { + Level level; + level.setLayerId(0); + level.addFrame(0); + m_levels.push_back(level); + } + } else + throw TImageException(m_path, "PSD code name error"); + } else if (list.size() == 2) // each psd layer is a tlevel + { + TPSDHeaderInfo psdheader = m_psdreader->getPSDHeaderInfo(); + for (int i = 0; i < psdheader.layersCount; i++) { + TPSDLayerInfo *li = m_psdreader->getLayerInfo(i); + long width = li->right - li->left; + long height = li->bottom - li->top; + if (width > 0 && height > 0) { + assert(li->layerId >= 0); + Level level(li->name, li->layerId); + level.addFrame(li->layerId); + m_levels.push_back(level); + } + } + if (psdheader.layersCount == + 0) // succede nel caso in cui la psd non ha blocco layerInfo + { + Level level; + level.setLayerId(0); + level.addFrame(0); + m_levels.push_back(level); + } + } else + throw TImageException(m_path, "PSD code name error"); + } else // list.size()==1. float + { + Level level; + level.setName(m_path.getName()); + level.addFrame(0); + m_levels.push_back(level); + } } -void TPSDParser::load(TRasterImageP &rasP, int layerId) -{ - m_psdreader->load(rasP, layerId); +void TPSDParser::load(TRasterImageP &rasP, int layerId) { + m_psdreader->load(rasP, layerId); } -int TPSDParser::getLevelIndexById(int layerId) -{ - int layerIndex = -1; - for (int i = 0; i < (int)m_levels.size(); i++) { - if (m_levels[i].getLayerId() == layerId) { - layerIndex = i; - break; - } - } - if (layerId == 0 && layerIndex < 0) - layerIndex = 0; - if (layerIndex < 0 && layerId != 0) - throw TImageException(m_path, "Layer ID not exists"); - return layerIndex; +int TPSDParser::getLevelIndexById(int layerId) { + int layerIndex = -1; + for (int i = 0; i < (int)m_levels.size(); i++) { + if (m_levels[i].getLayerId() == layerId) { + layerIndex = i; + break; + } + } + if (layerId == 0 && layerIndex < 0) layerIndex = 0; + if (layerIndex < 0 && layerId != 0) + throw TImageException(m_path, "Layer ID not exists"); + return layerIndex; } -int TPSDParser::getLevelIdByName(std::string levelName) -{ - int pos = levelName.find_last_of(LEVEL_NAME_INDEX_SEP); - int counter = 0; - if (pos != std::string::npos) { - counter = atoi(levelName.substr(pos + 1).c_str()); - levelName = levelName.substr(0, pos); - } - int lyid = -1; - int levelNameCount = 0; - for (int i = 0; i < (int)m_levels.size(); i++) { - if (m_levels[i].getName() == levelName) { - lyid = m_levels[i].getLayerId(); - if (counter == levelNameCount) - break; - levelNameCount++; - } - } - if (lyid == 0 && lyid < 0) - lyid = 0; - if (lyid < 0 && lyid != 0) - throw TImageException(m_path, "Layer ID not exists"); - return lyid; +int TPSDParser::getLevelIdByName(std::string levelName) { + int pos = levelName.find_last_of(LEVEL_NAME_INDEX_SEP); + int counter = 0; + if (pos != std::string::npos) { + counter = atoi(levelName.substr(pos + 1).c_str()); + levelName = levelName.substr(0, pos); + } + int lyid = -1; + int levelNameCount = 0; + for (int i = 0; i < (int)m_levels.size(); i++) { + if (m_levels[i].getName() == levelName) { + lyid = m_levels[i].getLayerId(); + if (counter == levelNameCount) break; + levelNameCount++; + } + } + if (lyid == 0 && lyid < 0) lyid = 0; + if (lyid < 0 && lyid != 0) + throw TImageException(m_path, "Layer ID not exists"); + return lyid; } -int TPSDParser::getFramesCount(int levelId) -{ - int levelIndex = getLevelIndexById(levelId); - assert(levelIndex >= 0 && levelIndex < (int)m_levels.size()); - return m_levels[levelIndex].getFrameCount(); +int TPSDParser::getFramesCount(int levelId) { + int levelIndex = getLevelIndexById(levelId); + assert(levelIndex >= 0 && levelIndex < (int)m_levels.size()); + return m_levels[levelIndex].getFrameCount(); } -std::string TPSDParser::getLevelName(int levelId) -{ - int levelIndex = getLevelIndexById(levelId); - assert(levelIndex >= 0 && levelIndex < (int)m_levels.size()); - return m_levels[levelIndex].getName(); +std::string TPSDParser::getLevelName(int levelId) { + int levelIndex = getLevelIndexById(levelId); + assert(levelIndex >= 0 && levelIndex < (int)m_levels.size()); + return m_levels[levelIndex].getName(); } -std::string TPSDParser::getLevelNameWithCounter(int levelId) -{ - std::string levelName = getLevelName(levelId); - int count = 0; - for (int i = 0; i < (int)m_levels.size(); i++) { - if (m_levels[i].getName() == levelName) { - if (m_levels[i].getLayerId() == levelId) { - break; - } - count++; - } - } - if (count > 0) { - levelName.append(LEVEL_NAME_INDEX_SEP); - std::string c = QString::number(count).toStdString(); - levelName.append(c); - } - return levelName; +std::string TPSDParser::getLevelNameWithCounter(int levelId) { + std::string levelName = getLevelName(levelId); + int count = 0; + for (int i = 0; i < (int)m_levels.size(); i++) { + if (m_levels[i].getName() == levelName) { + if (m_levels[i].getLayerId() == levelId) { + break; + } + count++; + } + } + if (count > 0) { + levelName.append(LEVEL_NAME_INDEX_SEP); + std::string c = QString::number(count).toStdString(); + levelName.append(c); + } + return levelName; } diff --git a/toonz/sources/common/psdlib/psd.h b/toonz/sources/common/psdlib/psd.h index a374ec9..9773114 100644 --- a/toonz/sources/common/psdlib/psd.h +++ b/toonz/sources/common/psdlib/psd.h @@ -40,265 +40,258 @@ class TRasterImageP; #define ModeDuotone16 15 struct TPSDLayerMaskInfo { - psdByte size; - long top; - long left; - long bottom; - long right; - char default_colour; - char flags; - - psdPixel rows, cols; + psdByte size; + long top; + long left; + long bottom; + long right; + char default_colour; + char flags; + + psdPixel rows, cols; }; struct TPSDBlendModeInfo { - char sig[4]; - char key[4]; - unsigned char opacity; - unsigned char clipping; - unsigned char flags; + char sig[4]; + char key[4]; + unsigned char opacity; + unsigned char clipping; + unsigned char flags; }; struct TPSDLayerInfo { - long top; - long left; - long bottom; - long right; - short channels; - - TPSDChannelInfo *chan; - int *chindex; - - unsigned long layerId; - unsigned long protect; - unsigned long section; - unsigned long foreignEffectID; - unsigned long layerVersion; - - int blendClipping; - int blendInterior; - int knockout; - int transparencyShapes; - int layerMaskAsGlobalMask; - int vectorMaskAsGlobalMask; - - TPSDBlendModeInfo blend; - TPSDLayerMaskInfo mask; - - double referencePointX; - double referencePointY; - - char *name; - char *nameno; // "layerNr" - char *unicodeName; - char *layerNameSource; - psdByte additionalpos; - psdByte additionallen; - psdByte filepos; // - - psdByte startDataPos; // Posizione di inizio dati all'interno del file - psdByte dataLength; // lunghezza dati - - // LAYER EFFECTS - unsigned long int *fxCommonStateVersion; - int fxCommonStateVisible; - unsigned long int fxShadowVersion; - float fxShadowBlur; - float fxShadowIntensity; - float fxShadowAngle; - float fxShadowDistance; - - //my tags - bool isFolder; + long top; + long left; + long bottom; + long right; + short channels; + + TPSDChannelInfo *chan; + int *chindex; + + unsigned long layerId; + unsigned long protect; + unsigned long section; + unsigned long foreignEffectID; + unsigned long layerVersion; + + int blendClipping; + int blendInterior; + int knockout; + int transparencyShapes; + int layerMaskAsGlobalMask; + int vectorMaskAsGlobalMask; + + TPSDBlendModeInfo blend; + TPSDLayerMaskInfo mask; + + double referencePointX; + double referencePointY; + + char *name; + char *nameno; // "layerNr" + char *unicodeName; + char *layerNameSource; + psdByte additionalpos; + psdByte additionallen; + psdByte filepos; // + + psdByte startDataPos; // Posizione di inizio dati all'interno del file + psdByte dataLength; // lunghezza dati + + // LAYER EFFECTS + unsigned long int *fxCommonStateVersion; + int fxCommonStateVisible; + unsigned long int fxShadowVersion; + float fxShadowBlur; + float fxShadowIntensity; + float fxShadowAngle; + float fxShadowDistance; + + // my tags + bool isFolder; }; struct TPSDHeaderInfo { - - char sig[4]; - short version; - char reserved[6]; - short channels; - long rows; - long cols; - short depth; - short mode; - double vres; // image resource. Vertical resolution - double hres; // image resource. Horizontal resolution - - psdByte colormodepos; - int layersCount; - int mergedalpha; - bool linfoBlockEmpty; - TPSDLayerInfo *linfo; // array of layer info - psdByte lmistart, lmilen; // set by doLayerAndMaskInfo() - psdByte layerDataPos; //set by doInfo + char sig[4]; + short version; + char reserved[6]; + short channels; + long rows; + long cols; + short depth; + short mode; + double vres; // image resource. Vertical resolution + double hres; // image resource. Horizontal resolution + + psdByte colormodepos; + int layersCount; + int mergedalpha; + bool linfoBlockEmpty; + TPSDLayerInfo *linfo; // array of layer info + psdByte lmistart, lmilen; // set by doLayerAndMaskInfo() + psdByte layerDataPos; // set by doInfo }; struct dictentry { - int id; - const char *key, *tag, *desc; - void (*func)(FILE *f, struct dictentry *dict, TPSDLayerInfo *li); + int id; + const char *key, *tag, *desc; + void (*func)(FILE *f, struct dictentry *dict, TPSDLayerInfo *li); }; // PSD LIB // Restituisce eccezioni -class DVAPI TPSDReader -{ - TFilePath m_path; - FILE *m_file; - int m_lx, m_ly; - TPSDHeaderInfo m_headerInfo; - int m_layerId; - int m_shrinkX; - int m_shrinkY; - TRect m_region; +class DVAPI TPSDReader { + TFilePath m_path; + FILE *m_file; + int m_lx, m_ly; + TPSDHeaderInfo m_headerInfo; + int m_layerId; + int m_shrinkX; + int m_shrinkY; + TRect m_region; public: - TPSDReader(const TFilePath &path); - ~TPSDReader(); - TImageReaderP getFrameReader(TFilePath path); - TPSDHeaderInfo getPSDHeaderInfo(); - - void load(TRasterImageP &rasP, int layerId); - TDimension getSize() const { return TDimension(m_lx, m_ly); } - TPSDLayerInfo *getLayerInfo(int index); - int getLayerInfoIndexById(int layerId); - void setShrink(int shrink) - { - m_shrinkX = shrink; - m_shrinkY = shrink; - } - void setShrink(int shrinkX, int shrinkY) - { - m_shrinkX = shrinkX; - m_shrinkY = shrinkY; - } - void setRegion(TRect region) { m_region = region; } - - int getShrinkX() { return m_shrinkX; } - int getShrinkY() { return m_shrinkY; } - TRect getRegion() { return m_region; } + TPSDReader(const TFilePath &path); + ~TPSDReader(); + TImageReaderP getFrameReader(TFilePath path); + TPSDHeaderInfo getPSDHeaderInfo(); + + void load(TRasterImageP &rasP, int layerId); + TDimension getSize() const { return TDimension(m_lx, m_ly); } + TPSDLayerInfo *getLayerInfo(int index); + int getLayerInfoIndexById(int layerId); + void setShrink(int shrink) { + m_shrinkX = shrink; + m_shrinkY = shrink; + } + void setShrink(int shrinkX, int shrinkY) { + m_shrinkX = shrinkX; + m_shrinkY = shrinkY; + } + void setRegion(TRect region) { m_region = region; } + + int getShrinkX() { return m_shrinkX; } + int getShrinkY() { return m_shrinkY; } + TRect getRegion() { return m_region; } private: - std::map m_layersSavebox; - - bool doInfo(); - bool doHeaderInfo(); - bool doColorModeData(); - bool doImageResources(); - bool doLayerAndMaskInfo(); - bool doLayersInfo(); - bool readLayerInfo(int index); - - //void doImage(unsigned char *rasP, TPSDLayerInfo *li); - void doImage(TRasterP &rasP, int layerId); - - void readImageData(TRasterP &rasP, TPSDLayerInfo *li, TPSDChannelInfo *chan, - int chancount, psdPixel rows, psdPixel cols); - int m_error; - TThread::Mutex m_mutex; - int openFile(); - - void doExtraData(TPSDLayerInfo *li, psdByte length); - int sigkeyblock(FILE *f, struct dictentry *dict, TPSDLayerInfo *li); - struct dictentry *findbykey(FILE *f, struct dictentry *parent, char *key, TPSDLayerInfo *li); + std::map m_layersSavebox; + + bool doInfo(); + bool doHeaderInfo(); + bool doColorModeData(); + bool doImageResources(); + bool doLayerAndMaskInfo(); + bool doLayersInfo(); + bool readLayerInfo(int index); + + // void doImage(unsigned char *rasP, TPSDLayerInfo *li); + void doImage(TRasterP &rasP, int layerId); + + void readImageData(TRasterP &rasP, TPSDLayerInfo *li, TPSDChannelInfo *chan, + int chancount, psdPixel rows, psdPixel cols); + int m_error; + TThread::Mutex m_mutex; + int openFile(); + + void doExtraData(TPSDLayerInfo *li, psdByte length); + int sigkeyblock(FILE *f, struct dictentry *dict, TPSDLayerInfo *li); + struct dictentry *findbykey(FILE *f, struct dictentry *parent, char *key, + TPSDLayerInfo *li); }; -// converts psd layers structure into toonz level structure according to path -class DVAPI TPSDParser -{ - - class Level - { - public: - Level(std::string nm = "Unknown", int lid = 0, bool is_folder = false) : name(nm), - layerId(lid), - folder(is_folder) - { - } - void addFrame(int layerId, bool isFolder = false) { framesId.push_back(Frame(layerId, isFolder)); } - int getFrameCount() { return (int)framesId.size(); } - std::string getName() { return name; } - int getLayerId() { return layerId; } - void setName(std::string nname) { name = nname; } - void setLayerId(int nlayerId) { layerId = nlayerId; } - int getFrameId(int index) - { - assert(index >= 0 && index < (int)framesId.size()); - return framesId[index].layerId; - } - // return true if frame is a subfolder - bool isSubFolder(int frameIndex) - { - assert(frameIndex >= 0 && frameIndex < (int)framesId.size()); - return framesId[frameIndex].isFolder; - } - // return true if the level is built from a psd folder - bool isFolder() { return folder; } - private: - struct Frame { - int layerId; // psd layerId - bool isFolder; - Frame(int layId, bool folder) : layerId(layId), isFolder(folder) - { - } - }; - - std::string name; // psd name - int layerId; // psd layer id - std::vector framesId; // array of layer ID as frame - bool folder; - }; - - TFilePath m_path; - std::vector m_levels; // layers id - TPSDReader *m_psdreader; //lib +// converts psd layers structure into toonz level structure according to +// path +class DVAPI TPSDParser { + class Level { + public: + Level(std::string nm = "Unknown", int lid = 0, bool is_folder = false) + : name(nm), layerId(lid), folder(is_folder) {} + void addFrame(int layerId, bool isFolder = false) { + framesId.push_back(Frame(layerId, isFolder)); + } + int getFrameCount() { return (int)framesId.size(); } + std::string getName() { return name; } + int getLayerId() { return layerId; } + void setName(std::string nname) { name = nname; } + void setLayerId(int nlayerId) { layerId = nlayerId; } + int getFrameId(int index) { + assert(index >= 0 && index < (int)framesId.size()); + return framesId[index].layerId; + } + // return true if frame is a subfolder + bool isSubFolder(int frameIndex) { + assert(frameIndex >= 0 && frameIndex < (int)framesId.size()); + return framesId[frameIndex].isFolder; + } + // return true if the level is built from a psd folder + bool isFolder() { return folder; } + + private: + struct Frame { + int layerId; // psd layerId + bool isFolder; + Frame(int layId, bool folder) : layerId(layId), isFolder(folder) {} + }; + + std::string name; // psd name + int layerId; // psd layer id + std::vector framesId; // array of layer ID as frame + bool folder; + }; + + TFilePath m_path; + std::vector m_levels; // layers id + TPSDReader *m_psdreader; // lib public: - // path define levels construction method - // if path = : - // filename.psd flat image so LevelsCount = 1; - // filename#LAYERID.psd each psd layer as a tlevel - // filename#LAYERID#frames.psd each psd layer as a frame so there is only one tlevel with 1 or more frames; - // filename#LAYERID#folder.psd each psd layer is a tlevel and - // each folder is a tlevel such as the psd layers - // contained into folder are frames of tlevel - // LAYERID(Integer) is psd layerId - TPSDParser(const TFilePath &path); - ~TPSDParser(); - int getLevelsCount() { return (int)m_levels.size(); } - // load a psd layer - // if layerId == 0 load flat image - void load(TRasterImageP &rasP, int layerId = 0); - - // Returns psd layerID - int getLevelId(int index) - { - assert(index >= 0 && index < (int)m_levels.size()); - return m_levels[index].getLayerId(); - } - bool isFolder(int levelIndex) - { - assert(levelIndex >= 0 && levelIndex < (int)m_levels.size()); - return m_levels[levelIndex].isFolder(); - } - int getLevelIndexById(int levelId); - // Returns layerID by name. Note that the layer name is not unique, so it return the first layer id found. - int getLevelIdByName(std::string levelName); - int getFrameId(int layerId, int frameIndex) { return m_levels[getLevelIndexById(layerId)].getFrameId(frameIndex); } - int getFramesCount(int levelId); - bool isSubFolder(int levelIndex, int frameIndex) - { - assert(levelIndex >= 0 && levelIndex < (int)m_levels.size()); - return m_levels[levelIndex].isSubFolder(frameIndex); - } - std::string getLevelName(int levelId); - // Returns level name. - // If there are 2 or more level with the same name then - // returns levelname, levelname__2, etc - std::string getLevelNameWithCounter(int levelId); + // path define levels construction method + // if path = : + // filename.psd flat image so LevelsCount = 1; + // filename#LAYERID.psd each psd layer as a tlevel + // filename#LAYERID#frames.psd each psd layer as a frame so there is only + // one tlevel with 1 or more frames; + // filename#LAYERID#folder.psd each psd layer is a tlevel and + // each folder is a tlevel such as the psd + // layers + // contained into folder are frames of tlevel + // LAYERID(Integer) is psd layerId + TPSDParser(const TFilePath &path); + ~TPSDParser(); + int getLevelsCount() { return (int)m_levels.size(); } + // load a psd layer + // if layerId == 0 load flat image + void load(TRasterImageP &rasP, int layerId = 0); + + // Returns psd layerID + int getLevelId(int index) { + assert(index >= 0 && index < (int)m_levels.size()); + return m_levels[index].getLayerId(); + } + bool isFolder(int levelIndex) { + assert(levelIndex >= 0 && levelIndex < (int)m_levels.size()); + return m_levels[levelIndex].isFolder(); + } + int getLevelIndexById(int levelId); + // Returns layerID by name. Note that the layer name is not unique, so it + // return the first layer id found. + int getLevelIdByName(std::string levelName); + int getFrameId(int layerId, int frameIndex) { + return m_levels[getLevelIndexById(layerId)].getFrameId(frameIndex); + } + int getFramesCount(int levelId); + bool isSubFolder(int levelIndex, int frameIndex) { + assert(levelIndex >= 0 && levelIndex < (int)m_levels.size()); + return m_levels[levelIndex].isSubFolder(frameIndex); + } + std::string getLevelName(int levelId); + // Returns level name. + // If there are 2 or more level with the same name then + // returns levelname, levelname__2, etc + std::string getLevelNameWithCounter(int levelId); private: - void doLevels(); // do m_levels + void doLevels(); // do m_levels }; -#endif //TIIO_PSD_H +#endif // TIIO_PSD_H diff --git a/toonz/sources/common/psdlib/psdutils.cpp b/toonz/sources/common/psdlib/psdutils.cpp index 963b07e..13eae17 100644 --- a/toonz/sources/common/psdlib/psdutils.cpp +++ b/toonz/sources/common/psdlib/psdutils.cpp @@ -8,142 +8,134 @@ #include "psdutils.h" -void readrow(FILE *psd, - TPSDChannelInfo *chan, - psdPixel row, // row index - unsigned char *inbuffer, // dest buffer for the uncompressed row - unsigned char *tmpbuffer) // temp rlebuffer for compressed data, 2xrb in size +void readrow(FILE *psd, TPSDChannelInfo *chan, + psdPixel row, // row index + unsigned char *inbuffer, // dest buffer for the uncompressed row + unsigned char * + tmpbuffer) // temp rlebuffer for compressed data, 2xrb in size { - psdPixel n = 0, rlebytes; - psdByte pos; - - int seekres = 0; - - switch (chan->comptype) { - case RAWDATA: /* uncompressed */ - pos = chan->filepos + chan->rowbytes * row; - seekres = fseek(psd, pos, SEEK_SET); - if (seekres != -1) - n = fread(inbuffer, 1, chan->rowbytes, psd); - break; - case RLECOMP: - pos = chan->rowpos[row]; - seekres = fseek(psd, pos, SEEK_SET); - if (seekres != -1) { - rlebytes = fread(tmpbuffer, 1, chan->rowpos[row + 1] - pos, psd); - n = unpackrow(inbuffer, tmpbuffer, chan->rowbytes, rlebytes); - } - break; - case ZIPWITHPREDICTION: - case ZIPWITHOUTPREDICTION: - memcpy(inbuffer, chan->unzipdata + chan->rowbytes * row, chan->rowbytes); - return; - } - // if we don't recognise the compression type, skip the row - // FIXME: or would it be better to use the last valid type seen? - - // if(seekres == -1) - // alwayswarn("# can't seek to " LL_L("%lld\n","%ld\n"), pos); - - if (n < chan->rowbytes) { - //warn("row data short (wanted %d, got %d bytes)", chan->rowbytes, n); - // zero out unwritten part of row - memset(inbuffer + n, 0, chan->rowbytes - n); - } + psdPixel n = 0, rlebytes; + psdByte pos; + + int seekres = 0; + + switch (chan->comptype) { + case RAWDATA: /* uncompressed */ + pos = chan->filepos + chan->rowbytes * row; + seekres = fseek(psd, pos, SEEK_SET); + if (seekres != -1) n = fread(inbuffer, 1, chan->rowbytes, psd); + break; + case RLECOMP: + pos = chan->rowpos[row]; + seekres = fseek(psd, pos, SEEK_SET); + if (seekres != -1) { + rlebytes = fread(tmpbuffer, 1, chan->rowpos[row + 1] - pos, psd); + n = unpackrow(inbuffer, tmpbuffer, chan->rowbytes, rlebytes); + } + break; + case ZIPWITHPREDICTION: + case ZIPWITHOUTPREDICTION: + memcpy(inbuffer, chan->unzipdata + chan->rowbytes * row, chan->rowbytes); + return; + } + // if we don't recognise the compression type, skip the row + // FIXME: or would it be better to use the last valid type seen? + + // if(seekres == -1) + // alwayswarn("# can't seek to " LL_L("%lld\n","%ld\n"), pos); + + if (n < chan->rowbytes) { + // warn("row data short (wanted %d, got %d bytes)", chan->rowbytes, n); + // zero out unwritten part of row + memset(inbuffer + n, 0, chan->rowbytes - n); + } } -int unpackrow(unsigned char *out, unsigned char *in, - psdPixel outlen, psdPixel inlen) -{ - psdPixel i, len; - int val; - - for (i = 0; inlen > 1 && i < outlen;) { - len = *in++; - --inlen; - - if (len == 128) /* ignore RLE flag value */ - ; - else { - if (len > 128) { - len = 1 + 256 - len; - - val = *in++; - --inlen; - - if ((i + len) <= outlen) - memset(out, val, len); - else { - memset(out, val, outlen - i); // fill to complete row - len = 0; - } - } else { - ++len; - if ((i + len) <= outlen) { - if (len > inlen) - break; - memcpy(out, in, len); - in += len; - inlen -= len; - } else { - memcpy(out, in, outlen - i); // copy to complete row - len = 0; - } - } - out += len; - i += len; - } - } - if (i < outlen) { - //WARNING: not enough RLE data for row; - } - return i; +int unpackrow(unsigned char *out, unsigned char *in, psdPixel outlen, + psdPixel inlen) { + psdPixel i, len; + int val; + + for (i = 0; inlen > 1 && i < outlen;) { + len = *in++; + --inlen; + + if (len == 128) /* ignore RLE flag value */ + ; + else { + if (len > 128) { + len = 1 + 256 - len; + + val = *in++; + --inlen; + + if ((i + len) <= outlen) + memset(out, val, len); + else { + memset(out, val, outlen - i); // fill to complete row + len = 0; + } + } else { + ++len; + if ((i + len) <= outlen) { + if (len > inlen) break; + memcpy(out, in, len); + in += len; + inlen -= len; + } else { + memcpy(out, in, outlen - i); // copy to complete row + len = 0; + } + } + out += len; + i += len; + } + } + if (i < outlen) { + // WARNING: not enough RLE data for row; + } + return i; } -void skipBlock(FILE *f) -{ - psdByte n = read4Bytes(f); - if (n) { - fseek(f, n, SEEK_CUR); - } else { - } +void skipBlock(FILE *f) { + psdByte n = read4Bytes(f); + if (n) { + fseek(f, n, SEEK_CUR); + } else { + } } // Read 2byte unsigned binary value. // BigEndian. -unsigned read2UBytes(FILE *f) -{ - unsigned n = fgetc(f) << 8; - return n |= fgetc(f); +unsigned read2UBytes(FILE *f) { + unsigned n = fgetc(f) << 8; + return n |= fgetc(f); } // Read 2byte binary value // BigEndian. -int read2Bytes(FILE *f) -{ - unsigned n = fgetc(f) << 8; - n |= fgetc(f); - return n < 0x8000 ? n : n - 0x10000; +int read2Bytes(FILE *f) { + unsigned n = fgetc(f) << 8; + n |= fgetc(f); + return n < 0x8000 ? n : n - 0x10000; } // Read 4byte signed binary value. // BigEndian. -long read4Bytes(FILE *f) -{ - long n = fgetc(f) << 24; - n |= fgetc(f) << 16; - n |= fgetc(f) << 8; - return n | fgetc(f); +long read4Bytes(FILE *f) { + long n = fgetc(f) << 24; + n |= fgetc(f) << 16; + n |= fgetc(f) << 8; + return n | fgetc(f); } -void *mymalloc(long n) -{ - void *p = malloc(n); - if (p) - return p; - else { - //ALLOCATION ERROR - } - return NULL; +void *mymalloc(long n) { + void *p = malloc(n); + if (p) + return p; + else { + // ALLOCATION ERROR + } + return NULL; } // ZIP COMPRESSION @@ -151,70 +143,63 @@ void *mymalloc(long n) // ZIP WITHOUT PREDICTION // If no error returns 1 else returns 0 int psdUnzipWithoutPrediction(unsigned char *src_buf, int src_len, - unsigned char *dst_buf, int dst_len) -{ - z_stream stream; - int state; + unsigned char *dst_buf, int dst_len) { + z_stream stream; + int state; - memset(&stream, 0, sizeof(z_stream)); - stream.data_type = Z_BINARY; + memset(&stream, 0, sizeof(z_stream)); + stream.data_type = Z_BINARY; - stream.next_in = (Bytef *)src_buf; - stream.avail_in = src_len; - stream.next_out = (Bytef *)dst_buf; - stream.avail_out = dst_len; + stream.next_in = (Bytef *)src_buf; + stream.avail_in = src_len; + stream.next_out = (Bytef *)dst_buf; + stream.avail_out = dst_len; - if (inflateInit(&stream) != Z_OK) - return 0; + if (inflateInit(&stream) != Z_OK) return 0; - do { - state = inflate(&stream, Z_PARTIAL_FLUSH); - if (state == Z_STREAM_END) - break; - if (state == Z_DATA_ERROR || state != Z_OK) - break; - } while (stream.avail_out > 0); + do { + state = inflate(&stream, Z_PARTIAL_FLUSH); + if (state == Z_STREAM_END) break; + if (state == Z_DATA_ERROR || state != Z_OK) break; + } while (stream.avail_out > 0); - if (state != Z_STREAM_END && state != Z_OK) - return 0; + if (state != Z_STREAM_END && state != Z_OK) return 0; - return 1; + return 1; } // ZIP WITH PREDICTION int psdUnzipWithPrediction(unsigned char *src_buf, int src_len, - unsigned char *dst_buf, int dst_len, - int row_size, int color_depth) -{ - int status; - int len; - unsigned char *buf; - - status = psdUnzipWithoutPrediction(src_buf, src_len, dst_buf, dst_len); - if (!status) - return status; - - buf = dst_buf; - do { - len = row_size; - if (color_depth == 16) { - while (--len) { - buf[2] += buf[0] + ((buf[1] + buf[3]) >> 8); - buf[3] += buf[1]; - buf += 2; - } - buf += 2; - dst_len -= row_size * 2; - } else { - while (--len) { - *(buf + 1) += *buf; - buf++; - } - buf++; - dst_len -= row_size; - } - } while (dst_len > 0); - - return 1; + unsigned char *dst_buf, int dst_len, int row_size, + int color_depth) { + int status; + int len; + unsigned char *buf; + + status = psdUnzipWithoutPrediction(src_buf, src_len, dst_buf, dst_len); + if (!status) return status; + + buf = dst_buf; + do { + len = row_size; + if (color_depth == 16) { + while (--len) { + buf[2] += buf[0] + ((buf[1] + buf[3]) >> 8); + buf[3] += buf[1]; + buf += 2; + } + buf += 2; + dst_len -= row_size * 2; + } else { + while (--len) { + *(buf + 1) += *buf; + buf++; + } + buf++; + dst_len -= row_size; + } + } while (dst_len > 0); + + return 1; } diff --git a/toonz/sources/common/psdlib/psdutils.h b/toonz/sources/common/psdlib/psdutils.h index 72629f0..714d4d8 100644 --- a/toonz/sources/common/psdlib/psdutils.h +++ b/toonz/sources/common/psdlib/psdutils.h @@ -6,37 +6,32 @@ #define BLOCKROWS 3 -#define NEXT2(x) (((x) + 1) & -2) // uguale o successivo (pad) -#define NEXT4(x) (((x) + 3) & -4) // uguale o successivo multiplo di 4 (pad) -#define FIXDPI(x) ((x) / 65536.) // fixedpt +#define NEXT2(x) (((x) + 1) & -2) // uguale o successivo (pad) +#define NEXT4(x) (((x) + 3) & -4) // uguale o successivo multiplo di 4 (pad) +#define FIXDPI(x) ((x) / 65536.) // fixedpt typedef long psdByte; typedef unsigned short psdUint16; typedef long psdPixel; -enum { RAWDATA, - RLECOMP, - ZIPWITHOUTPREDICTION, - ZIPWITHPREDICTION }; +enum { RAWDATA, RLECOMP, ZIPWITHOUTPREDICTION, ZIPWITHPREDICTION }; struct TPSDChannelInfo { - int id; // channel id - int comptype; // channel's compression type - psdPixel rows, cols, rowbytes; // computed by dochannel() - // FIXME: need depth?? - psdByte length; // channel byte count in file - psdByte filepos; // file offset of channel data (AFTER compression type) - psdByte *rowpos; // row data file positions (RLE ONLY) - unsigned char *unzipdata; // uncompressed data (ZIP ONLY) + int id; // channel id + int comptype; // channel's compression type + psdPixel rows, cols, rowbytes; // computed by dochannel() + // FIXME: need depth?? + psdByte length; // channel byte count in file + psdByte filepos; // file offset of channel data (AFTER compression type) + psdByte *rowpos; // row data file positions (RLE ONLY) + unsigned char *unzipdata; // uncompressed data (ZIP ONLY) }; -int unpackrow(unsigned char *out, unsigned char *in, psdPixel outlen, psdPixel inlen); +int unpackrow(unsigned char *out, unsigned char *in, psdPixel outlen, + psdPixel inlen); -void readrow(FILE *psd, - TPSDChannelInfo *chan, - psdPixel rowIndex, - unsigned char *inbuffer, - unsigned char *outbuffer); +void readrow(FILE *psd, TPSDChannelInfo *chan, psdPixel rowIndex, + unsigned char *inbuffer, unsigned char *outbuffer); void skipBlock(FILE *f); @@ -46,7 +41,7 @@ int read2Bytes(FILE *f); long read4Bytes(FILE *f); int psdUnzipWithoutPrediction(unsigned char *src_buf, int src_len, - unsigned char *dst_buf, int dst_len); + unsigned char *dst_buf, int dst_len); int psdUnzipWithPrediction(unsigned char *src_buf, int src_len, - unsigned char *dst_buf, int dst_len, - int row_size, int color_depth); + unsigned char *dst_buf, int dst_len, int row_size, + int color_depth); diff --git a/toonz/sources/common/tapptools/tcli.cpp b/toonz/sources/common/tapptools/tcli.cpp index 691d375..e7a9ec9 100644 --- a/toonz/sources/common/tapptools/tcli.cpp +++ b/toonz/sources/common/tapptools/tcli.cpp @@ -12,25 +12,18 @@ using namespace TCli; // Release // //--------------------------------------------------------- -namespace -{ +namespace { //--------------------------------------------------------- -void printToonzRelease(ostream &out) -{ - out << "Toonz 7.1" << endl; -} +void printToonzRelease(ostream &out) { out << "Toonz 7.1" << endl; } //--------------------------------------------------------- -void printLibRelease(ostream &out) -{ - out << "Tnzcore 1.0 - " __DATE__ << endl; -} +void printLibRelease(ostream &out) { out << "Tnzcore 1.0 - " __DATE__ << endl; } //--------------------------------------------------------- -} //namespace +} // namespace //========================================================= // @@ -44,12 +37,11 @@ void printLibRelease(ostream &out) // //--------------------------------------------------------- -class SpecialUsageElement : public UsageElement -{ +class SpecialUsageElement : public UsageElement { public: - SpecialUsageElement(std::string name) : UsageElement(name, " "){}; - void dumpValue(ostream &) const {}; - void resetValue(){}; + SpecialUsageElement(std::string name) : UsageElement(name, " "){}; + void dumpValue(ostream &) const {}; + void resetValue(){}; }; //--------------------------------------------------------- @@ -66,46 +58,39 @@ static Switcher libRelease("-librelease", ""); // helper function // //--------------------------------------------------------- -namespace -{ +namespace { //--------------------------------------------------------- -void fetchElement(int index, int &argc, char *argv[]) -{ - if (index >= argc) - throw UsageError("missing argument"); - for (int i = index; i < argc - 1; i++) - argv[i] = argv[i + 1]; - argc--; +void fetchElement(int index, int &argc, char *argv[]) { + if (index >= argc) throw UsageError("missing argument"); + for (int i = index; i < argc - 1; i++) argv[i] = argv[i + 1]; + argc--; } //--------------------------------------------------------- -void fetchElement(int &dst, int index, int &argc, char *argv[]) -{ - string s = argv[index]; - if (isInt(s)) - dst = std::stoi(s); - else - throw UsageError("expected int"); - fetchElement(index, argc, argv); +void fetchElement(int &dst, int index, int &argc, char *argv[]) { + string s = argv[index]; + if (isInt(s)) + dst = std::stoi(s); + else + throw UsageError("expected int"); + fetchElement(index, argc, argv); } //--------------------------------------------------------- -void fetchElement(string &dst, int index, int &argc, char *argv[]) -{ - char *s = argv[index]; - fetchElement(index, argc, argv); - if (*s == '-') - throw UsageError("expected argument"); - dst = string(s); +void fetchElement(string &dst, int index, int &argc, char *argv[]) { + char *s = argv[index]; + fetchElement(index, argc, argv); + if (*s == '-') throw UsageError("expected argument"); + dst = string(s); } //--------------------------------------------------------- -} //namespace +} // namespace //========================================================= // @@ -114,23 +99,17 @@ void fetchElement(string &dst, int index, int &argc, char *argv[]) //--------------------------------------------------------- UsageElement::UsageElement(string name, string help) - : m_name(name), m_help(help), m_selected(false) -{ -} + : m_name(name), m_help(help), m_selected(false) {} //--------------------------------------------------------- -void UsageElement::print(ostream &out) const -{ - out << m_name; -} +void UsageElement::print(ostream &out) const { out << m_name; } //--------------------------------------------------------- -void UsageElement::printHelpLine(ostream &out) const -{ - out << " " << m_name << endl; - out << " " << m_help << endl; +void UsageElement::printHelpLine(ostream &out) const { + out << " " << m_name << endl; + out << " " << m_help << endl; } //========================================================= @@ -139,34 +118,28 @@ void UsageElement::printHelpLine(ostream &out) const // //--------------------------------------------------------- -void Qualifier::print(ostream &out) const -{ - if (isSwitcher()) - out << m_name; - else - out << "[ " << m_name << " ]"; +void Qualifier::print(ostream &out) const { + if (isSwitcher()) + out << m_name; + else + out << "[ " << m_name << " ]"; } //--------------------------------------------------------- -void SimpleQualifier::fetch(int index, int &argc, char *argv[]) -{ - fetchElement(index, argc, argv); +void SimpleQualifier::fetch(int index, int &argc, char *argv[]) { + fetchElement(index, argc, argv); } //--------------------------------------------------------- -void SimpleQualifier::dumpValue(ostream &out) const -{ - out << m_name << " = " << (isSelected() ? "on" : "off") << endl; +void SimpleQualifier::dumpValue(ostream &out) const { + out << m_name << " = " << (isSelected() ? "on" : "off") << endl; } //--------------------------------------------------------- -void SimpleQualifier::resetValue() -{ - m_selected = false; -} +void SimpleQualifier::resetValue() { m_selected = false; } //========================================================= // @@ -174,28 +147,23 @@ void SimpleQualifier::resetValue() // //--------------------------------------------------------- -void Argument::fetch(int index, int &argc, char *argv[]) -{ - if (index >= argc) - throw UsageError("missing argument"); - if (!assign(argv[index])) - throw UsageError(string("bad argument type :") + argv[index]); - for (int i = index; i < argc - 1; i++) - argv[i] = argv[i + 1]; - argc--; +void Argument::fetch(int index, int &argc, char *argv[]) { + if (index >= argc) throw UsageError("missing argument"); + if (!assign(argv[index])) + throw UsageError(string("bad argument type :") + argv[index]); + for (int i = index; i < argc - 1; i++) argv[i] = argv[i + 1]; + argc--; } //--------------------------------------------------------- -void MultiArgument::fetch(int index, int &argc, char *argv[]) -{ - if (index >= argc) - throw UsageError("missing argument(s)"); - allocate(argc - index); - for (m_index = 0; m_index < m_count; m_index++) - if (!assign(argv[index + m_index])) - throw UsageError(string("bad argument type :") + argv[index + m_index]); - argc -= m_count; +void MultiArgument::fetch(int index, int &argc, char *argv[]) { + if (index >= argc) throw UsageError("missing argument(s)"); + allocate(argc - index); + for (m_index = 0; m_index < m_count; m_index++) + if (!assign(argv[index + m_index])) + throw UsageError(string("bad argument type :") + argv[index + m_index]); + argc -= m_count; } //========================================================= @@ -204,112 +172,96 @@ void MultiArgument::fetch(int index, int &argc, char *argv[]) // //--------------------------------------------------------- -UsageLine::UsageLine() - : m_count(0) -{ -} +UsageLine::UsageLine() : m_count(0) {} //--------------------------------------------------------- -UsageLine::~UsageLine() -{ -} +UsageLine::~UsageLine() {} //--------------------------------------------------------- -UsageLine::UsageLine(const UsageLine &src) -{ - m_count = src.m_count; - m_elements.reset(new UsageElementPtr[m_count]); - ::memcpy(m_elements.get(), src.m_elements.get(), m_count * sizeof(m_elements[0])); +UsageLine::UsageLine(const UsageLine &src) { + m_count = src.m_count; + m_elements.reset(new UsageElementPtr[m_count]); + ::memcpy(m_elements.get(), src.m_elements.get(), + m_count * sizeof(m_elements[0])); } //--------------------------------------------------------- -UsageLine &UsageLine::operator=(const UsageLine &src) -{ - if (src.m_elements != m_elements) { - m_elements.reset(new UsageElementPtr[src.m_count]); - ::memcpy(m_elements.get(), src.m_elements.get(), src.m_count * sizeof(m_elements[0])); - } - m_count = src.m_count; - return *this; +UsageLine &UsageLine::operator=(const UsageLine &src) { + if (src.m_elements != m_elements) { + m_elements.reset(new UsageElementPtr[src.m_count]); + ::memcpy(m_elements.get(), src.m_elements.get(), + src.m_count * sizeof(m_elements[0])); + } + m_count = src.m_count; + return *this; } //--------------------------------------------------------- -UsageLine::UsageLine(const UsageLine &src, UsageElement &elem) -{ - m_count = src.m_count; - m_elements.reset(new UsageElementPtr[m_count + 1]); - ::memcpy(m_elements.get(), src.m_elements.get(), m_count * sizeof(m_elements[0])); - m_elements[m_count++] = &elem; +UsageLine::UsageLine(const UsageLine &src, UsageElement &elem) { + m_count = src.m_count; + m_elements.reset(new UsageElementPtr[m_count + 1]); + ::memcpy(m_elements.get(), src.m_elements.get(), + m_count * sizeof(m_elements[0])); + m_elements[m_count++] = &elem; } //--------------------------------------------------------- -UsageLine::UsageLine(int count) -{ - m_count = count; - m_elements.reset(new UsageElementPtr[m_count]); - ::memset(m_elements.get(), 0, m_count * sizeof(m_elements[0])); +UsageLine::UsageLine(int count) { + m_count = count; + m_elements.reset(new UsageElementPtr[m_count]); + ::memset(m_elements.get(), 0, m_count * sizeof(m_elements[0])); } //--------------------------------------------------------- -UsageLine::UsageLine(UsageElement &elem) -{ - m_count = 1; - m_elements.reset(new UsageElementPtr[m_count]); - m_elements[0] = &elem; +UsageLine::UsageLine(UsageElement &elem) { + m_count = 1; + m_elements.reset(new UsageElementPtr[m_count]); + m_elements[0] = &elem; } //--------------------------------------------------------- -UsageLine::UsageLine(UsageElement &a, UsageElement &b) -{ - m_count = 2; - m_elements.reset(new UsageElementPtr[m_count]); - m_elements[0] = &a; - m_elements[1] = &b; +UsageLine::UsageLine(UsageElement &a, UsageElement &b) { + m_count = 2; + m_elements.reset(new UsageElementPtr[m_count]); + m_elements[0] = &a; + m_elements[1] = &b; } //--------------------------------------------------------- -UsageLine TCli::UsageLine::operator+(UsageElement &elem) -{ - return UsageLine(*this, elem); +UsageLine TCli::UsageLine::operator+(UsageElement &elem) { + return UsageLine(*this, elem); } //--------------------------------------------------------- -UsageLine TCli::operator+(UsageElement &a, UsageElement &b) -{ - return UsageLine(a, b); +UsageLine TCli::operator+(UsageElement &a, UsageElement &b) { + return UsageLine(a, b); } //--------------------------------------------------------- -UsageLine TCli::operator+(const UsageLine &a, const Optional &b) -{ - UsageLine ul(a.getCount() + b.getCount()); - int i; - for (i = 0; i < a.getCount(); i++) - ul[i] = a[i]; - for (int j = 0; j < b.getCount(); j++) - ul[i++] = b[j]; - return ul; +UsageLine TCli::operator+(const UsageLine &a, const Optional &b) { + UsageLine ul(a.getCount() + b.getCount()); + int i; + for (i = 0; i < a.getCount(); i++) ul[i] = a[i]; + for (int j = 0; j < b.getCount(); j++) ul[i++] = b[j]; + return ul; } //========================================================= -Optional::Optional(const UsageLine &ul) - : UsageLine(ul.getCount() + 2) -{ - m_elements[0] = &bra; - m_elements[m_count - 1] = &ket; - for (int i = 0; i < ul.getCount(); i++) - m_elements[i + 1] = ul[i]; +Optional::Optional(const UsageLine &ul) : UsageLine(ul.getCount() + 2) { + m_elements[0] = &bra; + m_elements[m_count - 1] = &ket; + for (int i = 0; i < ul.getCount(); i++) m_elements[i + 1] = ul[i]; } //========================================================= @@ -318,50 +270,47 @@ Optional::Optional(const UsageLine &ul) // //--------------------------------------------------------- -class TCli::UsageImp -{ - string m_progName; - vector m_usageLines; - std::map m_qtable; - vector m_qlist; - vector m_args; - typedef std::map::iterator qiterator; - typedef std::map::const_iterator const_qiterator; +class TCli::UsageImp { + string m_progName; + vector m_usageLines; + std::map m_qtable; + vector m_qlist; + vector m_args; + typedef std::map::iterator qiterator; + typedef std::map::const_iterator const_qiterator; - UsageLine *m_selectedUsageLine; + UsageLine *m_selectedUsageLine; public: - UsageImp(string progName); - ~UsageImp(){}; - void add(const UsageLine &); - void addStandardUsages(); + UsageImp(string progName); + ~UsageImp(){}; + void add(const UsageLine &); + void addStandardUsages(); - void registerQualifier(Qualifier *q); - void registerQualifier(string name, Qualifier *q); + void registerQualifier(Qualifier *q); + void registerQualifier(string name, Qualifier *q); - void registerArgument(Argument *arg); + void registerArgument(Argument *arg); - void printUsageLine(ostream &out, const UsageLine &ul) const; - void printUsageLines(ostream &out) const; + void printUsageLine(ostream &out, const UsageLine &ul) const; + void printUsageLines(ostream &out) const; - void print(ostream &out) const; + void print(ostream &out) const; - void resetValues(); - void clear(); - void parse(int argc, char *argv[]); - void fetchArguments( - UsageLine &ul, int a, int b, - int &argc, char *argv[]); - bool matchSwitcher(const UsageLine &ul) const; - bool hasSwitcher(const UsageLine &ul) const; - bool matchArgCount(const UsageLine &ul, int a, int b, int argc) const; + void resetValues(); + void clear(); + void parse(int argc, char *argv[]); + void fetchArguments(UsageLine &ul, int a, int b, int &argc, char *argv[]); + bool matchSwitcher(const UsageLine &ul) const; + bool hasSwitcher(const UsageLine &ul) const; + bool matchArgCount(const UsageLine &ul, int a, int b, int argc) const; - void dumpValues(ostream &out) const; + void dumpValues(ostream &out) const; - void getArgCountRange(const UsageLine &ul, int a, int b, - int &min, int &max) const; + void getArgCountRange(const UsageLine &ul, int a, int b, int &min, + int &max) const; - static const int InfiniteArgCount; + static const int InfiniteArgCount; }; //--------------------------------------------------------- @@ -371,407 +320,346 @@ const int UsageImp::InfiniteArgCount = 2048; //--------------------------------------------------------- UsageImp::UsageImp(string progName) - : m_progName(progName), m_selectedUsageLine(0) -{ - addStandardUsages(); -} - + : m_progName(progName), m_selectedUsageLine(0) { + addStandardUsages(); +} + //--------------------------------------------------------- -void UsageImp::addStandardUsages() -{ - add(help); - add(release); - add(libRelease); +void UsageImp::addStandardUsages() { + add(help); + add(release); + add(libRelease); } //--------------------------------------------------------- - -void UsageImp::clear() -{ - m_usageLines.clear(); - m_qtable.clear(); - m_qlist.clear(); - m_args.clear(); - m_selectedUsageLine = 0; - addStandardUsages(); + +void UsageImp::clear() { + m_usageLines.clear(); + m_qtable.clear(); + m_qlist.clear(); + m_args.clear(); + m_selectedUsageLine = 0; + addStandardUsages(); } //--------------------------------------------------------- -void UsageImp::registerArgument(Argument *arg) -{ - unsigned int i; - for (i = 0; i < m_args.size() && m_args[i] != arg; i++) { - } - if (i == m_args.size()) - m_args.push_back(arg); -} - -//--------------------------------------------------------- +void UsageImp::registerArgument(Argument *arg) { + unsigned int i; + for (i = 0; i < m_args.size() && m_args[i] != arg; i++) { + } + if (i == m_args.size()) m_args.push_back(arg); +} + +//--------------------------------------------------------- -void UsageImp::registerQualifier(string name, Qualifier *q) -{ - m_qtable[name] = q; - unsigned int i; - for (i = 0; i < m_qlist.size() && m_qlist[i] != q; i++) { - } - if (i == m_qlist.size()) - m_qlist.push_back(q); -} - -//--------------------------------------------------------- - -void UsageImp::registerQualifier(Qualifier *q) -{ - string str = q->getName(); - const char *s0 = str.c_str(); - while (*s0 == ' ') - s0++; - const char *s = s0; - for (;;) { - if (*s != '-') { - assert(!"Qualifier name must start with '-'"); - } - do - s++; - while (isalnum(*s)); - if (s == s0 + 1) { - assert(!"Empty qualifier name"); - } - std::string name(s0, s - s0); - registerQualifier(name, q); - while (*s == ' ') - s++; - // ignoro gli eventuali parametri - while (isalnum(*s)) { - while (isalnum(*s)) - s++; - while (*s == ' ') - s++; - } - if (*s != '|') - break; - s++; - while (*s == ' ') - s++; - s0 = s; - } - if (*s != '\0') { - assert(!"Unexpected character"); - } -} - -//--------------------------------------------------------- - -void UsageImp::add(const UsageLine &ul) -{ - m_usageLines.push_back(ul); - for (int i = 0; i < ul.getCount(); i++) { - Qualifier *q = dynamic_cast(ul[i]); - if (q) - registerQualifier(q); - Argument *a = dynamic_cast(ul[i]); - if (a) - registerArgument(a); - } -} - -//--------------------------------------------------------- - -void UsageImp::printUsageLine(ostream &out, const UsageLine &ul) const -{ - out << m_progName; - for (int j = 0; j < ul.getCount(); j++) - if (!ul[j]->isHidden()) { - out << " "; - ul[j]->print(out); - } - out << endl; -} - -//--------------------------------------------------------- - -void UsageImp::printUsageLines(std::ostream &out) const -{ - bool first = true; - for (unsigned int i = 0; i < m_usageLines.size(); i++) { - const UsageLine &ul = m_usageLines[i]; - int j; - for (j = 0; j < ul.getCount(); j++) - if (!ul[j]->isHidden()) - break; - if (j == ul.getCount()) - continue; - out << (first ? "usage: " : " "); - printUsageLine(out, ul); - first = false; - } - out << endl; -} - -//--------------------------------------------------------- - -void UsageImp::print(std::ostream &out) const -{ - printUsageLines(out); - out << endl; - unsigned int i; - for (i = 0; i < m_qlist.size(); i++) - if (!m_qlist[i]->isHidden()) - m_qlist[i]->printHelpLine(out); - for (i = 0; i < m_args.size(); i++) - m_args[i]->printHelpLine(out); - out << endl; -} - -//--------------------------------------------------------- - -void UsageImp::parse(int argc, char *argv[]) -{ - resetValues(); - if (argc == 0 || argv[0] == 0) - throw UsageError("missing program name"); - m_progName = string(argv[0]); - unsigned int i; - for (i = 1; i < (unsigned int)argc;) - if (argv[i][0] == '-') { - string qname(argv[i]); - qiterator qit = m_qtable.find(qname); - if (qit == m_qtable.end()) { - string msg = "unknown qualifier '" + qname + "'"; - throw UsageError(msg); - } - Qualifier *qualifier = qit->second; - qualifier->fetch(i, argc, argv); - qualifier->select(); - } else - i++; - - vector usages; - - for (i = 0; i < m_usageLines.size(); i++) - if (hasSwitcher(m_usageLines[i]) && - matchSwitcher(m_usageLines[i])) - usages.push_back(&m_usageLines[i]); - if (usages.empty()) - for (i = 0; i < m_usageLines.size(); i++) - if (!hasSwitcher(m_usageLines[i])) - usages.push_back(&m_usageLines[i]); - if (usages.size() == 0) - throw UsageError("unrecognized syntax"); - if (usages.size() > 1) { - int min = InfiniteArgCount; - int max = 0; - std::vector::iterator it; - for (it = usages.begin(); it != usages.end();) { - UsageLine &ul = **it; - int lmin, lmax; - getArgCountRange(ul, 0, ul.getCount() - 1, lmin, lmax); - min = std::min(min, lmin); - max = std::max(max, lmax); - if (matchArgCount(ul, 0, ul.getCount() - 1, argc - 1) == false) - it = usages.erase(it); - else - it++; - } - if (usages.size() == 0) { - if (argc - 1 < min) - throw UsageError("missing argument(s)"); - else if (argc - 1 > max) - throw UsageError("too many arguments"); - else - throw UsageError("bad argument number"); - } else if (usages.size() > 1) - throw UsageError("ambiguous syntax"); - } - - if (usages.size() == 1) { - UsageLine *found = usages[0]; - if (found->getCount() > 0) - fetchArguments(*found, 0, found->getCount() - 1, argc, argv); - if (argc > 1) - throw UsageError("too many arguments"); - m_selectedUsageLine = found; - } -} - -//--------------------------------------------------------- - -void UsageImp::fetchArguments( - UsageLine &ul, - int a, int b, int &argc, char *argv[]) -{ - assert(0 <= a && a <= b && b < ul.getCount()); - int i; - for (i = a; i <= b; i++) { - if (ul[i] == &bra || ul[i]->isMultiArgument()) - break; - if (ul[i]->isArgument()) { - Argument *argument = dynamic_cast(ul[i]); - assert(argument); - argument->fetch(1, argc, argv); - argument->select(); - } - } - if (i > b) { - } else if (ul[i] == &bra) { - int n = 0; - int j; - for (j = b; j > i && ul[j] != &ket; j--) - if (ul[j]->isArgument()) - n++; - assert(j > i + 1); - if (argc - 1 > n) - fetchArguments(ul, i + 1, j - 1, argc, argv); - if (j + 1 <= b) - fetchArguments(ul, j + 1, b, argc, argv); - } else if (ul[i]->isMultiArgument()) { - MultiArgument *argument = dynamic_cast(ul[i]); - assert(argument); - int n = 0; - for (int j = i + 1; j <= b; j++) - if (ul[j]->isArgument()) - n++; - int oldArgc = argc; - argc -= n; - argument->fetch(1, argc, argv); - argument->select(); - argc += n; - if (n > 0) { - if (argc < oldArgc) - for (int j = n; j > 0; j--) - argv[argc - j] = argv[oldArgc - j]; - fetchArguments(ul, i + 1, b, argc, argv); - } - } -} - -//--------------------------------------------------------- - -bool UsageImp::matchSwitcher(const UsageLine &ul) const -{ - for (int i = 0; i < ul.getCount(); i++) - if (ul[i]->isSwitcher() && - !ul[i]->isSelected()) - return false; - return true; -} - -//--------------------------------------------------------- - -bool UsageImp::hasSwitcher(const UsageLine &ul) const -{ - for (int i = 0; i < ul.getCount(); i++) - if (ul[i]->isSwitcher()) - return true; - return false; -} - -//--------------------------------------------------------- - -bool UsageImp::matchArgCount(const UsageLine &ul, - int a, int b, int argc) const -{ - int n = 0; - int i; - for (i = a; i <= b; i++) { - if (ul[i] == &bra || ul[i]->isMultiArgument()) - break; - if (ul[i]->isArgument()) - n++; - } - if (i > b) - return argc == n; - else if (ul[i] == &bra) { - int j; - for (j = b; j > i && ul[j] != &ket; j--) - if (ul[j]->isArgument()) - n++; - assert(j > i + 1); - if (n == argc) - return true; - else if (n > argc) - return false; - else - return matchArgCount(ul, i + 1, j - 1, argc - n); - } else { - assert(ul[i]->isMultiArgument()); - n++; - for (i++; i <= b; i++) - if (ul[i]->isArgument()) - n++; - return argc >= n; - } -} - -//--------------------------------------------------------- - -void UsageImp::getArgCountRange(const UsageLine &ul, int a, int b, - int &min, int &max) const -{ - min = max = 0; - int n = 0; - int i; - for (i = a; i <= b; i++) { - if (ul[i] == &bra || ul[i]->isMultiArgument()) - break; - if (ul[i]->isArgument()) - n++; - } - if (i > b) { - min = max = n; - return; - } else if (ul[i] == &bra) { - int j; - for (j = b; j > i && ul[j] != &ket; j--) - if (ul[j]->isArgument()) - n++; - assert(j > i + 1); - min = max = n; - int lmin, lmax; - getArgCountRange(ul, i + 1, j - 1, lmin, lmax); - if (lmax == InfiniteArgCount) - max = InfiniteArgCount; - else - max += lmax; - } else { - assert(ul[i]->isMultiArgument()); - n++; - for (i++; i <= b; i++) - if (ul[i]->isArgument()) - n++; - min = n; - max = InfiniteArgCount; - } -} - -//--------------------------------------------------------- - -void UsageImp::dumpValues(std::ostream &out) const -{ - if (m_selectedUsageLine == 0) - return; - cout << "selected usage: "; - printUsageLine(out, *m_selectedUsageLine); - unsigned int i; - for (i = 0; i < m_qlist.size(); i++) - m_qlist[i]->dumpValue(out); - for (i = 0; i < m_args.size(); i++) - m_args[i]->dumpValue(out); - out << endl - << endl; -} - -//--------------------------------------------------------- - -void UsageImp::resetValues() -{ - unsigned int i; - for (i = 0; i < m_qlist.size(); i++) - m_qlist[i]->resetValue(); - for (i = 0; i < m_args.size(); i++) - m_args[i]->resetValue(); +void UsageImp::registerQualifier(string name, Qualifier *q) { + m_qtable[name] = q; + unsigned int i; + for (i = 0; i < m_qlist.size() && m_qlist[i] != q; i++) { + } + if (i == m_qlist.size()) m_qlist.push_back(q); +} + +//--------------------------------------------------------- + +void UsageImp::registerQualifier(Qualifier *q) { + string str = q->getName(); + const char *s0 = str.c_str(); + while (*s0 == ' ') s0++; + const char *s = s0; + for (;;) { + if (*s != '-') { + assert(!"Qualifier name must start with '-'"); + } + do + s++; + while (isalnum(*s)); + if (s == s0 + 1) { + assert(!"Empty qualifier name"); + } + std::string name(s0, s - s0); + registerQualifier(name, q); + while (*s == ' ') s++; + // ignoro gli eventuali parametri + while (isalnum(*s)) { + while (isalnum(*s)) s++; + while (*s == ' ') s++; + } + if (*s != '|') break; + s++; + while (*s == ' ') s++; + s0 = s; + } + if (*s != '\0') { + assert(!"Unexpected character"); + } +} + +//--------------------------------------------------------- + +void UsageImp::add(const UsageLine &ul) { + m_usageLines.push_back(ul); + for (int i = 0; i < ul.getCount(); i++) { + Qualifier *q = dynamic_cast(ul[i]); + if (q) registerQualifier(q); + Argument *a = dynamic_cast(ul[i]); + if (a) registerArgument(a); + } +} + +//--------------------------------------------------------- + +void UsageImp::printUsageLine(ostream &out, const UsageLine &ul) const { + out << m_progName; + for (int j = 0; j < ul.getCount(); j++) + if (!ul[j]->isHidden()) { + out << " "; + ul[j]->print(out); + } + out << endl; +} + +//--------------------------------------------------------- + +void UsageImp::printUsageLines(std::ostream &out) const { + bool first = true; + for (unsigned int i = 0; i < m_usageLines.size(); i++) { + const UsageLine &ul = m_usageLines[i]; + int j; + for (j = 0; j < ul.getCount(); j++) + if (!ul[j]->isHidden()) break; + if (j == ul.getCount()) continue; + out << (first ? "usage: " : " "); + printUsageLine(out, ul); + first = false; + } + out << endl; +} + +//--------------------------------------------------------- + +void UsageImp::print(std::ostream &out) const { + printUsageLines(out); + out << endl; + unsigned int i; + for (i = 0; i < m_qlist.size(); i++) + if (!m_qlist[i]->isHidden()) m_qlist[i]->printHelpLine(out); + for (i = 0; i < m_args.size(); i++) m_args[i]->printHelpLine(out); + out << endl; +} + +//--------------------------------------------------------- + +void UsageImp::parse(int argc, char *argv[]) { + resetValues(); + if (argc == 0 || argv[0] == 0) throw UsageError("missing program name"); + m_progName = string(argv[0]); + unsigned int i; + for (i = 1; i < (unsigned int)argc;) + if (argv[i][0] == '-') { + string qname(argv[i]); + qiterator qit = m_qtable.find(qname); + if (qit == m_qtable.end()) { + string msg = "unknown qualifier '" + qname + "'"; + throw UsageError(msg); + } + Qualifier *qualifier = qit->second; + qualifier->fetch(i, argc, argv); + qualifier->select(); + } else + i++; + + vector usages; + + for (i = 0; i < m_usageLines.size(); i++) + if (hasSwitcher(m_usageLines[i]) && matchSwitcher(m_usageLines[i])) + usages.push_back(&m_usageLines[i]); + if (usages.empty()) + for (i = 0; i < m_usageLines.size(); i++) + if (!hasSwitcher(m_usageLines[i])) usages.push_back(&m_usageLines[i]); + if (usages.size() == 0) throw UsageError("unrecognized syntax"); + if (usages.size() > 1) { + int min = InfiniteArgCount; + int max = 0; + std::vector::iterator it; + for (it = usages.begin(); it != usages.end();) { + UsageLine &ul = **it; + int lmin, lmax; + getArgCountRange(ul, 0, ul.getCount() - 1, lmin, lmax); + min = std::min(min, lmin); + max = std::max(max, lmax); + if (matchArgCount(ul, 0, ul.getCount() - 1, argc - 1) == false) + it = usages.erase(it); + else + it++; + } + if (usages.size() == 0) { + if (argc - 1 < min) + throw UsageError("missing argument(s)"); + else if (argc - 1 > max) + throw UsageError("too many arguments"); + else + throw UsageError("bad argument number"); + } else if (usages.size() > 1) + throw UsageError("ambiguous syntax"); + } + + if (usages.size() == 1) { + UsageLine *found = usages[0]; + if (found->getCount() > 0) + fetchArguments(*found, 0, found->getCount() - 1, argc, argv); + if (argc > 1) throw UsageError("too many arguments"); + m_selectedUsageLine = found; + } +} + +//--------------------------------------------------------- + +void UsageImp::fetchArguments(UsageLine &ul, int a, int b, int &argc, + char *argv[]) { + assert(0 <= a && a <= b && b < ul.getCount()); + int i; + for (i = a; i <= b; i++) { + if (ul[i] == &bra || ul[i]->isMultiArgument()) break; + if (ul[i]->isArgument()) { + Argument *argument = dynamic_cast(ul[i]); + assert(argument); + argument->fetch(1, argc, argv); + argument->select(); + } + } + if (i > b) { + } else if (ul[i] == &bra) { + int n = 0; + int j; + for (j = b; j > i && ul[j] != &ket; j--) + if (ul[j]->isArgument()) n++; + assert(j > i + 1); + if (argc - 1 > n) fetchArguments(ul, i + 1, j - 1, argc, argv); + if (j + 1 <= b) fetchArguments(ul, j + 1, b, argc, argv); + } else if (ul[i]->isMultiArgument()) { + MultiArgument *argument = dynamic_cast(ul[i]); + assert(argument); + int n = 0; + for (int j = i + 1; j <= b; j++) + if (ul[j]->isArgument()) n++; + int oldArgc = argc; + argc -= n; + argument->fetch(1, argc, argv); + argument->select(); + argc += n; + if (n > 0) { + if (argc < oldArgc) + for (int j = n; j > 0; j--) argv[argc - j] = argv[oldArgc - j]; + fetchArguments(ul, i + 1, b, argc, argv); + } + } +} + +//--------------------------------------------------------- + +bool UsageImp::matchSwitcher(const UsageLine &ul) const { + for (int i = 0; i < ul.getCount(); i++) + if (ul[i]->isSwitcher() && !ul[i]->isSelected()) return false; + return true; +} + +//--------------------------------------------------------- + +bool UsageImp::hasSwitcher(const UsageLine &ul) const { + for (int i = 0; i < ul.getCount(); i++) + if (ul[i]->isSwitcher()) return true; + return false; +} + +//--------------------------------------------------------- + +bool UsageImp::matchArgCount(const UsageLine &ul, int a, int b, + int argc) const { + int n = 0; + int i; + for (i = a; i <= b; i++) { + if (ul[i] == &bra || ul[i]->isMultiArgument()) break; + if (ul[i]->isArgument()) n++; + } + if (i > b) + return argc == n; + else if (ul[i] == &bra) { + int j; + for (j = b; j > i && ul[j] != &ket; j--) + if (ul[j]->isArgument()) n++; + assert(j > i + 1); + if (n == argc) + return true; + else if (n > argc) + return false; + else + return matchArgCount(ul, i + 1, j - 1, argc - n); + } else { + assert(ul[i]->isMultiArgument()); + n++; + for (i++; i <= b; i++) + if (ul[i]->isArgument()) n++; + return argc >= n; + } +} + +//--------------------------------------------------------- + +void UsageImp::getArgCountRange(const UsageLine &ul, int a, int b, int &min, + int &max) const { + min = max = 0; + int n = 0; + int i; + for (i = a; i <= b; i++) { + if (ul[i] == &bra || ul[i]->isMultiArgument()) break; + if (ul[i]->isArgument()) n++; + } + if (i > b) { + min = max = n; + return; + } else if (ul[i] == &bra) { + int j; + for (j = b; j > i && ul[j] != &ket; j--) + if (ul[j]->isArgument()) n++; + assert(j > i + 1); + min = max = n; + int lmin, lmax; + getArgCountRange(ul, i + 1, j - 1, lmin, lmax); + if (lmax == InfiniteArgCount) + max = InfiniteArgCount; + else + max += lmax; + } else { + assert(ul[i]->isMultiArgument()); + n++; + for (i++; i <= b; i++) + if (ul[i]->isArgument()) n++; + min = n; + max = InfiniteArgCount; + } +} + +//--------------------------------------------------------- + +void UsageImp::dumpValues(std::ostream &out) const { + if (m_selectedUsageLine == 0) return; + cout << "selected usage: "; + printUsageLine(out, *m_selectedUsageLine); + unsigned int i; + for (i = 0; i < m_qlist.size(); i++) m_qlist[i]->dumpValue(out); + for (i = 0; i < m_args.size(); i++) m_args[i]->dumpValue(out); + out << endl << endl; +} + +//--------------------------------------------------------- + +void UsageImp::resetValues() { + unsigned int i; + for (i = 0; i < m_qlist.size(); i++) m_qlist[i]->resetValue(); + for (i = 0; i < m_args.size(); i++) m_args[i]->resetValue(); } //========================================================= @@ -780,75 +668,52 @@ void UsageImp::resetValues() // //--------------------------------------------------------- -Usage::Usage(string progName) - : m_imp(new UsageImp(progName)) -{ -} +Usage::Usage(string progName) : m_imp(new UsageImp(progName)) {} -Usage::~Usage() -{ -} +Usage::~Usage() {} -void Usage::add(const UsageLine &ul) -{ - m_imp->add(ul); -} +void Usage::add(const UsageLine &ul) { m_imp->add(ul); } -void Usage::print(std::ostream &out) const -{ - m_imp->print(out); -} +void Usage::print(std::ostream &out) const { m_imp->print(out); } -void Usage::dumpValues(std::ostream &out) const -{ - m_imp->dumpValues(out); -} +void Usage::dumpValues(std::ostream &out) const { m_imp->dumpValues(out); } -void Usage::clear() -{ - m_imp->clear(); -} +void Usage::clear() { m_imp->clear(); } -bool Usage::parse(const char *argvString, std::ostream &err) -{ - string s = string(argvString); - std::vector argv; - int len = s.size(); - for (int i = 0; i < len;) { - while (s[i] == ' ' || s[i] == '\t') - i++; - if (i < len) - argv.push_back(&s[i]); - while (i < len && !(s[i] == ' ' || s[i] == '\t')) - i++; - if (i < len) - s[i++] = '\0'; - } - return parse(argv.size(), &argv[0], err); +bool Usage::parse(const char *argvString, std::ostream &err) { + string s = string(argvString); + std::vector argv; + int len = s.size(); + for (int i = 0; i < len;) { + while (s[i] == ' ' || s[i] == '\t') i++; + if (i < len) argv.push_back(&s[i]); + while (i < len && !(s[i] == ' ' || s[i] == '\t')) i++; + if (i < len) s[i++] = '\0'; + } + return parse(argv.size(), &argv[0], err); } -bool Usage::parse(int argc, char *argv[], std::ostream &err) -{ - try { - m_imp->parse(argc, argv); - if (help) { - print(err); - return false; - } - if (release) { - printToonzRelease(err); - return false; - } - if (libRelease) { - printLibRelease(err); - return false; - } - return true; - } catch (UsageError e) { - err << "Usage error: " << e.getError() << endl; - m_imp->printUsageLines(err); - return false; - } +bool Usage::parse(int argc, char *argv[], std::ostream &err) { + try { + m_imp->parse(argc, argv); + if (help) { + print(err); + return false; + } + if (release) { + printToonzRelease(err); + return false; + } + if (libRelease) { + printLibRelease(err); + return false; + } + return true; + } catch (UsageError e) { + err << "Usage error: " << e.getError() << endl; + m_imp->printUsageLines(err); + return false; + } } //========================================================= @@ -858,52 +723,46 @@ bool Usage::parse(int argc, char *argv[], std::ostream &err) //--------------------------------------------------------- RangeQualifier::RangeQualifier() - : Qualifier("-range from to | -frame fr", - "frame range"), - m_from(0), m_to(-1) -{ -} + : Qualifier("-range from to | -frame fr", "frame range") + , m_from(0) + , m_to(-1) {} //--------------------------------------------------------- -void RangeQualifier::fetch(int index, int &argc, char *argv[]) -{ - assert(index < argc); - string qname(argv[index]); - fetchElement(index, argc, argv); - if (qname == "-range") { - fetchElement(m_from, index, argc, argv); - fetchElement(m_to, index, argc, argv); - } else if (qname == "-frame") { - fetchElement(m_from, index, argc, argv); - m_to = m_from; - } else { - assert(0); - } +void RangeQualifier::fetch(int index, int &argc, char *argv[]) { + assert(index < argc); + string qname(argv[index]); + fetchElement(index, argc, argv); + if (qname == "-range") { + fetchElement(m_from, index, argc, argv); + fetchElement(m_to, index, argc, argv); + } else if (qname == "-frame") { + fetchElement(m_from, index, argc, argv); + m_to = m_from; + } else { + assert(0); + } } -std::ostream &operator<<(std::ostream &out, const RangeQualifier &range) -{ - return out << "[" << range.getFrom() << ", " << range.getTo() << "]"; +std::ostream &operator<<(std::ostream &out, const RangeQualifier &range) { + return out << "[" << range.getFrom() << ", " << range.getTo() << "]"; } //--------------------------------------------------------- -void RangeQualifier::dumpValue(std::ostream &out) const -{ - out << m_name << " = "; - if (m_from <= m_to) - out << m_from << ", " << m_to; - else - out << "undefined"; - out << endl; +void RangeQualifier::dumpValue(std::ostream &out) const { + out << m_name << " = "; + if (m_from <= m_to) + out << m_from << ", " << m_to; + else + out << "undefined"; + out << endl; } //--------------------------------------------------------- -void RangeQualifier::resetValue() -{ - m_from = 0; - m_to = -1; - m_selected = false; +void RangeQualifier::resetValue() { + m_from = 0; + m_to = -1; + m_selected = false; } diff --git a/toonz/sources/common/tapptools/tcolorutils.cpp b/toonz/sources/common/tapptools/tcolorutils.cpp index 3f1b173..d05d375 100644 --- a/toonz/sources/common/tapptools/tcolorutils.cpp +++ b/toonz/sources/common/tapptools/tcolorutils.cpp @@ -24,53 +24,50 @@ extern "C" int isnan(double); //------------------------------------------------------------------------------ -class ClusterStatistic -{ +class ClusterStatistic { public: - KEYER_FLOAT sumComponents[3]; // vettore 3x1 - unsigned int elemsCount; - KEYER_FLOAT matrixR[9]; // matrice 3x3 = somma(x * trasposta(x)) - // dove x sono i pixel del cluster + KEYER_FLOAT sumComponents[3]; // vettore 3x1 + unsigned int elemsCount; + KEYER_FLOAT matrixR[9]; // matrice 3x3 = somma(x * trasposta(x)) + // dove x sono i pixel del cluster - KEYER_FLOAT covariance[9]; // matrice di covarianza - TPoint sumCoords; + KEYER_FLOAT covariance[9]; // matrice di covarianza + TPoint sumCoords; #ifdef WITH_ALPHA_IN_STATISTICS - KEYER_FLOAT sumAlpha; + KEYER_FLOAT sumAlpha; #endif }; //------------------------------------------------------------------------------ -class ClusterElem -{ +class ClusterElem { public: - ClusterElem(unsigned char _r, - unsigned char _g, - unsigned char _b, - KEYER_FLOAT _a, - unsigned int _x = 0, - unsigned int _y = 0) - : r(toDouble(_r)), g(toDouble(_g)), b(toDouble(_b)), a(_a), x(_x), y(_y), pix32(TPixel32(_r, _g, _b)) - { - } - - ~ClusterElem() {} - - static KEYER_FLOAT toDouble(unsigned char chan) - { - return ((KEYER_FLOAT)chan) * (KEYER_FLOAT)(1.0 / 255.0); - } - - unsigned int x; - unsigned int y; - KEYER_FLOAT r; - KEYER_FLOAT g; - KEYER_FLOAT b; - KEYER_FLOAT a; - TPixel32 pix32; + ClusterElem(unsigned char _r, unsigned char _g, unsigned char _b, + KEYER_FLOAT _a, unsigned int _x = 0, unsigned int _y = 0) + : r(toDouble(_r)) + , g(toDouble(_g)) + , b(toDouble(_b)) + , a(_a) + , x(_x) + , y(_y) + , pix32(TPixel32(_r, _g, _b)) {} + + ~ClusterElem() {} + + static KEYER_FLOAT toDouble(unsigned char chan) { + return ((KEYER_FLOAT)chan) * (KEYER_FLOAT)(1.0 / 255.0); + } + + unsigned int x; + unsigned int y; + KEYER_FLOAT r; + KEYER_FLOAT g; + KEYER_FLOAT b; + KEYER_FLOAT a; + TPixel32 pix32; }; //------------------------------------------------------------------------------ @@ -87,27 +84,26 @@ typedef std::vector ClusterElemContainer; //------------------------------------------------------------------------------ -class Cluster -{ +class Cluster { public: - Cluster(); - Cluster(const Cluster &rhs); + Cluster(); + Cluster(const Cluster &rhs); - ~Cluster(); + ~Cluster(); - void computeCovariance(); - void insert(ClusterElem *elem); - void computeStatistics(); - void getMeanAxis(KEYER_FLOAT axis[3]); + void computeCovariance(); + void insert(ClusterElem *elem); + void computeStatistics(); + void getMeanAxis(KEYER_FLOAT axis[3]); - ClusterStatistic statistic; - ClusterElemContainer data; + ClusterStatistic statistic; + ClusterElemContainer data; - KEYER_FLOAT eigenVector[3]; - KEYER_FLOAT eigenValue; + KEYER_FLOAT eigenVector[3]; + KEYER_FLOAT eigenValue; private: - void operator=(const Cluster &); + void operator=(const Cluster &); }; //------------------------------------------------------------------------------ @@ -117,374 +113,373 @@ typedef std::vector ClusterContainer; //---------------------------------------------------------------------------- void chooseLeafToClusterize(ClusterContainer::iterator &itRet, - KEYER_FLOAT &eigenValue, - KEYER_FLOAT eigenVector[3], - ClusterContainer &clusters); + KEYER_FLOAT &eigenValue, KEYER_FLOAT eigenVector[3], + ClusterContainer &clusters); -void split(Cluster *subcluster1, - Cluster *subcluster2, - KEYER_FLOAT eigenVector[3], - Cluster *cluster); +void split(Cluster *subcluster1, Cluster *subcluster2, + KEYER_FLOAT eigenVector[3], Cluster *cluster); void SolveCubic(KEYER_FLOAT a, /* coefficient of x^3 */ - KEYER_FLOAT b, /* coefficient of x^2 */ - KEYER_FLOAT c, /* coefficient of x */ - KEYER_FLOAT d, /* constant term */ - int *solutions, /* # of distinct solutions */ - KEYER_FLOAT *x); /* array of solutions */ + KEYER_FLOAT b, /* coefficient of x^2 */ + KEYER_FLOAT c, /* coefficient of x */ + KEYER_FLOAT d, /* constant term */ + int *solutions, /* # of distinct solutions */ + KEYER_FLOAT *x); /* array of solutions */ unsigned short int calcCovarianceEigenValues(const KEYER_FLOAT covariance[9], - KEYER_FLOAT eigenValues[3]); + KEYER_FLOAT eigenValues[3]); //---------------------------------------------------------------------------- -void split(Cluster *subcluster1, - Cluster *subcluster2, - KEYER_FLOAT eigenVector[3], - Cluster *cluster) -{ - KEYER_FLOAT n = (KEYER_FLOAT)cluster->statistic.elemsCount; +void split(Cluster *subcluster1, Cluster *subcluster2, + KEYER_FLOAT eigenVector[3], Cluster *cluster) { + KEYER_FLOAT n = (KEYER_FLOAT)cluster->statistic.elemsCount; - KEYER_FLOAT mean[3]; - mean[0] = cluster->statistic.sumComponents[0] / n; - mean[1] = cluster->statistic.sumComponents[1] / n; - mean[2] = cluster->statistic.sumComponents[2] / n; + KEYER_FLOAT mean[3]; + mean[0] = cluster->statistic.sumComponents[0] / n; + mean[1] = cluster->statistic.sumComponents[1] / n; + mean[2] = cluster->statistic.sumComponents[2] / n; - ClusterElemContainer::const_iterator it = cluster->data.begin(); - for (; it != cluster->data.end(); ++it) { - ClusterElem *elem = *it; + ClusterElemContainer::const_iterator it = cluster->data.begin(); + for (; it != cluster->data.end(); ++it) { + ClusterElem *elem = *it; - KEYER_FLOAT r = (KEYER_FLOAT)elem->r; - KEYER_FLOAT g = (KEYER_FLOAT)elem->g; - KEYER_FLOAT b = (KEYER_FLOAT)elem->b; + KEYER_FLOAT r = (KEYER_FLOAT)elem->r; + KEYER_FLOAT g = (KEYER_FLOAT)elem->g; + KEYER_FLOAT b = (KEYER_FLOAT)elem->b; - //cluster->data.erase(it); + // cluster->data.erase(it); - if (eigenVector[0] * r + eigenVector[1] * g + eigenVector[2] * b <= - eigenVector[0] * mean[0] + eigenVector[1] * mean[1] + eigenVector[2] * mean[2]) - subcluster1->insert(elem); - else - subcluster2->insert(elem); - } + if (eigenVector[0] * r + eigenVector[1] * g + eigenVector[2] * b <= + eigenVector[0] * mean[0] + eigenVector[1] * mean[1] + + eigenVector[2] * mean[2]) + subcluster1->insert(elem); + else + subcluster2->insert(elem); + } } //---------------------------------------------------------------------------- void chooseLeafToClusterize(ClusterContainer::iterator &itRet, - KEYER_FLOAT &eigenValue, - KEYER_FLOAT eigenVector[3], - ClusterContainer &clusters) -{ - itRet = clusters.end(); - - ClusterContainer::iterator itFound = clusters.end(); - bool found = false; - KEYER_FLOAT maxEigenValue = 0.0; - - unsigned short int multeplicity = 0; - - ClusterContainer::iterator it = clusters.begin(); - for (; it != clusters.end(); ++it) { - unsigned short int tmpMulteplicity = 0; - KEYER_FLOAT tmpEigenValue; - - Cluster *cluster = *it; - // calcola la matrice di covarianza - const KEYER_FLOAT *clusterCovariance = cluster->statistic.covariance; - assert(!ISNAN(clusterCovariance[0])); - - // calcola gli autovalori della matrice di covarianza della statistica - // del cluster (siccome la matrice e' simmetrica gli autovalori - // sono tutti reali) - KEYER_FLOAT eigenValues[3]; - tmpMulteplicity = calcCovarianceEigenValues(clusterCovariance, eigenValues); - assert(tmpMulteplicity > 0); - - tmpEigenValue = std::max({eigenValues[0], eigenValues[1], eigenValues[2]}); - cluster->eigenValue = tmpEigenValue; - - // eventuale aggiornamento del cluster da cercare - if (itFound == clusters.end()) { - itFound = it; - maxEigenValue = tmpEigenValue; - multeplicity = tmpMulteplicity; - found = true; - } else { - if (tmpEigenValue > maxEigenValue) { - itFound = it; - maxEigenValue = tmpEigenValue; - multeplicity = tmpMulteplicity; - } - } - } - - if (found) { - assert(multeplicity > 0); - itRet = itFound; - eigenValue = maxEigenValue; - - // calcola l'autovettore relativo a maxEigenValue - Cluster *clusterFound = *itFound; - - assert(multeplicity > 0); - - KEYER_FLOAT tmpMatrixM[9]; - - const KEYER_FLOAT *clusterCovariance = clusterFound->statistic.covariance; - int i = 0; - for (; i < 9; ++i) - tmpMatrixM[i] = clusterCovariance[i]; - - tmpMatrixM[0] -= maxEigenValue; - tmpMatrixM[4] -= maxEigenValue; - tmpMatrixM[8] -= maxEigenValue; - - for (i = 0; i < 3; ++i) - eigenVector[i] = 0.0; - - if (multeplicity == 1) { - KEYER_FLOAT u11 = tmpMatrixM[4] * tmpMatrixM[8] - tmpMatrixM[5] * tmpMatrixM[5]; - KEYER_FLOAT u12 = tmpMatrixM[2] * tmpMatrixM[5] - tmpMatrixM[1] * tmpMatrixM[8]; - KEYER_FLOAT u13 = tmpMatrixM[1] * tmpMatrixM[5] - tmpMatrixM[2] * tmpMatrixM[5]; - KEYER_FLOAT u22 = tmpMatrixM[0] * tmpMatrixM[8] - tmpMatrixM[2] * tmpMatrixM[2]; - KEYER_FLOAT u23 = tmpMatrixM[1] * tmpMatrixM[2] - tmpMatrixM[5] * tmpMatrixM[0]; - KEYER_FLOAT u33 = tmpMatrixM[0] * tmpMatrixM[4] - tmpMatrixM[1] * tmpMatrixM[1]; - - KEYER_FLOAT uMax = std::max({u11, u12, u13, u22, u23, u33}); - - if (uMax == u11) { - eigenVector[0] = u11; - eigenVector[1] = u12; - eigenVector[2] = u13; - } else if (uMax == u12) { - eigenVector[0] = u12; - eigenVector[1] = u22; - eigenVector[2] = u23; - } else if (uMax == u13) { - eigenVector[0] = u13; - eigenVector[1] = u23; - eigenVector[2] = u33; - } else if (uMax == u22) { - eigenVector[0] = u12; - eigenVector[1] = u22; - eigenVector[2] = u23; - } else if (uMax == u23) { - eigenVector[0] = u13; - eigenVector[1] = u23; - eigenVector[2] = u33; - } else if (uMax == u33) { - eigenVector[0] = u13; - eigenVector[1] = u23; - eigenVector[2] = u33; - } else { - assert(false && "impossibile!!"); - } - - } else if (multeplicity == 2) { - short int row = -1; - short int col = -1; - - KEYER_FLOAT mMax = std::max({tmpMatrixM[0], tmpMatrixM[1], tmpMatrixM[2], - tmpMatrixM[4], tmpMatrixM[5], tmpMatrixM[8]}); - - if (mMax == tmpMatrixM[0]) { - row = 1; - col = 1; - } else if (mMax == tmpMatrixM[1]) { - row = 1; - col = 2; - } else if (mMax == tmpMatrixM[2]) { - row = 1; - col = 3; - } else if (mMax == tmpMatrixM[4]) { - row = 2; - col = 2; - } else if (mMax == tmpMatrixM[5]) { - row = 2; - col = 3; - } else if (mMax == tmpMatrixM[8]) { - row = 3; - col = 3; - } - - if (row == 1) { - if (col == 1 || col == 2) { - eigenVector[0] = -tmpMatrixM[1]; - eigenVector[1] = tmpMatrixM[0]; - eigenVector[2] = 0.0; - } else { - eigenVector[0] = tmpMatrixM[2]; - eigenVector[1] = 0.0; - eigenVector[2] = -tmpMatrixM[0]; - } - } else if (row == 2) { - eigenVector[0] = 0.0; - eigenVector[1] = -tmpMatrixM[5]; - eigenVector[2] = tmpMatrixM[4]; - } else if (row == 3) { - eigenVector[0] = 0.0; - eigenVector[1] = -tmpMatrixM[8]; - eigenVector[2] = tmpMatrixM[5]; - } - } else if (multeplicity == 3) { - eigenVector[0] = 1.0; - eigenVector[1] = 0.0; - eigenVector[2] = 0.0; - } else { - assert(false && "impossibile!!"); - } - - // normalizzazione dell'autovettore calcolato - /* - KEYER_FLOAT eigenVectorMagnitude = sqrt(eigenVector[0]*eigenVector[0] + - eigenVector[1]*eigenVector[1] + - eigenVector[2]*eigenVector[2]); - assert(eigenVectorMagnitude > 0); - - eigenVector[0] /= eigenVectorMagnitude; - eigenVector[1] /= eigenVectorMagnitude; - eigenVector[2] /= eigenVectorMagnitude; - */ - - clusterFound->eigenVector[0] = eigenVector[0]; - clusterFound->eigenVector[1] = eigenVector[1]; - clusterFound->eigenVector[2] = eigenVector[2]; - - assert(!ISNAN(eigenVector[0])); - assert(!ISNAN(eigenVector[1])); - assert(!ISNAN(eigenVector[2])); - } + KEYER_FLOAT &eigenValue, KEYER_FLOAT eigenVector[3], + ClusterContainer &clusters) { + itRet = clusters.end(); + + ClusterContainer::iterator itFound = clusters.end(); + bool found = false; + KEYER_FLOAT maxEigenValue = 0.0; + + unsigned short int multeplicity = 0; + + ClusterContainer::iterator it = clusters.begin(); + for (; it != clusters.end(); ++it) { + unsigned short int tmpMulteplicity = 0; + KEYER_FLOAT tmpEigenValue; + + Cluster *cluster = *it; + // calcola la matrice di covarianza + const KEYER_FLOAT *clusterCovariance = cluster->statistic.covariance; + assert(!ISNAN(clusterCovariance[0])); + + // calcola gli autovalori della matrice di covarianza della statistica + // del cluster (siccome la matrice e' simmetrica gli autovalori + // sono tutti reali) + KEYER_FLOAT eigenValues[3]; + tmpMulteplicity = calcCovarianceEigenValues(clusterCovariance, eigenValues); + assert(tmpMulteplicity > 0); + + tmpEigenValue = std::max({eigenValues[0], eigenValues[1], eigenValues[2]}); + cluster->eigenValue = tmpEigenValue; + + // eventuale aggiornamento del cluster da cercare + if (itFound == clusters.end()) { + itFound = it; + maxEigenValue = tmpEigenValue; + multeplicity = tmpMulteplicity; + found = true; + } else { + if (tmpEigenValue > maxEigenValue) { + itFound = it; + maxEigenValue = tmpEigenValue; + multeplicity = tmpMulteplicity; + } + } + } + + if (found) { + assert(multeplicity > 0); + itRet = itFound; + eigenValue = maxEigenValue; + + // calcola l'autovettore relativo a maxEigenValue + Cluster *clusterFound = *itFound; + + assert(multeplicity > 0); + + KEYER_FLOAT tmpMatrixM[9]; + + const KEYER_FLOAT *clusterCovariance = clusterFound->statistic.covariance; + int i = 0; + for (; i < 9; ++i) tmpMatrixM[i] = clusterCovariance[i]; + + tmpMatrixM[0] -= maxEigenValue; + tmpMatrixM[4] -= maxEigenValue; + tmpMatrixM[8] -= maxEigenValue; + + for (i = 0; i < 3; ++i) eigenVector[i] = 0.0; + + if (multeplicity == 1) { + KEYER_FLOAT u11 = + tmpMatrixM[4] * tmpMatrixM[8] - tmpMatrixM[5] * tmpMatrixM[5]; + KEYER_FLOAT u12 = + tmpMatrixM[2] * tmpMatrixM[5] - tmpMatrixM[1] * tmpMatrixM[8]; + KEYER_FLOAT u13 = + tmpMatrixM[1] * tmpMatrixM[5] - tmpMatrixM[2] * tmpMatrixM[5]; + KEYER_FLOAT u22 = + tmpMatrixM[0] * tmpMatrixM[8] - tmpMatrixM[2] * tmpMatrixM[2]; + KEYER_FLOAT u23 = + tmpMatrixM[1] * tmpMatrixM[2] - tmpMatrixM[5] * tmpMatrixM[0]; + KEYER_FLOAT u33 = + tmpMatrixM[0] * tmpMatrixM[4] - tmpMatrixM[1] * tmpMatrixM[1]; + + KEYER_FLOAT uMax = std::max({u11, u12, u13, u22, u23, u33}); + + if (uMax == u11) { + eigenVector[0] = u11; + eigenVector[1] = u12; + eigenVector[2] = u13; + } else if (uMax == u12) { + eigenVector[0] = u12; + eigenVector[1] = u22; + eigenVector[2] = u23; + } else if (uMax == u13) { + eigenVector[0] = u13; + eigenVector[1] = u23; + eigenVector[2] = u33; + } else if (uMax == u22) { + eigenVector[0] = u12; + eigenVector[1] = u22; + eigenVector[2] = u23; + } else if (uMax == u23) { + eigenVector[0] = u13; + eigenVector[1] = u23; + eigenVector[2] = u33; + } else if (uMax == u33) { + eigenVector[0] = u13; + eigenVector[1] = u23; + eigenVector[2] = u33; + } else { + assert(false && "impossibile!!"); + } + + } else if (multeplicity == 2) { + short int row = -1; + short int col = -1; + + KEYER_FLOAT mMax = + std::max({tmpMatrixM[0], tmpMatrixM[1], tmpMatrixM[2], tmpMatrixM[4], + tmpMatrixM[5], tmpMatrixM[8]}); + + if (mMax == tmpMatrixM[0]) { + row = 1; + col = 1; + } else if (mMax == tmpMatrixM[1]) { + row = 1; + col = 2; + } else if (mMax == tmpMatrixM[2]) { + row = 1; + col = 3; + } else if (mMax == tmpMatrixM[4]) { + row = 2; + col = 2; + } else if (mMax == tmpMatrixM[5]) { + row = 2; + col = 3; + } else if (mMax == tmpMatrixM[8]) { + row = 3; + col = 3; + } + + if (row == 1) { + if (col == 1 || col == 2) { + eigenVector[0] = -tmpMatrixM[1]; + eigenVector[1] = tmpMatrixM[0]; + eigenVector[2] = 0.0; + } else { + eigenVector[0] = tmpMatrixM[2]; + eigenVector[1] = 0.0; + eigenVector[2] = -tmpMatrixM[0]; + } + } else if (row == 2) { + eigenVector[0] = 0.0; + eigenVector[1] = -tmpMatrixM[5]; + eigenVector[2] = tmpMatrixM[4]; + } else if (row == 3) { + eigenVector[0] = 0.0; + eigenVector[1] = -tmpMatrixM[8]; + eigenVector[2] = tmpMatrixM[5]; + } + } else if (multeplicity == 3) { + eigenVector[0] = 1.0; + eigenVector[1] = 0.0; + eigenVector[2] = 0.0; + } else { + assert(false && "impossibile!!"); + } + + // normalizzazione dell'autovettore calcolato + /* +KEYER_FLOAT eigenVectorMagnitude = sqrt(eigenVector[0]*eigenVector[0] + + eigenVector[1]*eigenVector[1] + + eigenVector[2]*eigenVector[2]); +assert(eigenVectorMagnitude > 0); + +eigenVector[0] /= eigenVectorMagnitude; +eigenVector[1] /= eigenVectorMagnitude; +eigenVector[2] /= eigenVectorMagnitude; +*/ + + clusterFound->eigenVector[0] = eigenVector[0]; + clusterFound->eigenVector[1] = eigenVector[1]; + clusterFound->eigenVector[2] = eigenVector[2]; + + assert(!ISNAN(eigenVector[0])); + assert(!ISNAN(eigenVector[1])); + assert(!ISNAN(eigenVector[2])); + } } //---------------------------------------------------------------------------- -unsigned short int calcCovarianceEigenValues(const KEYER_FLOAT clusterCovariance[9], - KEYER_FLOAT eigenValues[3]) -{ - unsigned short int multeplicity = 0; +unsigned short int calcCovarianceEigenValues( + const KEYER_FLOAT clusterCovariance[9], KEYER_FLOAT eigenValues[3]) { + unsigned short int multeplicity = 0; - KEYER_FLOAT a11 = clusterCovariance[0]; - KEYER_FLOAT a12 = clusterCovariance[1]; - KEYER_FLOAT a13 = clusterCovariance[2]; - KEYER_FLOAT a22 = clusterCovariance[4]; - KEYER_FLOAT a23 = clusterCovariance[5]; - KEYER_FLOAT a33 = clusterCovariance[8]; + KEYER_FLOAT a11 = clusterCovariance[0]; + KEYER_FLOAT a12 = clusterCovariance[1]; + KEYER_FLOAT a13 = clusterCovariance[2]; + KEYER_FLOAT a22 = clusterCovariance[4]; + KEYER_FLOAT a23 = clusterCovariance[5]; + KEYER_FLOAT a33 = clusterCovariance[8]; - KEYER_FLOAT c0 = - (KEYER_FLOAT)(a11 * a22 * a33 + 2.0 * a12 * a13 * a23 - a11 * a23 * a23 - a22 * a13 * a13 - a33 * a12 * a12); + KEYER_FLOAT c0 = + (KEYER_FLOAT)(a11 * a22 * a33 + 2.0 * a12 * a13 * a23 - a11 * a23 * a23 - + a22 * a13 * a13 - a33 * a12 * a12); - KEYER_FLOAT c1 = (KEYER_FLOAT)(a11 * a22 - a12 * a12 + a11 * a33 - a13 * a13 + a22 * a33 - a23 * a23); + KEYER_FLOAT c1 = (KEYER_FLOAT)(a11 * a22 - a12 * a12 + a11 * a33 - a13 * a13 + + a22 * a33 - a23 * a23); - KEYER_FLOAT c2 = (KEYER_FLOAT)(a11 + a22 + a33); + KEYER_FLOAT c2 = (KEYER_FLOAT)(a11 + a22 + a33); - int solutionsCount = 0; - SolveCubic((KEYER_FLOAT)-1.0, c2, -c1, c0, &solutionsCount, eigenValues); - assert(solutionsCount > 0); - multeplicity = 4 - solutionsCount; + int solutionsCount = 0; + SolveCubic((KEYER_FLOAT)-1.0, c2, -c1, c0, &solutionsCount, eigenValues); + assert(solutionsCount > 0); + multeplicity = 4 - solutionsCount; - assert(!ISNAN(eigenValues[0])); - assert(!ISNAN(eigenValues[1])); - assert(!ISNAN(eigenValues[2])); + assert(!ISNAN(eigenValues[0])); + assert(!ISNAN(eigenValues[1])); + assert(!ISNAN(eigenValues[2])); - assert(multeplicity > 0); - return multeplicity; + assert(multeplicity > 0); + return multeplicity; } //---------------------------------------------------------------------------- void SolveCubic(KEYER_FLOAT a, /* coefficient of x^3 */ - KEYER_FLOAT b, /* coefficient of x^2 */ - KEYER_FLOAT c, /* coefficient of x */ - KEYER_FLOAT d, /* constant term */ - int *solutions, /* # of distinct solutions */ - KEYER_FLOAT *x) /* array of solutions */ + KEYER_FLOAT b, /* coefficient of x^2 */ + KEYER_FLOAT c, /* coefficient of x */ + KEYER_FLOAT d, /* constant term */ + int *solutions, /* # of distinct solutions */ + KEYER_FLOAT *x) /* array of solutions */ { - static const KEYER_FLOAT epsilon = (KEYER_FLOAT)0.0001; - if (a != 0 && fabs(b - 0.0) <= epsilon && fabs(c - 0.0) <= epsilon && fabs(d - 0.0) <= epsilon) - //if(a != 0 && b == 0 && c == 0 && d == 0) - { - *solutions = 1; - x[0] = x[1] = x[2] = 0.0; - return; - } - KEYER_FLOAT a1 = (KEYER_FLOAT)(b / a); - KEYER_FLOAT a2 = (KEYER_FLOAT)(c / a); - KEYER_FLOAT a3 = (KEYER_FLOAT)(d / a); - KEYER_FLOAT Q = (KEYER_FLOAT)((a1 * a1 - 3.0 * a2) / 9.0); - KEYER_FLOAT R = (KEYER_FLOAT)((2.0 * a1 * a1 * a1 - 9.0 * a1 * a2 + 27.0 * a3) / 54.0); - KEYER_FLOAT R2_Q3 = (KEYER_FLOAT)(R * R - Q * Q * Q); - KEYER_FLOAT theta; - KEYER_FLOAT PI = (KEYER_FLOAT)3.1415926535897932384626433832795; - - if (R2_Q3 <= 0) { - *solutions = 3; - theta = (KEYER_FLOAT)acos(R / sqrt(Q * Q * Q)); - x[0] = (KEYER_FLOAT)(-2.0 * sqrt(Q) * cos(theta / 3.0) - a1 / 3.0); - x[1] = (KEYER_FLOAT)(-2.0 * sqrt(Q) * cos((theta + 2.0 * PI) / 3.0) - a1 / 3.0); - x[2] = (KEYER_FLOAT)(-2.0 * sqrt(Q) * cos((theta + 4.0 * PI) / 3.0) - a1 / 3.0); - - assert(!ISNAN(x[0])); - assert(!ISNAN(x[1])); - assert(!ISNAN(x[2])); - - /* - long KEYER_FLOAT v; - v = x[0]; - assert(areAlmostEqual(a*v*v*v+b*v*v+c*v+d, 0.0)); - v = x[1]; - assert(areAlmostEqual(a*v*v*v+b*v*v+c*v+d, 0.0)); - v = x[2]; - assert(areAlmostEqual(a*v*v*v+b*v*v+c*v+d, 0.0)); - */ - } else { - *solutions = 1; - x[0] = (KEYER_FLOAT)pow((float)(sqrt(R2_Q3) + fabs(R)), (float)(1 / 3.0)); - x[0] += (KEYER_FLOAT)(Q / x[0]); - x[0] *= (KEYER_FLOAT)((R < 0.0) ? 1 : -1); - x[0] -= (KEYER_FLOAT)(a1 / 3.0); - - assert(!ISNAN(x[0])); - - /* - long KEYER_FLOAT v; - v = x[0]; - assert(areAlmostEqual(a*v*v*v+b*v*v+c*v+d, 0.0)); - */ - } + static const KEYER_FLOAT epsilon = (KEYER_FLOAT)0.0001; + if (a != 0 && fabs(b - 0.0) <= epsilon && fabs(c - 0.0) <= epsilon && + fabs(d - 0.0) <= epsilon) + // if(a != 0 && b == 0 && c == 0 && d == 0) + { + *solutions = 1; + x[0] = x[1] = x[2] = 0.0; + return; + } + KEYER_FLOAT a1 = (KEYER_FLOAT)(b / a); + KEYER_FLOAT a2 = (KEYER_FLOAT)(c / a); + KEYER_FLOAT a3 = (KEYER_FLOAT)(d / a); + KEYER_FLOAT Q = (KEYER_FLOAT)((a1 * a1 - 3.0 * a2) / 9.0); + KEYER_FLOAT R = + (KEYER_FLOAT)((2.0 * a1 * a1 * a1 - 9.0 * a1 * a2 + 27.0 * a3) / 54.0); + KEYER_FLOAT R2_Q3 = (KEYER_FLOAT)(R * R - Q * Q * Q); + KEYER_FLOAT theta; + KEYER_FLOAT PI = (KEYER_FLOAT)3.1415926535897932384626433832795; + + if (R2_Q3 <= 0) { + *solutions = 3; + theta = (KEYER_FLOAT)acos(R / sqrt(Q * Q * Q)); + x[0] = (KEYER_FLOAT)(-2.0 * sqrt(Q) * cos(theta / 3.0) - a1 / 3.0); + x[1] = (KEYER_FLOAT)(-2.0 * sqrt(Q) * cos((theta + 2.0 * PI) / 3.0) - + a1 / 3.0); + x[2] = (KEYER_FLOAT)(-2.0 * sqrt(Q) * cos((theta + 4.0 * PI) / 3.0) - + a1 / 3.0); + + assert(!ISNAN(x[0])); + assert(!ISNAN(x[1])); + assert(!ISNAN(x[2])); + + /* +long KEYER_FLOAT v; +v = x[0]; +assert(areAlmostEqual(a*v*v*v+b*v*v+c*v+d, 0.0)); +v = x[1]; +assert(areAlmostEqual(a*v*v*v+b*v*v+c*v+d, 0.0)); +v = x[2]; +assert(areAlmostEqual(a*v*v*v+b*v*v+c*v+d, 0.0)); +*/ + } else { + *solutions = 1; + x[0] = (KEYER_FLOAT)pow((float)(sqrt(R2_Q3) + fabs(R)), (float)(1 / 3.0)); + x[0] += (KEYER_FLOAT)(Q / x[0]); + x[0] *= (KEYER_FLOAT)((R < 0.0) ? 1 : -1); + x[0] -= (KEYER_FLOAT)(a1 / 3.0); + + assert(!ISNAN(x[0])); + + /* +long KEYER_FLOAT v; +v = x[0]; +assert(areAlmostEqual(a*v*v*v+b*v*v+c*v+d, 0.0)); +*/ + } } //---------------------------------------------------------------------------- //------------------------------------------------------------------------------ -void clusterize(ClusterContainer &clusters, int clustersCount) -{ - unsigned int clustersSize = clusters.size(); - assert(clustersSize >= 1); - - // faccio in modo che in clusters ci siano solo e sempre le foglie - // dell'albero calcolato secondo l'algoritmo TSE descritto da Orchard-Bouman - // (c.f.r. "Color Quantization of Images" - M.Orchard, C. Bouman) - - // numero di iterazioni, numero di cluster = numero di iterazioni + 1 - int m = clustersCount - 1; - int i = 0; - for (; i < m; ++i) { - // sceglie la foglia dell'albero dei cluster (ovvero il cluster nel - // ClusterContainer "clusters") che ha il maggiore autovalore, ovvero - // il cluster che ha maggiore varainza rispetto all'asse opportuno - // (che poi e' l'autovettore corrispondente all'autovalore piu' grande) - KEYER_FLOAT eigenValue = 0.0; - KEYER_FLOAT eigenVector[3] = {0.0, 0.0, 0.0}; - ClusterContainer::iterator itChoosedCluster; - - chooseLeafToClusterize(itChoosedCluster, - eigenValue, - eigenVector, - clusters); - - assert(itChoosedCluster != clusters.end()); - Cluster *choosedCluster = *itChoosedCluster; +void clusterize(ClusterContainer &clusters, int clustersCount) { + unsigned int clustersSize = clusters.size(); + assert(clustersSize >= 1); + + // faccio in modo che in clusters ci siano solo e sempre le foglie + // dell'albero calcolato secondo l'algoritmo TSE descritto da Orchard-Bouman + // (c.f.r. "Color Quantization of Images" - M.Orchard, C. Bouman) + + // numero di iterazioni, numero di cluster = numero di iterazioni + 1 + int m = clustersCount - 1; + int i = 0; + for (; i < m; ++i) { + // sceglie la foglia dell'albero dei cluster (ovvero il cluster nel + // ClusterContainer "clusters") che ha il maggiore autovalore, ovvero + // il cluster che ha maggiore varainza rispetto all'asse opportuno + // (che poi e' l'autovettore corrispondente all'autovalore piu' grande) + KEYER_FLOAT eigenValue = 0.0; + KEYER_FLOAT eigenVector[3] = {0.0, 0.0, 0.0}; + ClusterContainer::iterator itChoosedCluster; + + chooseLeafToClusterize(itChoosedCluster, eigenValue, eigenVector, clusters); + + assert(itChoosedCluster != clusters.end()); + Cluster *choosedCluster = *itChoosedCluster; #if 0 @@ -498,266 +493,242 @@ void clusterize(ClusterContainer &clusters, int clustersCount) #else - // un cluster che ha un solo elemento non ha molto senso di esistere, - // credo crei problemi anche nel calcolo della matrice di covarianza, - // quindi mi fermo quando il cluster contiene meno di 4 elementi - if (choosedCluster->statistic.elemsCount == 3) - break; + // un cluster che ha un solo elemento non ha molto senso di esistere, + // credo crei problemi anche nel calcolo della matrice di covarianza, + // quindi mi fermo quando il cluster contiene meno di 4 elementi + if (choosedCluster->statistic.elemsCount == 3) break; #endif - // suddivide il cluster scelto in altri due cluster - Cluster *subcluster1 = new Cluster(); - Cluster *subcluster2 = new Cluster(); - split(subcluster1, subcluster2, eigenVector, choosedCluster); - assert(subcluster1); - assert(subcluster2); - if ((subcluster1->data.size() == 0) || - (subcluster2->data.size() == 0)) - break; - - // calcola la nuova statistica per subcluster1 - subcluster1->computeStatistics(); - - // calcola la nuova statistica per subcluster2 - int j = 0; - for (; j < 3; ++j) { - subcluster2->statistic.sumComponents[j] = - choosedCluster->statistic.sumComponents[j] - - subcluster1->statistic.sumComponents[j]; - } - - subcluster2->statistic.sumCoords.x = - choosedCluster->statistic.sumCoords.x - - subcluster1->statistic.sumCoords.x; - - subcluster2->statistic.sumCoords.y = - choosedCluster->statistic.sumCoords.y - - subcluster1->statistic.sumCoords.y; - - subcluster2->statistic.elemsCount = - choosedCluster->statistic.elemsCount - - subcluster1->statistic.elemsCount; + // suddivide il cluster scelto in altri due cluster + Cluster *subcluster1 = new Cluster(); + Cluster *subcluster2 = new Cluster(); + split(subcluster1, subcluster2, eigenVector, choosedCluster); + assert(subcluster1); + assert(subcluster2); + if ((subcluster1->data.size() == 0) || (subcluster2->data.size() == 0)) + break; + + // calcola la nuova statistica per subcluster1 + subcluster1->computeStatistics(); + + // calcola la nuova statistica per subcluster2 + int j = 0; + for (; j < 3; ++j) { + subcluster2->statistic.sumComponents[j] = + choosedCluster->statistic.sumComponents[j] - + subcluster1->statistic.sumComponents[j]; + } + + subcluster2->statistic.sumCoords.x = choosedCluster->statistic.sumCoords.x - + subcluster1->statistic.sumCoords.x; + + subcluster2->statistic.sumCoords.y = choosedCluster->statistic.sumCoords.y - + subcluster1->statistic.sumCoords.y; + + subcluster2->statistic.elemsCount = choosedCluster->statistic.elemsCount - + subcluster1->statistic.elemsCount; #ifdef WITH_ALPHA_IN_STATISTICS - subcluster2->statistic.sumAlpha = - choosedCluster->statistic.sumAlpha - - subcluster1->statistic.sumAlpha; + subcluster2->statistic.sumAlpha = + choosedCluster->statistic.sumAlpha - subcluster1->statistic.sumAlpha; #endif - for (j = 0; j < 9; ++j) - subcluster2->statistic.matrixR[j] = - choosedCluster->statistic.matrixR[j] - - subcluster1->statistic.matrixR[j]; - - subcluster2->computeCovariance(); - - // aggiorna in modo opportuno il ClusterContainer "clusters", cancellando - // il cluster scelto e inserendo i due appena creati. - // Facendo cosi' il ClusterContainer "cluster" contiene solo e sempre - // le foglie dell'albero creato dall'algoritmo TSE. - - Cluster *cluster = *itChoosedCluster; - assert(cluster); - cluster->data.clear(); - //clearPointerContainer(cluster->data); - assert(cluster->data.size() == 0); - delete cluster; - clusters.erase(itChoosedCluster); - - clusters.push_back(subcluster1); - clusters.push_back(subcluster2); - } + for (j = 0; j < 9; ++j) + subcluster2->statistic.matrixR[j] = choosedCluster->statistic.matrixR[j] - + subcluster1->statistic.matrixR[j]; + + subcluster2->computeCovariance(); + + // aggiorna in modo opportuno il ClusterContainer "clusters", cancellando + // il cluster scelto e inserendo i due appena creati. + // Facendo cosi' il ClusterContainer "cluster" contiene solo e sempre + // le foglie dell'albero creato dall'algoritmo TSE. + + Cluster *cluster = *itChoosedCluster; + assert(cluster); + cluster->data.clear(); + // clearPointerContainer(cluster->data); + assert(cluster->data.size() == 0); + delete cluster; + clusters.erase(itChoosedCluster); + + clusters.push_back(subcluster1); + clusters.push_back(subcluster2); + } } //------------------------------------------------------------------------------ -Cluster::Cluster() -{ -} +Cluster::Cluster() {} //------------------------------------------------------------------------------ -Cluster::Cluster(const Cluster &rhs) - : statistic(rhs.statistic) -{ - ClusterElemContainer::const_iterator it = rhs.data.begin(); - for (; it != rhs.data.end(); ++it) - data.push_back(new ClusterElem(**it)); +Cluster::Cluster(const Cluster &rhs) : statistic(rhs.statistic) { + ClusterElemContainer::const_iterator it = rhs.data.begin(); + for (; it != rhs.data.end(); ++it) data.push_back(new ClusterElem(**it)); } //------------------------------------------------------------------------------ -Cluster::~Cluster() -{ - clearPointerContainer(data); -} +Cluster::~Cluster() { clearPointerContainer(data); } //------------------------------------------------------------------------------ -void Cluster::computeCovariance() -{ - KEYER_FLOAT sumComponentsMatrix[9]; - - KEYER_FLOAT sumR = statistic.sumComponents[0]; - KEYER_FLOAT sumG = statistic.sumComponents[1]; - KEYER_FLOAT sumB = statistic.sumComponents[2]; - - sumComponentsMatrix[0] = sumR * sumR; - sumComponentsMatrix[1] = sumR * sumG; - sumComponentsMatrix[2] = sumR * sumB; - - sumComponentsMatrix[3] = sumComponentsMatrix[1]; - sumComponentsMatrix[4] = sumG * sumG; - sumComponentsMatrix[5] = sumG * sumB; - - sumComponentsMatrix[6] = sumComponentsMatrix[2]; - sumComponentsMatrix[7] = sumComponentsMatrix[5]; - sumComponentsMatrix[8] = sumB * sumB; - - KEYER_FLOAT n = (KEYER_FLOAT)statistic.elemsCount; - assert(n > 0); - int i = 0; - for (; i < 9; ++i) { - statistic.covariance[i] = - statistic.matrixR[i] - sumComponentsMatrix[i] / n; - assert(!ISNAN(statistic.matrixR[i])); - //assert(statistic.covariance[i] >= 0.0); - // instabilita' numerica ??? - if (statistic.covariance[i] < 0.0) - statistic.covariance[i] = 0.0; - } +void Cluster::computeCovariance() { + KEYER_FLOAT sumComponentsMatrix[9]; + + KEYER_FLOAT sumR = statistic.sumComponents[0]; + KEYER_FLOAT sumG = statistic.sumComponents[1]; + KEYER_FLOAT sumB = statistic.sumComponents[2]; + + sumComponentsMatrix[0] = sumR * sumR; + sumComponentsMatrix[1] = sumR * sumG; + sumComponentsMatrix[2] = sumR * sumB; + + sumComponentsMatrix[3] = sumComponentsMatrix[1]; + sumComponentsMatrix[4] = sumG * sumG; + sumComponentsMatrix[5] = sumG * sumB; + + sumComponentsMatrix[6] = sumComponentsMatrix[2]; + sumComponentsMatrix[7] = sumComponentsMatrix[5]; + sumComponentsMatrix[8] = sumB * sumB; + + KEYER_FLOAT n = (KEYER_FLOAT)statistic.elemsCount; + assert(n > 0); + int i = 0; + for (; i < 9; ++i) { + statistic.covariance[i] = statistic.matrixR[i] - sumComponentsMatrix[i] / n; + assert(!ISNAN(statistic.matrixR[i])); + // assert(statistic.covariance[i] >= 0.0); + // instabilita' numerica ??? + if (statistic.covariance[i] < 0.0) statistic.covariance[i] = 0.0; + } } //------------------------------------------------------------------------------ -void Cluster::insert(ClusterElem *elem) -{ - +void Cluster::insert(ClusterElem *elem) { #ifdef CLUSTER_ELEM_CONTAINER_IS_A_SET - data.insert(elem); + data.insert(elem); #else - data.push_back(elem); + data.push_back(elem); #endif } //------------------------------------------------------------------------------ -void Cluster::computeStatistics() -{ - // inizializza a zero la statistica del cluster - statistic.elemsCount = 0; +void Cluster::computeStatistics() { + // inizializza a zero la statistica del cluster + statistic.elemsCount = 0; - statistic.sumCoords = TPoint(0, 0); + statistic.sumCoords = TPoint(0, 0); - int i = 0; - for (; i < 3; ++i) - statistic.sumComponents[i] = 0.0; + int i = 0; + for (; i < 3; ++i) statistic.sumComponents[i] = 0.0; - for (i = 0; i < 9; ++i) - statistic.matrixR[i] = 0.0; + for (i = 0; i < 9; ++i) statistic.matrixR[i] = 0.0; - // calcola la statistica del cluster - ClusterElemContainer::const_iterator it = data.begin(); - for (; it != data.end(); ++it) { - const ClusterElem *elem = *it; + // calcola la statistica del cluster + ClusterElemContainer::const_iterator it = data.begin(); + for (; it != data.end(); ++it) { + const ClusterElem *elem = *it; #ifdef WITH_ALPHA_IN_STATISTICS - KEYER_FLOAT alpha = elem->a; + KEYER_FLOAT alpha = elem->a; #endif - KEYER_FLOAT r = (KEYER_FLOAT)elem->r; - KEYER_FLOAT g = (KEYER_FLOAT)elem->g; - KEYER_FLOAT b = (KEYER_FLOAT)elem->b; + KEYER_FLOAT r = (KEYER_FLOAT)elem->r; + KEYER_FLOAT g = (KEYER_FLOAT)elem->g; + KEYER_FLOAT b = (KEYER_FLOAT)elem->b; - statistic.sumComponents[0] += r; - statistic.sumComponents[1] += g; - statistic.sumComponents[2] += b; + statistic.sumComponents[0] += r; + statistic.sumComponents[1] += g; + statistic.sumComponents[2] += b; #ifdef WITH_ALPHA_IN_STATISTICS - statistic.sumAlpha += alpha; + statistic.sumAlpha += alpha; #endif - // prima riga della matrice R - statistic.matrixR[0] += r * r; - statistic.matrixR[1] += r * g; - statistic.matrixR[2] += r * b; + // prima riga della matrice R + statistic.matrixR[0] += r * r; + statistic.matrixR[1] += r * g; + statistic.matrixR[2] += r * b; - // seconda riga della matrice R - statistic.matrixR[3] += r * g; - statistic.matrixR[4] += g * g; - statistic.matrixR[5] += g * b; + // seconda riga della matrice R + statistic.matrixR[3] += r * g; + statistic.matrixR[4] += g * g; + statistic.matrixR[5] += g * b; - // terza riga della matrice R - statistic.matrixR[6] += r * b; - statistic.matrixR[7] += b * g; - statistic.matrixR[8] += b * b; + // terza riga della matrice R + statistic.matrixR[6] += r * b; + statistic.matrixR[7] += b * g; + statistic.matrixR[8] += b * b; - statistic.sumCoords.x += elem->x; - statistic.sumCoords.y += elem->y; + statistic.sumCoords.x += elem->x; + statistic.sumCoords.y += elem->y; - ++statistic.elemsCount; - } + ++statistic.elemsCount; + } - assert(statistic.elemsCount > 0); + assert(statistic.elemsCount > 0); - computeCovariance(); + computeCovariance(); } //------------------------------------------------------------------------------ -void Cluster::getMeanAxis(KEYER_FLOAT axis[3]) -{ - KEYER_FLOAT n = (KEYER_FLOAT)statistic.elemsCount; +void Cluster::getMeanAxis(KEYER_FLOAT axis[3]) { + KEYER_FLOAT n = (KEYER_FLOAT)statistic.elemsCount; #if 1 - axis[0] = (KEYER_FLOAT)(sqrt(statistic.covariance[0]) / n); - axis[1] = (KEYER_FLOAT)(sqrt(statistic.covariance[4]) / n); - axis[2] = (KEYER_FLOAT)(sqrt(statistic.covariance[8]) / n); + axis[0] = (KEYER_FLOAT)(sqrt(statistic.covariance[0]) / n); + axis[1] = (KEYER_FLOAT)(sqrt(statistic.covariance[4]) / n); + axis[2] = (KEYER_FLOAT)(sqrt(statistic.covariance[8]) / n); #else - KEYER_FLOAT I[3]; - KEYER_FLOAT J[3]; - KEYER_FLOAT K[3]; - - I[0] = statistic.covariance[0]; - I[1] = statistic.covariance[1]; - I[2] = statistic.covariance[2]; - - J[0] = statistic.covariance[3]; - J[1] = statistic.covariance[4]; - J[2] = statistic.covariance[5]; - - K[0] = statistic.covariance[6]; - K[1] = statistic.covariance[7]; - K[2] = statistic.covariance[8]; - - KEYER_FLOAT magnitudeI = I[0] * I[0] + I[1] * I[1] + I[2] * I[2]; - KEYER_FLOAT magnitudeJ = J[0] * J[0] + J[1] * J[1] + J[2] * I[2]; - KEYER_FLOAT magnitudeK = K[0] * K[0] + K[1] * K[1] + K[2] * I[2]; - - if (magnitudeI >= magnitudeJ && magnitudeI >= magnitudeK) { - axis[0] = sqrt(I[0] / n); - axis[1] = sqrt(I[1] / n); - axis[2] = sqrt(I[2] / n); - } else if (magnitudeJ >= magnitudeI && magnitudeJ >= magnitudeK) { - axis[0] = sqrt(J[0] / n); - axis[1] = sqrt(J[1] / n); - axis[2] = sqrt(J[2] / n); - } else if (magnitudeK >= magnitudeI && magnitudeK >= magnitudeJ) { - axis[0] = sqrt(K[0] / n); - axis[1] = sqrt(K[1] / n); - axis[2] = sqrt(K[2] / n); - } + KEYER_FLOAT I[3]; + KEYER_FLOAT J[3]; + KEYER_FLOAT K[3]; + + I[0] = statistic.covariance[0]; + I[1] = statistic.covariance[1]; + I[2] = statistic.covariance[2]; + + J[0] = statistic.covariance[3]; + J[1] = statistic.covariance[4]; + J[2] = statistic.covariance[5]; + + K[0] = statistic.covariance[6]; + K[1] = statistic.covariance[7]; + K[2] = statistic.covariance[8]; + + KEYER_FLOAT magnitudeI = I[0] * I[0] + I[1] * I[1] + I[2] * I[2]; + KEYER_FLOAT magnitudeJ = J[0] * J[0] + J[1] * J[1] + J[2] * I[2]; + KEYER_FLOAT magnitudeK = K[0] * K[0] + K[1] * K[1] + K[2] * I[2]; + + if (magnitudeI >= magnitudeJ && magnitudeI >= magnitudeK) { + axis[0] = sqrt(I[0] / n); + axis[1] = sqrt(I[1] / n); + axis[2] = sqrt(I[2] / n); + } else if (magnitudeJ >= magnitudeI && magnitudeJ >= magnitudeK) { + axis[0] = sqrt(J[0] / n); + axis[1] = sqrt(J[1] / n); + axis[2] = sqrt(J[2] / n); + } else if (magnitudeK >= magnitudeI && magnitudeK >= magnitudeJ) { + axis[0] = sqrt(K[0] / n); + axis[1] = sqrt(K[1] / n); + axis[2] = sqrt(K[2] / n); + } #endif } @@ -766,146 +737,142 @@ void Cluster::getMeanAxis(KEYER_FLOAT axis[3]) //#define METODO_USATO_SU_TOONZ46 -void buildPaletteForBlendedImages(std::set &palette, const TRaster32P &raster, int maxColorCount) -{ - int lx = raster->getLx(); - int ly = raster->getLy(); - - ClusterContainer clusters; - Cluster *cluster = new Cluster; - raster->lock(); - for (int y = 0; y < ly; ++y) { - TPixel32 *pix = raster->pixels(y); - for (int x = 0; x < lx; ++x) { - TPixel32 color = *(pix + x); - ClusterElem *ce = new ClusterElem(color.r, color.g, color.b, (float)(color.m / 255.0)); - cluster->insert(ce); - } - } - raster->unlock(); - cluster->computeStatistics(); - - clusters.push_back(cluster); - clusterize(clusters, maxColorCount); - - palette.clear(); - //palette.reserve( clusters.size()); - - for (UINT i = 0; i < clusters.size(); ++i) { - ClusterStatistic &stat = clusters[i]->statistic; - TPixel32 col((int)(stat.sumComponents[0] / stat.elemsCount * 255), - (int)(stat.sumComponents[1] / stat.elemsCount * 255), - (int)(stat.sumComponents[2] / stat.elemsCount * 255), - 255); - palette.insert(col); - - clearPointerContainer(clusters[i]->data); - } - - clearPointerContainer(clusters); +void buildPaletteForBlendedImages(std::set &palette, + const TRaster32P &raster, int maxColorCount) { + int lx = raster->getLx(); + int ly = raster->getLy(); + + ClusterContainer clusters; + Cluster *cluster = new Cluster; + raster->lock(); + for (int y = 0; y < ly; ++y) { + TPixel32 *pix = raster->pixels(y); + for (int x = 0; x < lx; ++x) { + TPixel32 color = *(pix + x); + ClusterElem *ce = + new ClusterElem(color.r, color.g, color.b, (float)(color.m / 255.0)); + cluster->insert(ce); + } + } + raster->unlock(); + cluster->computeStatistics(); + + clusters.push_back(cluster); + clusterize(clusters, maxColorCount); + + palette.clear(); + // palette.reserve( clusters.size()); + + for (UINT i = 0; i < clusters.size(); ++i) { + ClusterStatistic &stat = clusters[i]->statistic; + TPixel32 col((int)(stat.sumComponents[0] / stat.elemsCount * 255), + (int)(stat.sumComponents[1] / stat.elemsCount * 255), + (int)(stat.sumComponents[2] / stat.elemsCount * 255), 255); + palette.insert(col); + + clearPointerContainer(clusters[i]->data); + } + + clearPointerContainer(clusters); } //------------------------------------------------------------------------------ -namespace -{ +namespace { #define DISTANCE 3 -bool inline areNear(const TPixel &c1, const TPixel &c2) -{ - if (abs(c1.r - c2.r) > DISTANCE) - return false; - if (abs(c1.g - c2.g) > DISTANCE) - return false; - if (abs(c1.b - c2.b) > DISTANCE) - return false; - if (abs(c1.m - c2.m) > DISTANCE) - return false; - - return true; +bool inline areNear(const TPixel &c1, const TPixel &c2) { + if (abs(c1.r - c2.r) > DISTANCE) return false; + if (abs(c1.g - c2.g) > DISTANCE) return false; + if (abs(c1.b - c2.b) > DISTANCE) return false; + if (abs(c1.m - c2.m) > DISTANCE) return false; + + return true; } -bool find(const std::set &palette, const TPixel &color) -{ - std::set::const_iterator it = palette.begin(); +bool find(const std::set &palette, const TPixel &color) { + std::set::const_iterator it = palette.begin(); - while (it != palette.end()) { - if (areNear(*it, color)) - return true; - ++it; - } + while (it != palette.end()) { + if (areNear(*it, color)) return true; + ++it; + } - return false; + return false; } -} //namespace +} // namespace /*-- 似ている色をまとめて1つのStyleにする --*/ -void TColorUtils::buildPalette(std::set &palette, const TRaster32P &raster, int maxColorCount) -{ - int lx = raster->getLx(); - int ly = raster->getLy(); - int wrap = raster->getWrap(); - - int x, y; - TPixel old = TPixel::Black; - int solidColors = 0; - int count = maxColorCount; - raster->lock(); - for (y = 1; y < ly - 1 && count > 0; y++) { - TPixel *pix = raster->pixels(y); - for (x = 1; x < lx - 1 && count > 0; x++, pix++) { - TPixel color = *pix; - if (areNear(color, *(pix - 1)) && areNear(color, *(pix + 1)) && - areNear(color, *(pix - wrap)) && areNear(color, *(pix + wrap)) && - areNear(color, *(pix - wrap - 1)) && areNear(color, *(pix - wrap + 1)) && - areNear(color, *(pix + wrap - 1)) && areNear(color, *(pix + wrap + 1))) { - solidColors++; - if (!areNear(*pix, old) && !find(palette, *pix)) { - old = color; - count--; - palette.insert(color); - } - } - } - } - - raster->unlock(); - - if (solidColors < lx * ly / 2) { - palette.clear(); - buildPaletteForBlendedImages(palette, raster, maxColorCount); - } +void TColorUtils::buildPalette(std::set &palette, + const TRaster32P &raster, int maxColorCount) { + int lx = raster->getLx(); + int ly = raster->getLy(); + int wrap = raster->getWrap(); + + int x, y; + TPixel old = TPixel::Black; + int solidColors = 0; + int count = maxColorCount; + raster->lock(); + for (y = 1; y < ly - 1 && count > 0; y++) { + TPixel *pix = raster->pixels(y); + for (x = 1; x < lx - 1 && count > 0; x++, pix++) { + TPixel color = *pix; + if (areNear(color, *(pix - 1)) && areNear(color, *(pix + 1)) && + areNear(color, *(pix - wrap)) && areNear(color, *(pix + wrap)) && + areNear(color, *(pix - wrap - 1)) && + areNear(color, *(pix - wrap + 1)) && + areNear(color, *(pix + wrap - 1)) && + areNear(color, *(pix + wrap + 1))) { + solidColors++; + if (!areNear(*pix, old) && !find(palette, *pix)) { + old = color; + count--; + palette.insert(color); + } + } + } + } + + raster->unlock(); + + if (solidColors < lx * ly / 2) { + palette.clear(); + buildPaletteForBlendedImages(palette, raster, maxColorCount); + } } /*-- 全ての異なるピクセルの色を別のStyleにする --*/ -void TColorUtils::buildPrecisePalette(std::set &palette, const TRaster32P &raster, int maxColorCount) -{ - int lx = raster->getLx(); - int ly = raster->getLy(); - int wrap = raster->getWrap(); - - int x, y; - int count = maxColorCount; - raster->lock(); - for (y = 1; y < ly - 1 && count > 0; y++) { - TPixel *pix = raster->pixels(y); - for (x = 1; x < lx - 1 && count > 0; x++, pix++) { - if (!find(palette, *pix)) { - TPixel color = *pix; - count--; - palette.insert(color); - } - } - } - - raster->unlock(); - - /*-- 色数が最大値を超えたら、似ている色をまとめて1つのStyleにする手法を行う --*/ - if (count == 0) { - palette.clear(); - buildPalette(palette, raster, maxColorCount); - } +void TColorUtils::buildPrecisePalette(std::set &palette, + const TRaster32P &raster, + int maxColorCount) { + int lx = raster->getLx(); + int ly = raster->getLy(); + int wrap = raster->getWrap(); + + int x, y; + int count = maxColorCount; + raster->lock(); + for (y = 1; y < ly - 1 && count > 0; y++) { + TPixel *pix = raster->pixels(y); + for (x = 1; x < lx - 1 && count > 0; x++, pix++) { + if (!find(palette, *pix)) { + TPixel color = *pix; + count--; + palette.insert(color); + } + } + } + + raster->unlock(); + + /*-- 色数が最大値を超えたら、似ている色をまとめて1つのStyleにする手法を行う + * --*/ + if (count == 0) { + palette.clear(); + buildPalette(palette, raster, maxColorCount); + } } //------------------------------------------------------------------------------ diff --git a/toonz/sources/common/tapptools/tenv.cpp b/toonz/sources/common/tapptools/tenv.cpp index f41fe41..d7b3268 100644 --- a/toonz/sources/common/tapptools/tenv.cpp +++ b/toonz/sources/common/tapptools/tenv.cpp @@ -17,14 +17,13 @@ // Imposto l'offlineGL usando AGL (per togliere la dipendenza da X) -TOfflineGL::Imp *MacOfflineGenerator1(const TDimension &dim) -{ - return new MacImplementation(dim); +TOfflineGL::Imp *MacOfflineGenerator1(const TDimension &dim) { + return new MacImplementation(dim); } #endif #include -#include +#include using namespace TEnv; @@ -34,180 +33,168 @@ using namespace TEnv; // //========================================================= -namespace -{ +namespace { -class EnvGlobals -{ // singleton +class EnvGlobals { // singleton - std::string m_applicationName; - std::string m_applicationVersion; - std::string m_applicationVersionWithoutRevision; - std::string m_applicationFullName; - std::string m_moduleName; - std::string m_rootVarName; - std::string m_systemVarPrefix; - TFilePath m_registryRoot; - TFilePath m_envFile; - TFilePath *m_stuffDir; - TFilePath *m_dllRelativeDir; + std::string m_applicationName; + std::string m_applicationVersion; + std::string m_applicationVersionWithoutRevision; + std::string m_applicationFullName; + std::string m_moduleName; + std::string m_rootVarName; + std::string m_systemVarPrefix; + TFilePath m_registryRoot; + TFilePath m_envFile; + TFilePath *m_stuffDir; + TFilePath *m_dllRelativeDir; - EnvGlobals() : m_stuffDir(0) {} + EnvGlobals() : m_stuffDir(0) {} public: - ~EnvGlobals() { delete m_stuffDir; } + ~EnvGlobals() { delete m_stuffDir; } - static EnvGlobals *instance() - { - static EnvGlobals _instance; - return &_instance; - } + static EnvGlobals *instance() { + static EnvGlobals _instance; + return &_instance; + } - TFilePath getSystemVarPath(std::string varName) - { + TFilePath getSystemVarPath(std::string varName) { #ifdef _WIN32 - return m_registryRoot + varName; + return m_registryRoot + varName; #else - QString settingsPath; + QString settingsPath; #ifdef MACOSX - settingsPath = QString::fromStdString(getApplicationName()) + QString("_") + - QString::fromStdString(getApplicationVersionWithoutRevision()) + QString(".app") + - QString("/Contents/Resources/SystemVar.ini"); -#else /* Generic Unix */ - // TODO: use QStandardPaths::ConfigLocation when we drop Qt4 - settingsPath = QDir::homePath(); - settingsPath.append("/.config/"); - settingsPath.append(getApplicationName().c_str()); - settingsPath.append("/SystemVar.ini"); + settingsPath = + QString::fromStdString(getApplicationName()) + QString("_") + + QString::fromStdString(getApplicationVersionWithoutRevision()) + + QString(".app") + QString("/Contents/Resources/SystemVar.ini"); +#else /* Generic Unix */ + // TODO: use QStandardPaths::ConfigLocation when we drop Qt4 + settingsPath = QDir::homePath(); + settingsPath.append("/.config/"); + settingsPath.append(getApplicationName().c_str()); + settingsPath.append("/SystemVar.ini"); #endif - QSettings settings(settingsPath, QSettings::IniFormat); - QString qStr = QString::fromStdString(varName); - QString systemVar = settings.value(qStr).toString(); - //printf("getSystemVarPath: path:%s key:%s var:%s\n", settingsPath.toStdString().data(), varName.data(), systemVar.toStdString().data()); - return TFilePath(systemVar.toStdWString()); + QSettings settings(settingsPath, QSettings::IniFormat); + QString qStr = QString::fromStdString(varName); + QString systemVar = settings.value(qStr).toString(); + // printf("getSystemVarPath: path:%s key:%s var:%s\n", + // settingsPath.toStdString().data(), varName.data(), + // systemVar.toStdString().data()); + return TFilePath(systemVar.toStdWString()); #endif - } + } - TFilePath getRootVarPath() - { - return getSystemVarPath(m_rootVarName); - } + TFilePath getRootVarPath() { return getSystemVarPath(m_rootVarName); } - std::string getSystemVarValue(std::string varName) - { + std::string getSystemVarValue(std::string varName) { #ifdef _WIN32 - return TSystem::getSystemValue(getSystemVarPath(varName)).toStdString(); + return TSystem::getSystemValue(getSystemVarPath(varName)).toStdString(); #else - TFilePath systemVarPath = getSystemVarPath(varName); - if (systemVarPath.isEmpty()) { - std::cout << "varName:" << varName << " TOONZROOT not set..." << std::endl; - return ""; - } - return ::to_string(systemVarPath); + TFilePath systemVarPath = getSystemVarPath(varName); + if (systemVarPath.isEmpty()) { + std::cout << "varName:" << varName << " TOONZROOT not set..." + << std::endl; + return ""; + } + return ::to_string(systemVarPath); /* - char *value = getenv(varName.c_str()); - if (!value) - { - std::cout << varName << " not set, returning TOONZROOT" << std::endl; + char *value = getenv(varName.c_str()); + if (!value) + { + std::cout << varName << " not set, returning + TOONZROOT" << std::endl; //value = getenv("TOONZROOT"); value=""; std::cout << "!!!value= "<< value << std::endl; - if (!value) - { - std::cout << varName << "TOONZROOT not set..." << std::endl; - //exit(-1); - return ""; - } - } + if (!value) + { + std::cout << varName << "TOONZROOT not + set..." << std::endl; + //exit(-1); + return ""; + } + } return string(value); - */ + */ #endif - } - - TFilePath getStuffDir() - { - if (m_stuffDir) - return *m_stuffDir; - return TFilePath(getSystemVarValue(m_rootVarName)); - } - void setStuffDir(const TFilePath &stuffDir) - { - delete m_stuffDir; - m_stuffDir = new TFilePath(stuffDir); - } - - void updateEnvFile() - { - TFilePath profilesDir = getSystemVarPathValue(getSystemVarPrefix() + "PROFILES"); - if (profilesDir == TFilePath()) - profilesDir = getStuffDir() + "profiles"; - m_envFile = profilesDir + "env" + (TSystem::getUserName().toStdString() + ".env"); - } - - void setApplication(std::string applicationName, std::string applicationVersion, std::string revision) - { - m_applicationName = applicationName; - m_applicationVersionWithoutRevision = applicationVersion; - if (!revision.empty()) { - m_applicationVersion = m_applicationVersionWithoutRevision + "." + revision; - } else { - m_applicationVersion = m_applicationVersionWithoutRevision; - } - m_applicationFullName = m_applicationName + " " + m_applicationVersion; - m_moduleName = m_applicationName; - m_rootVarName = toUpper(m_applicationName) + "ROOT"; + } + + TFilePath getStuffDir() { + if (m_stuffDir) return *m_stuffDir; + return TFilePath(getSystemVarValue(m_rootVarName)); + } + void setStuffDir(const TFilePath &stuffDir) { + delete m_stuffDir; + m_stuffDir = new TFilePath(stuffDir); + } + + void updateEnvFile() { + TFilePath profilesDir = + getSystemVarPathValue(getSystemVarPrefix() + "PROFILES"); + if (profilesDir == TFilePath()) profilesDir = getStuffDir() + "profiles"; + m_envFile = + profilesDir + "env" + (TSystem::getUserName().toStdString() + ".env"); + } + + void setApplication(std::string applicationName, + std::string applicationVersion, std::string revision) { + m_applicationName = applicationName; + m_applicationVersionWithoutRevision = applicationVersion; + if (!revision.empty()) { + m_applicationVersion = + m_applicationVersionWithoutRevision + "." + revision; + } else { + m_applicationVersion = m_applicationVersionWithoutRevision; + } + m_applicationFullName = m_applicationName + " " + m_applicationVersion; + m_moduleName = m_applicationName; + m_rootVarName = toUpper(m_applicationName) + "ROOT"; #ifdef _WIN32 - m_registryRoot = TFilePath("SOFTWARE\\OpenToonz\\") + m_applicationName + applicationVersion; + m_registryRoot = TFilePath("SOFTWARE\\OpenToonz\\") + m_applicationName + + applicationVersion; #endif - m_systemVarPrefix = m_applicationName; - updateEnvFile(); - } - - std::string getApplicationName() { return m_applicationName; } - std::string getApplicationVersion() { return m_applicationVersion; } - std::string getApplicationVersionWithoutRevision() { return m_applicationVersionWithoutRevision; } - - TFilePath getEnvFile() { return m_envFile; } - - void setApplicationFullName(std::string applicationFullName) - { - m_applicationFullName = applicationFullName; - } - std::string getApplicationFullName() { return m_applicationFullName; } - - void setModuleName(std::string moduleName) { m_moduleName = moduleName; } - std::string getModuleName() { return m_moduleName; } - - void setRootVarName(std::string varName) - { - m_rootVarName = varName; - updateEnvFile(); - } - std::string getRootVarName() - { - return m_rootVarName; - } - - void setSystemVarPrefix(std::string prefix) - { - m_systemVarPrefix = prefix; - } - std::string getSystemVarPrefix() { return m_systemVarPrefix; } - - void setDllRelativeDir(const TFilePath &dllRelativeDir) - { - delete m_dllRelativeDir; - m_dllRelativeDir = new TFilePath(dllRelativeDir); - } - - TFilePath getDllRelativeDir() - { - if (m_dllRelativeDir) - return *m_dllRelativeDir; - return TFilePath("."); - } + m_systemVarPrefix = m_applicationName; + updateEnvFile(); + } + + std::string getApplicationName() { return m_applicationName; } + std::string getApplicationVersion() { return m_applicationVersion; } + std::string getApplicationVersionWithoutRevision() { + return m_applicationVersionWithoutRevision; + } + + TFilePath getEnvFile() { return m_envFile; } + + void setApplicationFullName(std::string applicationFullName) { + m_applicationFullName = applicationFullName; + } + std::string getApplicationFullName() { return m_applicationFullName; } + + void setModuleName(std::string moduleName) { m_moduleName = moduleName; } + std::string getModuleName() { return m_moduleName; } + + void setRootVarName(std::string varName) { + m_rootVarName = varName; + updateEnvFile(); + } + std::string getRootVarName() { return m_rootVarName; } + + void setSystemVarPrefix(std::string prefix) { m_systemVarPrefix = prefix; } + std::string getSystemVarPrefix() { return m_systemVarPrefix; } + + void setDllRelativeDir(const TFilePath &dllRelativeDir) { + delete m_dllRelativeDir; + m_dllRelativeDir = new TFilePath(dllRelativeDir); + } + + TFilePath getDllRelativeDir() { + if (m_dllRelativeDir) return *m_dllRelativeDir; + return TFilePath("."); + } }; /* @@ -217,10 +204,10 @@ TFilePath EnvGlobals::getSystemPath(int id) if(it != m_systemPaths.end()) return it->second; switch(id) { - case StuffDir: return TFilePath(); + case StuffDir: return TFilePath(); case ConfigDir: return getSystemPath(StuffDir) + "config"; case ProfilesDir: return getSystemPath(StuffDir) + "profiles"; - default: return TFilePath(); + default: return TFilePath(); } } @@ -230,7 +217,7 @@ void EnvGlobals::setSystemPath(int id, const TFilePath &fp) } */ -} // namespace +} // namespace //========================================================= // @@ -238,15 +225,18 @@ void EnvGlobals::setSystemPath(int id, const TFilePath &fp) // //========================================================= -class Variable::Imp -{ +class Variable::Imp { public: - std::string m_name; - std::string m_value; - bool m_loaded, m_defaultDefined, m_assigned; - - Imp(std::string name) - : m_name(name), m_value(""), m_loaded(false), m_defaultDefined(false), m_assigned(false) {} + std::string m_name; + std::string m_value; + bool m_loaded, m_defaultDefined, m_assigned; + + Imp(std::string name) + : m_name(name) + , m_value("") + , m_loaded(false) + , m_defaultDefined(false) + , m_assigned(false) {} }; //========================================================= @@ -255,318 +245,272 @@ public: // //========================================================= -namespace -{ - -class VariableSet -{ +namespace { - std::map m_variables; - bool m_loaded; +class VariableSet { + std::map m_variables; + bool m_loaded; public: - VariableSet() : m_loaded(false) {} - - ~VariableSet() - { - std::map::iterator it; - for (it = m_variables.begin(); it != m_variables.end(); ++it) - delete it->second; - } - - static VariableSet *instance() - { - static VariableSet instance; - return &instance; - } - - Variable::Imp *getImp(std::string name) - { - std::map::iterator it; - it = m_variables.find(name); - if (it == m_variables.end()) { - Variable::Imp *imp = new Variable::Imp(name); - m_variables[name] = imp; - return imp; - } else - return it->second; - } - - void commit() - { - //save(); - } - - void loadIfNeeded() - { - if (m_loaded) - return; - m_loaded = true; - try { - load(); - } catch (...) { - } - } - - void load(); - void save(); + VariableSet() : m_loaded(false) {} + + ~VariableSet() { + std::map::iterator it; + for (it = m_variables.begin(); it != m_variables.end(); ++it) + delete it->second; + } + + static VariableSet *instance() { + static VariableSet instance; + return &instance; + } + + Variable::Imp *getImp(std::string name) { + std::map::iterator it; + it = m_variables.find(name); + if (it == m_variables.end()) { + Variable::Imp *imp = new Variable::Imp(name); + m_variables[name] = imp; + return imp; + } else + return it->second; + } + + void commit() { + // save(); + } + + void loadIfNeeded() { + if (m_loaded) return; + m_loaded = true; + try { + load(); + } catch (...) { + } + } + + void load(); + void save(); }; //------------------------------------------------------------------- -void VariableSet::load() -{ +void VariableSet::load() { #ifndef WIN32 - EnvGlobals::instance()->updateEnvFile(); + EnvGlobals::instance()->updateEnvFile(); #endif - TFilePath fp = EnvGlobals::instance()->getEnvFile(); - if (fp == TFilePath()) - return; - Tifstream is(fp); - if (!is) - return; - char buffer[1024]; - while (is.getline(buffer, sizeof(buffer))) { - char *s = buffer; - while (*s == ' ') - s++; - char *t = s; - while ('a' <= *s && *s <= 'z' || 'A' <= *s && *s <= 'Z' || '0' <= *s && *s <= '9' || *s == '_') - s++; - std::string name(t, s - t); - if (name.size() == 0) - continue; - while (*s == ' ') - s++; - if (*s != '\"') - continue; - s++; - std::string value; - while (*s != '\n' && *s != '\0' && *s != '\"') { - if (*s != '\\') - value.push_back(*s); - else { - s++; - if (*s == '\\') - value.push_back('\\'); - else if (*s == '"') - value.push_back('"'); - else if (*s == 'n') - value.push_back('\n'); - else - continue; - } - s++; - } - Variable::Imp *imp = getImp(name); - imp->m_value = value; - imp->m_loaded = true; - } + TFilePath fp = EnvGlobals::instance()->getEnvFile(); + if (fp == TFilePath()) return; + Tifstream is(fp); + if (!is) return; + char buffer[1024]; + while (is.getline(buffer, sizeof(buffer))) { + char *s = buffer; + while (*s == ' ') s++; + char *t = s; + while ('a' <= *s && *s <= 'z' || 'A' <= *s && *s <= 'Z' || + '0' <= *s && *s <= '9' || *s == '_') + s++; + std::string name(t, s - t); + if (name.size() == 0) continue; + while (*s == ' ') s++; + if (*s != '\"') continue; + s++; + std::string value; + while (*s != '\n' && *s != '\0' && *s != '\"') { + if (*s != '\\') + value.push_back(*s); + else { + s++; + if (*s == '\\') + value.push_back('\\'); + else if (*s == '"') + value.push_back('"'); + else if (*s == 'n') + value.push_back('\n'); + else + continue; + } + s++; + } + Variable::Imp *imp = getImp(name); + imp->m_value = value; + imp->m_loaded = true; + } } //------------------------------------------------------------------- -void VariableSet::save() -{ - TFilePath fp = EnvGlobals::instance()->getEnvFile(); - if (fp == TFilePath()) - return; - bool exists = TFileStatus(fp.getParentDir()).doesExist(); - if (!exists) { - try { - TSystem::mkDir(fp.getParentDir()); - } catch (...) { - return; - } - } - Tofstream os(fp); - if (!os) - return; - std::map::iterator it; - for (it = m_variables.begin(); it != m_variables.end(); ++it) { - os << it->first << " \""; - std::string s = it->second->m_value; - for (int i = 0; i < (int)s.size(); i++) - if (s[i] == '\"') - os << "\\\""; - else if (s[i] == '\\') - os << "\\\\"; - else if (s[i] == '\n') - os << "\\n"; - else - os.put(s[i]); - os << "\"" << std::endl; - } +void VariableSet::save() { + TFilePath fp = EnvGlobals::instance()->getEnvFile(); + if (fp == TFilePath()) return; + bool exists = TFileStatus(fp.getParentDir()).doesExist(); + if (!exists) { + try { + TSystem::mkDir(fp.getParentDir()); + } catch (...) { + return; + } + } + Tofstream os(fp); + if (!os) return; + std::map::iterator it; + for (it = m_variables.begin(); it != m_variables.end(); ++it) { + os << it->first << " \""; + std::string s = it->second->m_value; + for (int i = 0; i < (int)s.size(); i++) + if (s[i] == '\"') + os << "\\\""; + else if (s[i] == '\\') + os << "\\\\"; + else if (s[i] == '\n') + os << "\\n"; + else + os.put(s[i]); + os << "\"" << std::endl; + } } //------------------------------------------------------------------- -} // namespace +} // namespace //========================================================= Variable::Variable(std::string name) - : m_imp(VariableSet::instance()->getImp(name)) -{ -} + : m_imp(VariableSet::instance()->getImp(name)) {} //------------------------------------------------------------------- Variable::Variable(std::string name, std::string defaultValue) - : m_imp(VariableSet::instance()->getImp(name)) -{ - //assert(!m_imp->m_defaultDefined); - m_imp->m_defaultDefined = true; - if (!m_imp->m_loaded) - m_imp->m_value = defaultValue; + : m_imp(VariableSet::instance()->getImp(name)) { + // assert(!m_imp->m_defaultDefined); + m_imp->m_defaultDefined = true; + if (!m_imp->m_loaded) m_imp->m_value = defaultValue; } //------------------------------------------------------------------- -Variable::~Variable() -{ -} +Variable::~Variable() {} //------------------------------------------------------------------- -std::string Variable::getName() const -{ - return m_imp->m_name; -} +std::string Variable::getName() const { return m_imp->m_name; } //------------------------------------------------------------------- -std::string Variable::getValue() const -{ - VariableSet::instance()->loadIfNeeded(); - return m_imp->m_value; +std::string Variable::getValue() const { + VariableSet::instance()->loadIfNeeded(); + return m_imp->m_value; } //------------------------------------------------------------------- -void Variable::assignValue(std::string value) -{ - VariableSet *vs = VariableSet::instance(); - vs->loadIfNeeded(); - m_imp->m_value = value; - try { - vs->commit(); - } catch (...) { - } +void Variable::assignValue(std::string value) { + VariableSet *vs = VariableSet::instance(); + vs->loadIfNeeded(); + m_imp->m_value = value; + try { + vs->commit(); + } catch (...) { + } } //=================================================================== -void TEnv::setApplication(std::string applicationName, std::string applicationVersion, std::string revision) -{ - EnvGlobals::instance()->setApplication(applicationName, applicationVersion, revision); +void TEnv::setApplication(std::string applicationName, + std::string applicationVersion, + std::string revision) { + EnvGlobals::instance()->setApplication(applicationName, applicationVersion, + revision); #ifdef LEVO_MACOSX - TOfflineGL::defineImpGenerator(MacOfflineGenerator1); + TOfflineGL::defineImpGenerator(MacOfflineGenerator1); #endif } -std::string TEnv::getApplicationName() -{ - return EnvGlobals::instance()->getApplicationName(); +std::string TEnv::getApplicationName() { + return EnvGlobals::instance()->getApplicationName(); } -std::string TEnv::getApplicationVersion() -{ - return EnvGlobals::instance()->getApplicationVersion(); +std::string TEnv::getApplicationVersion() { + return EnvGlobals::instance()->getApplicationVersion(); } -void TEnv::setApplicationFullName(std::string applicationFullName) -{ - EnvGlobals::instance()->setApplicationFullName(applicationFullName); +void TEnv::setApplicationFullName(std::string applicationFullName) { + EnvGlobals::instance()->setApplicationFullName(applicationFullName); } -std::string TEnv::getApplicationFullName() -{ - return EnvGlobals::instance()->getApplicationFullName(); +std::string TEnv::getApplicationFullName() { + return EnvGlobals::instance()->getApplicationFullName(); } -void TEnv::setModuleName(std::string moduleName) -{ - EnvGlobals::instance()->setModuleName(moduleName); +void TEnv::setModuleName(std::string moduleName) { + EnvGlobals::instance()->setModuleName(moduleName); } -std::string TEnv::getModuleName() -{ - return EnvGlobals::instance()->getModuleName(); +std::string TEnv::getModuleName() { + return EnvGlobals::instance()->getModuleName(); } -void TEnv::setRootVarName(std::string varName) -{ - EnvGlobals::instance()->setRootVarName(varName); +void TEnv::setRootVarName(std::string varName) { + EnvGlobals::instance()->setRootVarName(varName); } -std::string TEnv::getRootVarName() -{ - return EnvGlobals::instance()->getRootVarName(); +std::string TEnv::getRootVarName() { + return EnvGlobals::instance()->getRootVarName(); } -TFilePath TEnv::getRootVarPath() -{ - return EnvGlobals::instance()->getRootVarPath(); +TFilePath TEnv::getRootVarPath() { + return EnvGlobals::instance()->getRootVarPath(); } -std::string TEnv::getSystemVarStringValue(std::string varName) -{ - return EnvGlobals::instance()->getSystemVarValue(varName); +std::string TEnv::getSystemVarStringValue(std::string varName) { + return EnvGlobals::instance()->getSystemVarValue(varName); } -TFilePath TEnv::getSystemVarPathValue(std::string varName) -{ - EnvGlobals *eg = EnvGlobals::instance(); - return TFilePath(eg->getSystemVarValue(varName)); +TFilePath TEnv::getSystemVarPathValue(std::string varName) { + EnvGlobals *eg = EnvGlobals::instance(); + return TFilePath(eg->getSystemVarValue(varName)); } -TFilePathSet TEnv::getSystemVarPathSetValue(std::string varName) -{ - TFilePathSet lst; - std::string value = EnvGlobals::instance()->getSystemVarValue(varName); - int len = (int)value.size(); - int i = 0; - int j = value.find(';'); - while (j != std::string::npos) { - std::string s = value.substr(i, j - i); - lst.push_back(TFilePath(s)); - i = j + 1; - if (i >= len) - return lst; - j = value.find(';', i); - } - if (i < len) - lst.push_back(TFilePath(value.substr(i))); - return lst; -} - -void TEnv::setSystemVarPrefix(std::string varName) -{ - EnvGlobals::instance()->setSystemVarPrefix(varName); +TFilePathSet TEnv::getSystemVarPathSetValue(std::string varName) { + TFilePathSet lst; + std::string value = EnvGlobals::instance()->getSystemVarValue(varName); + int len = (int)value.size(); + int i = 0; + int j = value.find(';'); + while (j != std::string::npos) { + std::string s = value.substr(i, j - i); + lst.push_back(TFilePath(s)); + i = j + 1; + if (i >= len) return lst; + j = value.find(';', i); + } + if (i < len) lst.push_back(TFilePath(value.substr(i))); + return lst; } -std::string TEnv::getSystemVarPrefix() -{ - return EnvGlobals::instance()->getSystemVarPrefix(); +void TEnv::setSystemVarPrefix(std::string varName) { + EnvGlobals::instance()->setSystemVarPrefix(varName); } -TFilePath TEnv::getStuffDir() -{ - //#ifdef MACOSX - //return TFilePath("/Applications/Toonz 5.0/Toonz 5.0 stuff"); - //#else - return EnvGlobals::instance()->getStuffDir(); - //#endif +std::string TEnv::getSystemVarPrefix() { + return EnvGlobals::instance()->getSystemVarPrefix(); } -TFilePath TEnv::getConfigDir() -{ - TFilePath configDir = getSystemVarPathValue(getSystemVarPrefix() + "CONFIG"); - if (configDir == TFilePath()) - configDir = getStuffDir() + "config"; - return configDir; +TFilePath TEnv::getStuffDir() { + //#ifdef MACOSX + // return TFilePath("/Applications/Toonz 5.0/Toonz 5.0 stuff"); + //#else + return EnvGlobals::instance()->getStuffDir(); + //#endif +} + +TFilePath TEnv::getConfigDir() { + TFilePath configDir = getSystemVarPathValue(getSystemVarPrefix() + "CONFIG"); + if (configDir == TFilePath()) configDir = getStuffDir() + "config"; + return configDir; } /*TFilePath TEnv::getProfilesDir() @@ -575,25 +519,19 @@ TFilePath TEnv::getConfigDir() return fp != TFilePath() ? fp + "profiles" : fp; } */ -void TEnv::setStuffDir(const TFilePath &stuffDir) -{ - EnvGlobals::instance()->setStuffDir(stuffDir); +void TEnv::setStuffDir(const TFilePath &stuffDir) { + EnvGlobals::instance()->setStuffDir(stuffDir); } -TFilePath TEnv::getDllRelativeDir() -{ - return EnvGlobals::instance()->getDllRelativeDir(); +TFilePath TEnv::getDllRelativeDir() { + return EnvGlobals::instance()->getDllRelativeDir(); } -void TEnv::setDllRelativeDir(const TFilePath &dllRelativeDir) -{ - EnvGlobals::instance()->setDllRelativeDir(dllRelativeDir); +void TEnv::setDllRelativeDir(const TFilePath &dllRelativeDir) { + EnvGlobals::instance()->setDllRelativeDir(dllRelativeDir); } -void TEnv::saveAllEnvVariables() -{ - VariableSet::instance()->save(); -} +void TEnv::saveAllEnvVariables() { VariableSet::instance()->save(); } /* void TEnv::defineSystemPath(SystemFileId id, const TFilePath ®istryName) @@ -618,114 +556,101 @@ TFilePath TEnv::getSystemPath(SystemFileId id) // //========================================================= -namespace -{ +namespace { -std::istream &operator>>(std::istream &is, TFilePath &path) -{ - std::string s; - is >> s; - return is; +std::istream &operator>>(std::istream &is, TFilePath &path) { + std::string s; + is >> s; + return is; } -std::istream &operator>>(std::istream &is, TRect &rect) -{ - return is >> rect.x0 >> rect.y0 >> rect.x1 >> rect.y1; +std::istream &operator>>(std::istream &is, TRect &rect) { + return is >> rect.x0 >> rect.y0 >> rect.x1 >> rect.y1; } template -std::string toString2(T value) -{ - std::ostrstream ss; - ss << value << '\0'; - std::string s(ss.str()); - ss.freeze(false); - return s; +std::string toString2(T value) { + std::ostringstream ss; + ss << value << '\0'; + return ss.str(); } template <> -std::string toString2(TRect value) -{ - std::ostrstream ss; - ss << value.x0 << " " << value.y0 << " " << value.x1 << " " << value.y1 << '\0'; - std::string s = ss.str(); - ss.freeze(false); - return s; +std::string toString2(TRect value) { + std::ostringstream ss; + ss << value.x0 << " " << value.y0 << " " << value.x1 << " " << value.y1 + << '\0'; + return ss.str(); } template -void fromString(std::string s, T &value) -{ - if (s.empty()) - return; - std::istrstream is(s.c_str(), s.size()); - is >> value; +void fromString(std::string s, T &value) { + if (s.empty()) return; + std::istringstream is(s); + is >> value; } -void fromString(std::string s, std::string &value) -{ - value = s; -} +void fromString(std::string s, std::string &value) { value = s; } -} // namespace +} // namespace //------------------------------------------------------------------- -IntVar::IntVar(std::string name, int defValue) : Variable(name, std::to_string(defValue)) {} +IntVar::IntVar(std::string name, int defValue) + : Variable(name, std::to_string(defValue)) {} IntVar::IntVar(std::string name) : Variable(name) {} -IntVar::operator int() const -{ - int v; - fromString(getValue(), v); - return v; +IntVar::operator int() const { + int v; + fromString(getValue(), v); + return v; } void IntVar::operator=(int v) { assignValue(std::to_string(v)); } //------------------------------------------------------------------- -DoubleVar::DoubleVar(std::string name, double defValue) : Variable(name, std::to_string(defValue)) {} +DoubleVar::DoubleVar(std::string name, double defValue) + : Variable(name, std::to_string(defValue)) {} DoubleVar::DoubleVar(std::string name) : Variable(name) {} -DoubleVar::operator double() const -{ - double v; - fromString(getValue(), v); - return v; +DoubleVar::operator double() const { + double v; + fromString(getValue(), v); + return v; } void DoubleVar::operator=(double v) { assignValue(std::to_string(v)); } //------------------------------------------------------------------- -StringVar::StringVar(std::string name, const std::string &defValue) : Variable(name, defValue) {} +StringVar::StringVar(std::string name, const std::string &defValue) + : Variable(name, defValue) {} StringVar::StringVar(std::string name) : Variable(name) {} -StringVar::operator std::string() const -{ - std::string v; - fromString(getValue(), v); - return v; +StringVar::operator std::string() const { + std::string v; + fromString(getValue(), v); + return v; } void StringVar::operator=(const std::string &v) { assignValue(v); } //------------------------------------------------------------------- -FilePathVar::FilePathVar(std::string name, const TFilePath &defValue) : Variable(name, ::to_string(defValue)) {} +FilePathVar::FilePathVar(std::string name, const TFilePath &defValue) + : Variable(name, ::to_string(defValue)) {} FilePathVar::FilePathVar(std::string name) : Variable(name) {} -FilePathVar::operator TFilePath() const -{ - std::string v; - fromString(getValue(), v); - return TFilePath(v); +FilePathVar::operator TFilePath() const { + std::string v; + fromString(getValue(), v); + return TFilePath(v); } void FilePathVar::operator=(const TFilePath &v) { assignValue(::to_string(v)); } //------------------------------------------------------------------- -RectVar::RectVar(std::string name, const TRect &defValue) : Variable(name, toString2(defValue)) {} +RectVar::RectVar(std::string name, const TRect &defValue) + : Variable(name, toString2(defValue)) {} RectVar::RectVar(std::string name) : Variable(name) {} -RectVar::operator TRect() const -{ - TRect v; - fromString(getValue(), v); - return v; +RectVar::operator TRect() const { + TRect v; + fromString(getValue(), v); + return v; } void RectVar::operator=(const TRect &v) { assignValue(toString2(v)); } diff --git a/toonz/sources/common/tapptools/tparamundo.cpp b/toonz/sources/common/tapptools/tparamundo.cpp index 2825122..1609d85 100644 --- a/toonz/sources/common/tapptools/tparamundo.cpp +++ b/toonz/sources/common/tapptools/tparamundo.cpp @@ -4,30 +4,27 @@ //#include "tparam.h" #include "tundo.h" -class ParamUndoManager : public TParamUndoManager -{ +class ParamUndoManager : public TParamUndoManager { public: - ParamUndoManager() {} - ~ParamUndoManager() {} - void onChange(const TParamChange &change); + ParamUndoManager() {} + ~ParamUndoManager() {} + void onChange(const TParamChange &change); }; //------------------------------------------------------------------- -TParamUndoManager *TParamUndoManager::instance() -{ - static ParamUndoManager instance; - return &instance; +TParamUndoManager *TParamUndoManager::instance() { + static ParamUndoManager instance; + return &instance; } //------------------------------------------------------------------- -void ParamUndoManager::onChange(const TParamChange &change) -{ - assert(0); +void ParamUndoManager::onChange(const TParamChange &change) { + assert(0); - //if (!change.m_undoing && !change.m_dragging) - // TUndoManager::manager()->add(change.createUndo()); + // if (!change.m_undoing && !change.m_dragging) + // TUndoManager::manager()->add(change.createUndo()); } //------------------------------------------------------------------- diff --git a/toonz/sources/common/tapptools/ttimer.cpp b/toonz/sources/common/tapptools/ttimer.cpp index 974edc9..de91626 100644 --- a/toonz/sources/common/tapptools/ttimer.cpp +++ b/toonz/sources/common/tapptools/ttimer.cpp @@ -10,123 +10,116 @@ #include #include -//moto strano: se togliamo l'include della glut non linka +// moto strano: se togliamo l'include della glut non linka #include //------------------------------------------------------------------------------ -namespace -{ +namespace { -void CALLBACK ElapsedTimeCB(UINT uID, UINT uMsg, - DWORD dwUser, DWORD dw1, - DWORD dw2); +void CALLBACK ElapsedTimeCB(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, + DWORD dw2); }; //------------------------------------------------------------------------------ -class TTimer::Imp -{ +class TTimer::Imp { public: - Imp(std::string name, UINT timerRes, TTimer::Type type, TTimer *timer); - ~Imp(); + Imp(std::string name, UINT timerRes, TTimer::Type type, TTimer *timer); + ~Imp(); - void start(UINT delay) - { - if (m_started) - throw TException("The timer is already started"); + void start(UINT delay) { + if (m_started) throw TException("The timer is already started"); - m_timerID = timeSetEvent(delay, m_timerRes, - (LPTIMECALLBACK)ElapsedTimeCB, (DWORD) this, - m_type | TIME_CALLBACK_FUNCTION); + m_timerID = timeSetEvent(delay, m_timerRes, (LPTIMECALLBACK)ElapsedTimeCB, + (DWORD)this, m_type | TIME_CALLBACK_FUNCTION); - m_delay = delay; - m_ticks = 0; - if (m_timerID == NULL) - throw TException("Unable to start timer"); + m_delay = delay; + m_ticks = 0; + if (m_timerID == NULL) throw TException("Unable to start timer"); - m_started = true; - } + m_started = true; + } - void stop() - { - if (m_started) - timeKillEvent(m_timerID); - m_started = false; - } + void stop() { + if (m_started) timeKillEvent(m_timerID); + m_started = false; + } - std::string getName() { return m_name; } - TUINT64 getTicks() { return m_ticks; } - UINT getDelay() { return m_delay; } + std::string getName() { return m_name; } + TUINT64 getTicks() { return m_ticks; } + UINT getDelay() { return m_delay; } - std::string m_name; + std::string m_name; - UINT m_timerRes; - UINT m_type; - TTimer *m_timer; + UINT m_timerRes; + UINT m_type; + TTimer *m_timer; - UINT m_timerID; - UINT m_delay; - TUINT64 m_ticks; - bool m_started; + UINT m_timerID; + UINT m_delay; + TUINT64 m_ticks; + bool m_started; - TGenericTimerAction *m_action; + TGenericTimerAction *m_action; }; //------------------------------------------------------------------------------ -TTimer::Imp::Imp(std::string name, UINT timerRes, TTimer::Type type, TTimer *timer) - : m_name(name), m_timerRes(timerRes), m_timer(timer), m_type(type), m_timerID(NULL), m_ticks(0), m_delay(0), m_started(false), m_action(0) -{ - - TIMECAPS tc; - - if (timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) { - throw TException("Unable to create timer"); - } - - m_timerRes = std::min((int)std::max((int)tc.wPeriodMin, (int)m_timerRes), (int)tc.wPeriodMax); - timeBeginPeriod(m_timerRes); - - switch (type) { - case TTimer::OneShot: - m_type = TIME_ONESHOT; - break; - - case TTimer::Periodic: - m_type = TIME_PERIODIC; - break; - - default: - throw TException("Unexpected timer type"); - break; - } +TTimer::Imp::Imp(std::string name, UINT timerRes, TTimer::Type type, + TTimer *timer) + : m_name(name) + , m_timerRes(timerRes) + , m_timer(timer) + , m_type(type) + , m_timerID(NULL) + , m_ticks(0) + , m_delay(0) + , m_started(false) + , m_action(0) { + TIMECAPS tc; + + if (timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) { + throw TException("Unable to create timer"); + } + + m_timerRes = std::min((int)std::max((int)tc.wPeriodMin, (int)m_timerRes), + (int)tc.wPeriodMax); + timeBeginPeriod(m_timerRes); + + switch (type) { + case TTimer::OneShot: + m_type = TIME_ONESHOT; + break; + + case TTimer::Periodic: + m_type = TIME_PERIODIC; + break; + + default: + throw TException("Unexpected timer type"); + break; + } } //------------------------------------------------------------------------------ -TTimer::Imp::~Imp() -{ - stop(); - timeEndPeriod(m_timerRes); +TTimer::Imp::~Imp() { + stop(); + timeEndPeriod(m_timerRes); - if (m_action) - delete m_action; + if (m_action) delete m_action; } //------------------------------------------------------------------------------ -namespace -{ - -void CALLBACK ElapsedTimeCB(UINT uID, UINT uMsg, - DWORD dwUser, DWORD dw1, - DWORD dw2) -{ - TTimer::Imp *imp = reinterpret_cast(dwUser); - imp->m_ticks++; - if (imp->m_action) - imp->m_action->sendCommand(imp->m_ticks); +namespace { + +void CALLBACK ElapsedTimeCB(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, + DWORD dw2) { + TTimer::Imp *imp = reinterpret_cast(dwUser); + imp->m_ticks++; + if (imp->m_action) imp->m_action->sendCommand(imp->m_ticks); } }; #elif LINUX @@ -134,156 +127,129 @@ void CALLBACK ElapsedTimeCB(UINT uID, UINT uMsg, #include #include #include "tthread.h" -namespace -{ +namespace { Uint32 ElapsedTimeCB(Uint32 interval, void *param); } -class TTimer::Imp -{ +class TTimer::Imp { public: - Imp(std::string name, UINT timerRes, TTimer::Type type, TTimer *timer) - : m_action(0), m_ticks(0) - { - } - ~Imp() {} - - void start(UINT delay) - { - static bool first = true; - if (first) { - SDL_Init(SDL_INIT_TIMER); - first = false; - } - m_timerID = SDL_AddTimer(delay, ElapsedTimeCB, this); - } - - void stop() - { - SDL_RemoveTimer(m_timerID); - } - - std::string getName() { return m_name; } - TUINT64 getTicks() { return m_ticks; } - UINT getDelay() { return m_delay; } - - std::string m_name; - - UINT m_timerRes; - UINT m_type; - TTimer *m_timer; - - SDL_TimerID m_timerID; - UINT m_delay; - TUINT64 m_ticks; - bool m_started; - - TGenericTimerAction *m_action; + Imp(std::string name, UINT timerRes, TTimer::Type type, TTimer *timer) + : m_action(0), m_ticks(0) {} + ~Imp() {} + + void start(UINT delay) { + static bool first = true; + if (first) { + SDL_Init(SDL_INIT_TIMER); + first = false; + } + m_timerID = SDL_AddTimer(delay, ElapsedTimeCB, this); + } + + void stop() { SDL_RemoveTimer(m_timerID); } + + std::string getName() { return m_name; } + TUINT64 getTicks() { return m_ticks; } + UINT getDelay() { return m_delay; } + + std::string m_name; + + UINT m_timerRes; + UINT m_type; + TTimer *m_timer; + + SDL_TimerID m_timerID; + UINT m_delay; + TUINT64 m_ticks; + bool m_started; + + TGenericTimerAction *m_action; }; -class SendCommandMSG : public TThread::Message -{ - TTimer::Imp *m_ztimp; +class SendCommandMSG : public TThread::Message { + TTimer::Imp *m_ztimp; public: - SendCommandMSG(TTimer::Imp *ztimp) : TThread::Message(), m_ztimp(ztimp) - { - } - ~SendCommandMSG() {} - TThread::Message *clone() const { return new SendCommandMSG(*this); } - void onDeliver() - { - if (m_ztimp->m_action) - m_ztimp->m_action->sendCommand(m_ztimp->m_ticks); - } + SendCommandMSG(TTimer::Imp *ztimp) : TThread::Message(), m_ztimp(ztimp) {} + ~SendCommandMSG() {} + TThread::Message *clone() const { return new SendCommandMSG(*this); } + void onDeliver() { + if (m_ztimp->m_action) m_ztimp->m_action->sendCommand(m_ztimp->m_ticks); + } }; -namespace -{ -Uint32 ElapsedTimeCB(Uint32 interval, void *param) -{ - TTimer::Imp *imp = reinterpret_cast(param); - imp->m_ticks++; - SendCommandMSG(imp).send(); - return interval; +namespace { +Uint32 ElapsedTimeCB(Uint32 interval, void *param) { + TTimer::Imp *imp = reinterpret_cast(param); + imp->m_ticks++; + SendCommandMSG(imp).send(); + return interval; } } #elif __sgi -class TTimer::Imp -{ +class TTimer::Imp { public: - Imp(std::string name, UINT timerRes, TTimer::Type type, TTimer *timer) - : m_action(0) {} - ~Imp() {} + Imp(std::string name, UINT timerRes, TTimer::Type type, TTimer *timer) + : m_action(0) {} + ~Imp() {} - void start(UINT delay) - { - if (m_started) - throw TException("The timer is already started"); + void start(UINT delay) { + if (m_started) throw TException("The timer is already started"); - m_started = true; - } + m_started = true; + } - void stop() - { - m_started = false; - } + void stop() { m_started = false; } - std::string getName() { return m_name; } - TUINT64 getTicks() { return m_ticks; } - UINT getDelay() { return m_delay; } + std::string getName() { return m_name; } + TUINT64 getTicks() { return m_ticks; } + UINT getDelay() { return m_delay; } - std::string m_name; + std::string m_name; - UINT m_timerRes; - UINT m_type; - TTimer *m_timer; + UINT m_timerRes; + UINT m_type; + TTimer *m_timer; - UINT m_timerID; - UINT m_delay; - TUINT64 m_ticks; - bool m_started; + UINT m_timerID; + UINT m_delay; + TUINT64 m_ticks; + bool m_started; - TGenericTimerAction *m_action; + TGenericTimerAction *m_action; }; #elif MACOSX -class TTimer::Imp -{ +class TTimer::Imp { public: - Imp(std::string name, UINT timerRes, TTimer::Type type, TTimer *timer) - : m_action(0) {} - ~Imp() {} - - void start(UINT delay) - { - if (m_started) - throw TException("The timer is already started"); - throw TException("The timer is not yet available under MAC :("); - m_started = true; - } - - void stop() - { - m_started = false; - } - - std::string getName() { return m_name; } - TUINT64 getTicks() { return m_ticks; } - UINT getDelay() { return m_delay; } - - std::string m_name; - - UINT m_timerRes; - UINT m_type; - TTimer *m_timer; - - UINT m_timerID; - UINT m_delay; - TUINT64 m_ticks; - bool m_started; - - TGenericTimerAction *m_action; + Imp(std::string name, UINT timerRes, TTimer::Type type, TTimer *timer) + : m_action(0) {} + ~Imp() {} + + void start(UINT delay) { + if (m_started) throw TException("The timer is already started"); + throw TException("The timer is not yet available under MAC :("); + m_started = true; + } + + void stop() { m_started = false; } + + std::string getName() { return m_name; } + TUINT64 getTicks() { return m_ticks; } + UINT getDelay() { return m_delay; } + + std::string m_name; + + UINT m_timerRes; + UINT m_type; + TTimer *m_timer; + + UINT m_timerID; + UINT m_delay; + TUINT64 m_ticks; + bool m_started; + + TGenericTimerAction *m_action; }; #endif @@ -295,64 +261,40 @@ public: //=============================================================================== TTimer::TTimer(const std::string &name, UINT timerRes, Type type) - : m_imp(new TTimer::Imp(name, timerRes, type, this)) -{ -} + : m_imp(new TTimer::Imp(name, timerRes, type, this)) {} //-------------------------------------------------------------------------------- -TTimer::~TTimer() -{ -} +TTimer::~TTimer() {} //-------------------------------------------------------------------------------- -void TTimer::start(UINT delay) -{ - m_imp->start(delay); -} +void TTimer::start(UINT delay) { m_imp->start(delay); } //-------------------------------------------------------------------------------- -bool TTimer::isStarted() const -{ - return m_imp->m_started; -} +bool TTimer::isStarted() const { return m_imp->m_started; } //-------------------------------------------------------------------------------- -void TTimer::stop() -{ - m_imp->stop(); -} +void TTimer::stop() { m_imp->stop(); } //-------------------------------------------------------------------------------- -std::string TTimer::getName() const -{ - return m_imp->getName(); -} +std::string TTimer::getName() const { return m_imp->getName(); } //-------------------------------------------------------------------------------- -TUINT64 TTimer::getTicks() const -{ - return m_imp->getTicks(); -} +TUINT64 TTimer::getTicks() const { return m_imp->getTicks(); } //-------------------------------------------------------------------------------- -UINT TTimer::getDelay() const -{ - return m_imp->getDelay(); -} +UINT TTimer::getDelay() const { return m_imp->getDelay(); } //-------------------------------------------------------------------------------- -void TTimer::setAction(TGenericTimerAction *action) -{ - if (m_imp->m_action) - delete m_imp->m_action; +void TTimer::setAction(TGenericTimerAction *action) { + if (m_imp->m_action) delete m_imp->m_action; - m_imp->m_action = action; + m_imp->m_action = action; } diff --git a/toonz/sources/common/tcache/timagecache.cpp b/toonz/sources/common/tcache/timagecache.cpp index 2ea1403..33dc367 100644 --- a/toonz/sources/common/tcache/timagecache.cpp +++ b/toonz/sources/common/tcache/timagecache.cpp @@ -63,62 +63,61 @@ class ImageBuilder; class ImageInfo; -//std::ofstream os("C:\\cache.txt"); +// std::ofstream os("C:\\cache.txt"); TUINT32 HistoryCount = 0; //------------------------------------------------------------------------------ -class TheCodec : public TRasterCodecLz4 -{ +class TheCodec : public TRasterCodecLz4 { public: - static TheCodec *instance() - { - if (!_instance) - _instance = new TheCodec(); + static TheCodec *instance() { + if (!_instance) _instance = new TheCodec(); - return _instance; - } + return _instance; + } - void reset() - { - if (_instance) - _instance->TRasterCodecLz4::reset(); - } + void reset() { + if (_instance) _instance->TRasterCodecLz4::reset(); + } private: - static TheCodec *_instance; - TheCodec() : TRasterCodecLz4("Lz4_Codec", false) {} + static TheCodec *_instance; + TheCodec() : TRasterCodecLz4("Lz4_Codec", false) {} }; TheCodec *TheCodec::_instance = 0; //------------------------------------------------------------------------------ -class CacheItem : public TSmartObject -{ - DECLARE_CLASS_CODE +class CacheItem : public TSmartObject { + DECLARE_CLASS_CODE public: - CacheItem() - : m_cantCompress(false), m_builder(0), m_imageInfo(0), m_modified(false) {} - - CacheItem(ImageBuilder *builder, ImageInfo *imageInfo) - : m_cantCompress(false), m_builder(builder), m_imageInfo(imageInfo), m_historyCount(0), m_modified(false) - { - } - - virtual ~CacheItem() {} - - virtual TUINT32 getSize() const = 0; - - // getImage restituisce un'immagine non compressa - virtual TImageP getImage() const = 0; - - bool m_cantCompress; - ImageBuilder *m_builder; - ImageInfo *m_imageInfo; - std::string m_id; - TUINT32 m_historyCount; - bool m_modified; + CacheItem() + : m_cantCompress(false) + , m_builder(0) + , m_imageInfo(0) + , m_modified(false) {} + + CacheItem(ImageBuilder *builder, ImageInfo *imageInfo) + : m_cantCompress(false) + , m_builder(builder) + , m_imageInfo(imageInfo) + , m_historyCount(0) + , m_modified(false) {} + + virtual ~CacheItem() {} + + virtual TUINT32 getSize() const = 0; + + // getImage restituisce un'immagine non compressa + virtual TImageP getImage() const = 0; + + bool m_cantCompress; + ImageBuilder *m_builder; + ImageInfo *m_imageInfo; + std::string m_id; + TUINT32 m_historyCount; + bool m_modified; }; #ifdef _WIN32 @@ -131,72 +130,63 @@ DEFINE_CLASS_CODE(CacheItem, 101) //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ -class ImageInfo -{ - +class ImageInfo { public: - TDimension m_size; - ImageInfo(const TDimension &size) : m_size(size) {} - virtual ~ImageInfo() {} - virtual ImageInfo *clone() = 0; + TDimension m_size; + ImageInfo(const TDimension &size) : m_size(size) {} + virtual ~ImageInfo() {} + virtual ImageInfo *clone() = 0; }; //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ -class ImageBuilder -{ +class ImageBuilder { public: - virtual ~ImageBuilder() {} - virtual ImageBuilder *clone() = 0; - virtual TImageP build(ImageInfo *info, const TRasterP &ras) = 0; + virtual ~ImageBuilder() {} + virtual ImageBuilder *clone() = 0; + virtual TImageP build(ImageInfo *info, const TRasterP &ras) = 0; }; //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ -class RasterImageInfo : public ImageInfo -{ +class RasterImageInfo : public ImageInfo { public: - RasterImageInfo(const TRasterImageP &ri); + RasterImageInfo(const TRasterImageP &ri); - void setInfo(const TRasterImageP &ri); + void setInfo(const TRasterImageP &ri); - ImageInfo *clone(); + ImageInfo *clone(); - double m_dpix, m_dpiy; - std::string m_name; - TRect m_savebox; - bool m_isOpaque; - TPoint m_offset; - int m_subs; + double m_dpix, m_dpiy; + std::string m_name; + TRect m_savebox; + bool m_isOpaque; + TPoint m_offset; + int m_subs; }; RasterImageInfo::RasterImageInfo(const TRasterImageP &ri) - : ImageInfo(ri->getRaster()->getSize()) -{ - ri->getDpi(m_dpix, m_dpiy); - m_name = ri->getName(); - m_savebox = ri->getSavebox(); - m_isOpaque = ri->isOpaque(); - m_offset = ri->getOffset(); - m_subs = ri->getSubsampling(); + : ImageInfo(ri->getRaster()->getSize()) { + ri->getDpi(m_dpix, m_dpiy); + m_name = ri->getName(); + m_savebox = ri->getSavebox(); + m_isOpaque = ri->isOpaque(); + m_offset = ri->getOffset(); + m_subs = ri->getSubsampling(); } -void RasterImageInfo::setInfo(const TRasterImageP &ri) -{ - ri->setDpi(m_dpix, m_dpiy); - ri->setName(m_name); - ri->setSavebox(m_savebox); - ri->setOpaqueFlag(m_isOpaque); - ri->setOffset(m_offset); - ri->setSubsampling(m_subs); +void RasterImageInfo::setInfo(const TRasterImageP &ri) { + ri->setDpi(m_dpix, m_dpiy); + ri->setName(m_name); + ri->setSavebox(m_savebox); + ri->setOpaqueFlag(m_isOpaque); + ri->setOffset(m_offset); + ri->setSubsampling(m_subs); } -ImageInfo *RasterImageInfo::clone() -{ - return new RasterImageInfo(*this); -} +ImageInfo *RasterImageInfo::clone() { return new RasterImageInfo(*this); } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ @@ -205,52 +195,45 @@ ImageInfo *RasterImageInfo::clone() #include "tpalette.h" #include "ttoonzimage.h" -class ToonzImageInfo : public ImageInfo -{ +class ToonzImageInfo : public ImageInfo { public: - ToonzImageInfo(const TToonzImageP &ti); - ~ToonzImageInfo() - { - if (m_palette) - m_palette->release(); - } - - ImageInfo *clone() - { - ToonzImageInfo *ret = new ToonzImageInfo(*this); - if (ret->m_palette) - ret->m_palette->addRef(); - return ret; - } - - void setInfo(const TToonzImageP &ti); - - double m_dpix, m_dpiy; - std::string m_name; - TRect m_savebox; - TPoint m_offset; - int m_subs; - TPalette *m_palette; + ToonzImageInfo(const TToonzImageP &ti); + ~ToonzImageInfo() { + if (m_palette) m_palette->release(); + } + + ImageInfo *clone() { + ToonzImageInfo *ret = new ToonzImageInfo(*this); + if (ret->m_palette) ret->m_palette->addRef(); + return ret; + } + + void setInfo(const TToonzImageP &ti); + + double m_dpix, m_dpiy; + std::string m_name; + TRect m_savebox; + TPoint m_offset; + int m_subs; + TPalette *m_palette; }; -ToonzImageInfo::ToonzImageInfo(const TToonzImageP &ti) : ImageInfo(ti->getSize()) -{ - m_palette = ti->getPalette(); - if (m_palette) - m_palette->addRef(); - - ti->getDpi(m_dpix, m_dpiy); - m_savebox = ti->getSavebox(); - m_offset = ti->getOffset(); - m_subs = ti->getSubsampling(); +ToonzImageInfo::ToonzImageInfo(const TToonzImageP &ti) + : ImageInfo(ti->getSize()) { + m_palette = ti->getPalette(); + if (m_palette) m_palette->addRef(); + + ti->getDpi(m_dpix, m_dpiy); + m_savebox = ti->getSavebox(); + m_offset = ti->getOffset(); + m_subs = ti->getSubsampling(); } -void ToonzImageInfo::setInfo(const TToonzImageP &ti) -{ - ti->setPalette(m_palette); - ti->setDpi(m_dpix, m_dpiy); - ti->setOffset(m_offset); - ti->setSubsampling(m_subs); +void ToonzImageInfo::setInfo(const TToonzImageP &ti) { + ti->setPalette(m_palette); + ti->setDpi(m_dpix, m_dpiy); + ti->setOffset(m_offset); + ti->setSubsampling(m_subs); } #endif @@ -258,925 +241,897 @@ void ToonzImageInfo::setInfo(const TToonzImageP &ti) //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ -class RasterImageBuilder : public ImageBuilder -{ +class RasterImageBuilder : public ImageBuilder { public: - ImageBuilder *clone() - { - return new RasterImageBuilder(*this); - } + ImageBuilder *clone() { return new RasterImageBuilder(*this); } - TImageP build(ImageInfo *info, const TRasterP &ras); + TImageP build(ImageInfo *info, const TRasterP &ras); }; -TImageP RasterImageBuilder::build(ImageInfo *info, const TRasterP &ras) -{ - RasterImageInfo *riInfo = dynamic_cast(info); - assert(riInfo); +TImageP RasterImageBuilder::build(ImageInfo *info, const TRasterP &ras) { + RasterImageInfo *riInfo = dynamic_cast(info); + assert(riInfo); - int rcount = ras->getRefCount(); - TRasterImageP ri = new TRasterImage(); + int rcount = ras->getRefCount(); + TRasterImageP ri = new TRasterImage(); #ifdef _DEBUGTOONZ - ras->m_cashed = true; + ras->m_cashed = true; #endif - ri->setRaster(ras); - riInfo->setInfo(ri); - assert(ras->getRefCount() > rcount); - return ri; + ri->setRaster(ras); + riInfo->setInfo(ri); + assert(ras->getRefCount() > rcount); + return ri; } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ #ifndef TNZCORE_LIGHT -class ToonzImageBuilder : public ImageBuilder -{ +class ToonzImageBuilder : public ImageBuilder { public: - ImageBuilder *clone() - { - return new ToonzImageBuilder(*this); - } + ImageBuilder *clone() { return new ToonzImageBuilder(*this); } - TImageP build(ImageInfo *info, const TRasterP &ras); + TImageP build(ImageInfo *info, const TRasterP &ras); }; -TImageP ToonzImageBuilder::build(ImageInfo *info, const TRasterP &ras) -{ - ToonzImageInfo *tiInfo = dynamic_cast(info); - assert(tiInfo); - - TRasterCM32P rasCM32 = ras; - assert(rasCM32); - - TRasterCM32P imgRasCM32; - - assert(TRect(tiInfo->m_size).contains(tiInfo->m_savebox)); - - if (ras->getSize() != tiInfo->m_size) { - TRasterCM32P fullRas(tiInfo->m_size); - TRect rectToExtract(tiInfo->m_savebox); - TPixelCM32 bgColor; - fullRas->fillOutside(tiInfo->m_savebox, bgColor); - fullRas->extractT(rectToExtract)->copy(ras); - assert(rectToExtract == tiInfo->m_savebox); - imgRasCM32 = fullRas; - } else - imgRasCM32 = rasCM32; +TImageP ToonzImageBuilder::build(ImageInfo *info, const TRasterP &ras) { + ToonzImageInfo *tiInfo = dynamic_cast(info); + assert(tiInfo); + + TRasterCM32P rasCM32 = ras; + assert(rasCM32); + + TRasterCM32P imgRasCM32; + + assert(TRect(tiInfo->m_size).contains(tiInfo->m_savebox)); + + if (ras->getSize() != tiInfo->m_size) { + TRasterCM32P fullRas(tiInfo->m_size); + TRect rectToExtract(tiInfo->m_savebox); + TPixelCM32 bgColor; + fullRas->fillOutside(tiInfo->m_savebox, bgColor); + fullRas->extractT(rectToExtract)->copy(ras); + assert(rectToExtract == tiInfo->m_savebox); + imgRasCM32 = fullRas; + } else + imgRasCM32 = rasCM32; #ifdef _DEBUG - imgRasCM32->m_cashed = true; + imgRasCM32->m_cashed = true; #endif - TToonzImageP ti = new TToonzImage(imgRasCM32, tiInfo->m_savebox); - tiInfo->setInfo(ti); - return ti; + TToonzImageP ti = new TToonzImage(imgRasCM32, tiInfo->m_savebox); + tiInfo->setInfo(ti); + return ti; } #endif //------------------------------------------------------------------------------ -class UncompressedOnMemoryCacheItem : public CacheItem -{ +class UncompressedOnMemoryCacheItem : public CacheItem { public: - UncompressedOnMemoryCacheItem(const TImageP &image) : m_image(image) - { - TRasterImageP ri = m_image; + UncompressedOnMemoryCacheItem(const TImageP &image) : m_image(image) { + TRasterImageP ri = m_image; - if (ri) - m_imageInfo = new RasterImageInfo(ri); + if (ri) m_imageInfo = new RasterImageInfo(ri); #ifndef TNZCORE_LIGHT - else { - TToonzImageP ti = m_image; - if (ti) - m_imageInfo = new ToonzImageInfo(ti); - else - m_imageInfo = 0; - } + else { + TToonzImageP ti = m_image; + if (ti) + m_imageInfo = new ToonzImageInfo(ti); + else + m_imageInfo = 0; + } #else - else - m_imageInfo = 0; + else + m_imageInfo = 0; #endif - } + } - ~UncompressedOnMemoryCacheItem() - { - if (m_imageInfo) - delete m_imageInfo; - } + ~UncompressedOnMemoryCacheItem() { + if (m_imageInfo) delete m_imageInfo; + } - TUINT32 getSize() const; - TImageP getImage() const { return m_image; } + TUINT32 getSize() const; + TImageP getImage() const { return m_image; } - TImageP m_image; + TImageP m_image; }; #ifdef _WIN32 template class DVAPI TSmartPointerT; -template class DVAPI TDerivedSmartPointerT; +template class DVAPI + TDerivedSmartPointerT; #endif -typedef TDerivedSmartPointerT UncompressedOnMemoryCacheItemP; +typedef TDerivedSmartPointerT + UncompressedOnMemoryCacheItemP; //------------------------------------------------------------------------------ -TUINT32 UncompressedOnMemoryCacheItem::getSize() const -{ - TRasterImageP ri = m_image; - if (ri) { - TRasterP ras = ri->getRaster(); - if (ras) - return ras->getLy() * ras->getRowSize(); - else - return 0; - } else { +TUINT32 UncompressedOnMemoryCacheItem::getSize() const { + TRasterImageP ri = m_image; + if (ri) { + TRasterP ras = ri->getRaster(); + if (ras) + return ras->getLy() * ras->getRowSize(); + else + return 0; + } else { #ifndef TNZCORE_LIGHT - TToonzImageP ti = m_image; - if (ti) { - TDimension size = ti->getSize(); - return size.lx * size.ly * sizeof(TPixelCM32); - } + TToonzImageP ti = m_image; + if (ti) { + TDimension size = ti->getSize(); + return size.lx * size.ly * sizeof(TPixelCM32); + } #endif - } + } - return 0; + return 0; } //------------------------------------------------------------------------------ -class CompressedOnMemoryCacheItem : public CacheItem -{ +class CompressedOnMemoryCacheItem : public CacheItem { public: - CompressedOnMemoryCacheItem(const TImageP &img); + CompressedOnMemoryCacheItem(const TImageP &img); - CompressedOnMemoryCacheItem(const TRasterP &compressedRas, - ImageBuilder *builder, - ImageInfo *info); + CompressedOnMemoryCacheItem(const TRasterP &compressedRas, + ImageBuilder *builder, ImageInfo *info); - ~CompressedOnMemoryCacheItem(); + ~CompressedOnMemoryCacheItem(); - TUINT32 getSize() const; - TImageP getImage() const; + TUINT32 getSize() const; + TImageP getImage() const; - TRasterP m_compressedRas; + TRasterP m_compressedRas; }; #ifdef _WIN32 template class DVAPI TSmartPointerT; -template class DVAPI TDerivedSmartPointerT; +template class DVAPI + TDerivedSmartPointerT; #endif -typedef TDerivedSmartPointerT CompressedOnMemoryCacheItemP; +typedef TDerivedSmartPointerT + CompressedOnMemoryCacheItemP; //------------------------------------------------------------------------------ CompressedOnMemoryCacheItem::CompressedOnMemoryCacheItem(const TImageP &img) - : m_compressedRas() -{ - TRasterImageP ri = img; - if (ri) { - m_imageInfo = new RasterImageInfo(ri); - m_builder = new RasterImageBuilder(); - TINT32 buffSize = 0; - m_compressedRas = TheCodec::instance()->compress(ri->getRaster(), 1, buffSize); - } + : m_compressedRas() { + TRasterImageP ri = img; + if (ri) { + m_imageInfo = new RasterImageInfo(ri); + m_builder = new RasterImageBuilder(); + TINT32 buffSize = 0; + m_compressedRas = + TheCodec::instance()->compress(ri->getRaster(), 1, buffSize); + } #ifndef TNZCORE_LIGHT - else { - TToonzImageP ti = img; - if (ti) { - m_imageInfo = new ToonzImageInfo(ti); - m_builder = new ToonzImageBuilder(); - TRasterCM32P rasCM32 = ti->getRaster(); - TINT32 buffSize = 0; - m_compressedRas = TheCodec::instance()->compress(rasCM32, 1, buffSize); - } else - assert(false); - } + else { + TToonzImageP ti = img; + if (ti) { + m_imageInfo = new ToonzImageInfo(ti); + m_builder = new ToonzImageBuilder(); + TRasterCM32P rasCM32 = ti->getRaster(); + TINT32 buffSize = 0; + m_compressedRas = TheCodec::instance()->compress(rasCM32, 1, buffSize); + } else + assert(false); + } #else - else - assert(false); + else + assert(false); #endif } //------------------------------------------------------------------------------ CompressedOnMemoryCacheItem::CompressedOnMemoryCacheItem(const TRasterP &ras, - ImageBuilder *builder, - ImageInfo *info) - : CacheItem(builder, info), m_compressedRas(ras) -{ -} + ImageBuilder *builder, + ImageInfo *info) + : CacheItem(builder, info), m_compressedRas(ras) {} //------------------------------------------------------------------------------ -CompressedOnMemoryCacheItem::~CompressedOnMemoryCacheItem() -{ - delete m_imageInfo; +CompressedOnMemoryCacheItem::~CompressedOnMemoryCacheItem() { + delete m_imageInfo; } //------------------------------------------------------------------------------ -TUINT32 CompressedOnMemoryCacheItem::getSize() const -{ - if (m_compressedRas) - return m_compressedRas->getLx(); - else - return 0; +TUINT32 CompressedOnMemoryCacheItem::getSize() const { + if (m_compressedRas) + return m_compressedRas->getLx(); + else + return 0; } //------------------------------------------------------------------------------ -TImageP CompressedOnMemoryCacheItem::getImage() const -{ - assert(m_compressedRas); +TImageP CompressedOnMemoryCacheItem::getImage() const { + assert(m_compressedRas); - // PER IL MOMENTO DISCRIMINO: DA ELIMINARE - TRasterP ras; + // PER IL MOMENTO DISCRIMINO: DA ELIMINARE + TRasterP ras; - TheCodec::instance()->decompress(m_compressedRas, ras); + TheCodec::instance()->decompress(m_compressedRas, ras); #ifdef _DEBUGTOONZ - ras->m_cashed = true; + ras->m_cashed = true; #endif #ifndef TNZCORE_LIGHT - ToonzImageBuilder *tibuilder = dynamic_cast(m_builder); - if (tibuilder) - return tibuilder->build(m_imageInfo, ras); - else + ToonzImageBuilder *tibuilder = dynamic_cast(m_builder); + if (tibuilder) + return tibuilder->build(m_imageInfo, ras); + else #endif - return m_builder->build(m_imageInfo, ras); + return m_builder->build(m_imageInfo, ras); } //------------------------------------------------------------------------------ -class CompressedOnDiskCacheItem : public CacheItem -{ +class CompressedOnDiskCacheItem : public CacheItem { public: - CompressedOnDiskCacheItem(const TFilePath &fp, - const TRasterP &compressedRas, - ImageBuilder *builder, - ImageInfo *info); + CompressedOnDiskCacheItem(const TFilePath &fp, const TRasterP &compressedRas, + ImageBuilder *builder, ImageInfo *info); - ~CompressedOnDiskCacheItem(); + ~CompressedOnDiskCacheItem(); - TUINT32 getSize() const { return 0; } - TImageP getImage() const; - TFilePath m_fp; + TUINT32 getSize() const { return 0; } + TImageP getImage() const; + TFilePath m_fp; }; #ifdef _WIN32 template class DVAPI TSmartPointerT; -template class DVAPI TDerivedSmartPointerT; +template class DVAPI + TDerivedSmartPointerT; #endif -typedef TDerivedSmartPointerT CompressedOnDiskCacheItemP; +typedef TDerivedSmartPointerT + CompressedOnDiskCacheItemP; //------------------------------------------------------------------------------ -CompressedOnDiskCacheItem::CompressedOnDiskCacheItem(const TFilePath &fp, - const TRasterP &compressedRas, - ImageBuilder *builder, - ImageInfo *info) - : CacheItem(builder, info), m_fp(fp) -{ - compressedRas->lock(); +CompressedOnDiskCacheItem::CompressedOnDiskCacheItem( + const TFilePath &fp, const TRasterP &compressedRas, ImageBuilder *builder, + ImageInfo *info) + : CacheItem(builder, info), m_fp(fp) { + compressedRas->lock(); - Tofstream oss(m_fp); - assert(compressedRas->getLy() == 1 && compressedRas->getPixelSize() == 1); - TUINT32 size = compressedRas->getLx(); - oss.write((char *)&size, sizeof(TUINT32)); - oss.write((char *)compressedRas->getRawData(), size); - assert(!oss.fail()); + Tofstream oss(m_fp); + assert(compressedRas->getLy() == 1 && compressedRas->getPixelSize() == 1); + TUINT32 size = compressedRas->getLx(); + oss.write((char *)&size, sizeof(TUINT32)); + oss.write((char *)compressedRas->getRawData(), size); + assert(!oss.fail()); - compressedRas->unlock(); + compressedRas->unlock(); } //------------------------------------------------------------------------------ -CompressedOnDiskCacheItem::~CompressedOnDiskCacheItem() -{ - delete m_imageInfo; - TSystem::deleteFile(m_fp); +CompressedOnDiskCacheItem::~CompressedOnDiskCacheItem() { + delete m_imageInfo; + TSystem::deleteFile(m_fp); } //------------------------------------------------------------------------------ -TImageP CompressedOnDiskCacheItem::getImage() const -{ - Tifstream is(m_fp); - TUINT32 dataSize; - is.read((char *)&dataSize, sizeof(TUINT32)); - TRasterGR8P ras(dataSize, 1); - ras->lock(); - UCHAR *data = ras->getRawData(); - is.read((char *)data, dataSize); - assert(!is.fail()); - ras->unlock(); - CompressedOnMemoryCacheItem item(ras, m_builder->clone(), m_imageInfo->clone()); - return item.getImage(); +TImageP CompressedOnDiskCacheItem::getImage() const { + Tifstream is(m_fp); + TUINT32 dataSize; + is.read((char *)&dataSize, sizeof(TUINT32)); + TRasterGR8P ras(dataSize, 1); + ras->lock(); + UCHAR *data = ras->getRawData(); + is.read((char *)data, dataSize); + assert(!is.fail()); + ras->unlock(); + CompressedOnMemoryCacheItem item(ras, m_builder->clone(), + m_imageInfo->clone()); + return item.getImage(); } //------------------------------------------------------------------------------ -class UncompressedOnDiskCacheItem : public CacheItem -{ - int m_pixelsize; +class UncompressedOnDiskCacheItem : public CacheItem { + int m_pixelsize; public: - UncompressedOnDiskCacheItem(const TFilePath &fp, - const TImageP &img); + UncompressedOnDiskCacheItem(const TFilePath &fp, const TImageP &img); - ~UncompressedOnDiskCacheItem(); + ~UncompressedOnDiskCacheItem(); - TUINT32 getSize() const { return 0; } - TImageP getImage() const; - //TRaster32P getRaster32() const; + TUINT32 getSize() const { return 0; } + TImageP getImage() const; + // TRaster32P getRaster32() const; - TFilePath m_fp; + TFilePath m_fp; }; #ifdef _WIN32 template class DVAPI TSmartPointerT; -template class DVAPI TDerivedSmartPointerT; +template class DVAPI + TDerivedSmartPointerT; #endif -typedef TDerivedSmartPointerT UncompressedOnDiskCacheItemP; +typedef TDerivedSmartPointerT + UncompressedOnDiskCacheItemP; //------------------------------------------------------------------------------ UncompressedOnDiskCacheItem::UncompressedOnDiskCacheItem(const TFilePath &fp, - const TImageP &image) - : CacheItem(0, 0), m_fp(fp) -{ - TRasterImageP ri = image; - - TRasterP ras; - if (ri) { - m_imageInfo = new RasterImageInfo(ri); - ras = ri->getRaster(); - } + const TImageP &image) + : CacheItem(0, 0), m_fp(fp) { + TRasterImageP ri = image; + + TRasterP ras; + if (ri) { + m_imageInfo = new RasterImageInfo(ri); + ras = ri->getRaster(); + } #ifndef TNZCORE_LIGHT - else { - TToonzImageP ti = image; - if (ti) { - m_imageInfo = new ToonzImageInfo(ti); - ras = ti->getRaster(); - } else - assert(false); - } + else { + TToonzImageP ti = image; + if (ti) { + m_imageInfo = new ToonzImageInfo(ti); + ras = ti->getRaster(); + } else + assert(false); + } #else - else - assert(false); + else + assert(false); #endif - m_builder = 0; - - int dataSize = ras->getLx() * ras->getLy() * ras->getPixelSize(); - - int lx = ras->getLx(); - int ly = ras->getLy(); - int wrap = ras->getWrap(); - m_pixelsize = ras->getPixelSize(); - - Tofstream oss(m_fp); - //oss.write((char*)&dataSize, sizeof(TUINT32)); - //assert(!oss.fail()); - ras->lock(); - if (lx == wrap) { - oss.write((char *)ras->getRawData(), dataSize); - assert(!oss.fail()); - } else { - char *buf = (char *)ras->getRawData(); - for (int i = 0; i < ly; i++, buf += wrap) { - oss.write(buf, lx * m_pixelsize); - assert(!oss.fail()); - } - } - ras->unlock(); + m_builder = 0; + + int dataSize = ras->getLx() * ras->getLy() * ras->getPixelSize(); + + int lx = ras->getLx(); + int ly = ras->getLy(); + int wrap = ras->getWrap(); + m_pixelsize = ras->getPixelSize(); + + Tofstream oss(m_fp); + // oss.write((char*)&dataSize, sizeof(TUINT32)); + // assert(!oss.fail()); + ras->lock(); + if (lx == wrap) { + oss.write((char *)ras->getRawData(), dataSize); + assert(!oss.fail()); + } else { + char *buf = (char *)ras->getRawData(); + for (int i = 0; i < ly; i++, buf += wrap) { + oss.write(buf, lx * m_pixelsize); + assert(!oss.fail()); + } + } + ras->unlock(); } //------------------------------------------------------------------------------ -UncompressedOnDiskCacheItem::~UncompressedOnDiskCacheItem() -{ - delete m_imageInfo; - TSystem::deleteFile(m_fp); +UncompressedOnDiskCacheItem::~UncompressedOnDiskCacheItem() { + delete m_imageInfo; + TSystem::deleteFile(m_fp); } //------------------------------------------------------------------------------ -TImageP UncompressedOnDiskCacheItem::getImage() const -{ - Tifstream is(m_fp); - TUINT32 dataSize = m_imageInfo->m_size.lx * m_imageInfo->m_size.ly * m_pixelsize; - - //is.read((char*)&dataSize, sizeof(TUINT32)); - //assert(unsigned(m_lx*m_ly*m_pixelsize)==dataSize); - - TRasterP ras; - - RasterImageInfo *rii = dynamic_cast(m_imageInfo); - - if (rii) { - if (m_pixelsize == 4) - ras = (TRasterP)(TRaster32P(rii->m_size)); - else if (m_pixelsize == 8) - ras = (TRasterP)(TRaster64P(rii->m_size)); - else if (m_pixelsize == 1) - ras = (TRasterP)(TRasterGR8P(rii->m_size)); - else if (m_pixelsize == 2) - ras = (TRasterP)(TRasterGR16P(rii->m_size)); - else - assert(false); - ras->lock(); - char *data = (char *)ras->getRawData(); - is.read(data, dataSize); - ras->unlock(); +TImageP UncompressedOnDiskCacheItem::getImage() const { + Tifstream is(m_fp); + TUINT32 dataSize = + m_imageInfo->m_size.lx * m_imageInfo->m_size.ly * m_pixelsize; + + // is.read((char*)&dataSize, sizeof(TUINT32)); + // assert(unsigned(m_lx*m_ly*m_pixelsize)==dataSize); + + TRasterP ras; + + RasterImageInfo *rii = dynamic_cast(m_imageInfo); + + if (rii) { + if (m_pixelsize == 4) + ras = (TRasterP)(TRaster32P(rii->m_size)); + else if (m_pixelsize == 8) + ras = (TRasterP)(TRaster64P(rii->m_size)); + else if (m_pixelsize == 1) + ras = (TRasterP)(TRasterGR8P(rii->m_size)); + else if (m_pixelsize == 2) + ras = (TRasterP)(TRasterGR16P(rii->m_size)); + else + assert(false); + ras->lock(); + char *data = (char *)ras->getRawData(); + is.read(data, dataSize); + ras->unlock(); #ifdef _DEBUGTOONZ - ras->m_cashed = true; + ras->m_cashed = true; #endif - return RasterImageBuilder().build(m_imageInfo, ras); - } + return RasterImageBuilder().build(m_imageInfo, ras); + } #ifndef TNZCORE_LIGHT - else { - ToonzImageInfo *tii = dynamic_cast(m_imageInfo); - if (tii) { - ras = (TRasterP)(TRasterCM32P(tii->m_size)); - ras->lock(); - char *data = (char *)ras->getRawData(); - is.read(data, dataSize); - ras->unlock(); + else { + ToonzImageInfo *tii = dynamic_cast(m_imageInfo); + if (tii) { + ras = (TRasterP)(TRasterCM32P(tii->m_size)); + ras->lock(); + char *data = (char *)ras->getRawData(); + is.read(data, dataSize); + ras->unlock(); #ifdef _DEBUG - ras->m_cashed = true; + ras->m_cashed = true; #endif - return ToonzImageBuilder().build(m_imageInfo, ras); - } else { - assert(false); - return 0; - } - } + return ToonzImageBuilder().build(m_imageInfo, ras); + } else { + assert(false); + return 0; + } + } #else - else { - assert(false); - return 0; - } + else { + assert(false); + return 0; + } #endif } //------------------------------------------------------------------------------ -std::string TImageCache::getUniqueId(void) -{ - static TAtomicVar count; - std::stringstream ss; - ss << ++count; - return "IMAGECACHEUNIQUEID" + ss.str(); +std::string TImageCache::getUniqueId(void) { + static TAtomicVar count; + std::stringstream ss; + ss << ++count; + return "IMAGECACHEUNIQUEID" + ss.str(); } -class TImageCache::Imp -{ +class TImageCache::Imp { public: - Imp() : m_rootDir() - { - //ATTENZIONE: e' molto piu' veloce se si usa memoria fisica - //invece che virtuale: la virtuale e' tanta, non c'e' quindi bisogno - //di comprimere le immagini, che grandi come sono vengono swappate su disco - if (TBigMemoryManager::instance()->isActive()) - return; - - m_reservedMemory = (TINT64)(TSystem::getMemorySize(true) * 0.10); - if (m_reservedMemory < 64 * 1024) - m_reservedMemory = 64 * 1024; - } - - ~Imp() - { - if (m_rootDir != TFilePath()) - TSystem::rmDirTree(m_rootDir); - } - - bool inline notEnoughMemory() - { - if (TBigMemoryManager::instance()->isActive()) - return TBigMemoryManager::instance()->getAvailableMemoryinKb() < 50 * 1024; - else - return TSystem::memoryShortage(); - } - - void doCompress(); - void doCompress(std::string id); - UCHAR *compressAndMalloc(TUINT32 requestedSize); // compress in the cache till it can nallocate the requested memory - void outputMap(UINT chunkRequested, std::string filename); - void remove(const std::string &id); - void remap(const std::string &dstId, const std::string &srcId); - TImageP get(const std::string &id, bool toBeModified); - void add(const std::string &id, const TImageP &img, bool overwrite); - TFilePath m_rootDir; + Imp() : m_rootDir() { + // ATTENZIONE: e' molto piu' veloce se si usa memoria fisica + // invece che virtuale: la virtuale e' tanta, non c'e' quindi bisogno + // di comprimere le immagini, che grandi come sono vengono swappate su disco + if (TBigMemoryManager::instance()->isActive()) return; + + m_reservedMemory = (TINT64)(TSystem::getMemorySize(true) * 0.10); + if (m_reservedMemory < 64 * 1024) m_reservedMemory = 64 * 1024; + } + + ~Imp() { + if (m_rootDir != TFilePath()) TSystem::rmDirTree(m_rootDir); + } + + bool inline notEnoughMemory() { + if (TBigMemoryManager::instance()->isActive()) + return TBigMemoryManager::instance()->getAvailableMemoryinKb() < + 50 * 1024; + else + return TSystem::memoryShortage(); + } + + void doCompress(); + void doCompress(std::string id); + UCHAR *compressAndMalloc(TUINT32 requestedSize); // compress in the cache + // till it can nallocate the + // requested memory + void outputMap(UINT chunkRequested, std::string filename); + void remove(const std::string &id); + void remap(const std::string &dstId, const std::string &srcId); + TImageP get(const std::string &id, bool toBeModified); + void add(const std::string &id, const TImageP &img, bool overwrite); + TFilePath m_rootDir; #ifndef TNZCORE_LIGHT - QThreadStorage m_isEnabled; + QThreadStorage m_isEnabled; #else - bool m_isEnabled; + bool m_isEnabled; #endif - std::map m_uncompressedItems; - std::map m_itemHistory; - std::map m_compressedItems; - std::map m_itemsByImagePointer; //items ordered by ImageP.getPointer() - std::map m_duplicatedItems; //for duplicated items (when id1!=id2 but image1==image2) in the map: key is dup id, value is main id - //memoria fisica totale della macchina che non puo' essere utilizzata; - TINT64 m_reservedMemory; - TThread::Mutex m_mutex; - - static int m_fileid; + std::map m_uncompressedItems; + std::map m_itemHistory; + std::map m_compressedItems; + std::map + m_itemsByImagePointer; // items ordered by ImageP.getPointer() + std::map m_duplicatedItems; // for duplicated items + // (when id1!=id2 but + // image1==image2) in + // the map: key is dup + // id, value is main id + // memoria fisica totale della macchina che non puo' essere utilizzata; + TINT64 m_reservedMemory; + TThread::Mutex m_mutex; + + static int m_fileid; }; int TImageCache::Imp::m_fileid; //------------------------------------------------------------------------------ -namespace -{ -inline void *getPointer(const TImageP &img) -{ - TRasterImageP rimg = img; - if (rimg) - return rimg->getRaster().getPointer(); +namespace { +inline void *getPointer(const TImageP &img) { + TRasterImageP rimg = img; + if (rimg) return rimg->getRaster().getPointer(); #ifndef TNZCORE_LIGHT - TToonzImageP timg = img; - if (timg) - return timg->getRaster().getPointer(); + TToonzImageP timg = img; + if (timg) return timg->getRaster().getPointer(); #endif - return img.getPointer(); + return img.getPointer(); } // Returns true or false whether the image or its eventual raster are // referenced by someone other than Toonz cache. -inline TINT32 hasExternalReferences(const TImageP &img) -{ - int refCount; +inline TINT32 hasExternalReferences(const TImageP &img) { + int refCount; - { - TRasterImageP rimg = img; - if (rimg) - refCount = rimg->getRaster()->getRefCount(); - } + { + TRasterImageP rimg = img; + if (rimg) refCount = rimg->getRaster()->getRefCount(); + } #ifndef TNZCORE_LIGHT - { - TToonzImageP timg = img; - if (timg) - refCount = timg->getRaster()->getRefCount() - 1; //!!! the TToonzImage::getRaster method increments raster refCount!(the TRasterImage::getRaster don't) - } + { + TToonzImageP timg = img; + if (timg) + refCount = timg->getRaster()->getRefCount() - + 1; //!!! the TToonzImage::getRaster method increments raster + //!refCount!(the TRasterImage::getRaster don't) + } #endif - return std::max(refCount, img->getRefCount()) > 1; + return std::max(refCount, img->getRefCount()) > 1; } } //------------------------------------------------------------------------------ -void TImageCache::Imp::doCompress() -{ - // se la memoria usata per mantenere le immagini decompresse e' superiore - // a un dato valore, comprimo alcune immagini non compresse non checked-out - // in modo da liberare memoria +void TImageCache::Imp::doCompress() { + // se la memoria usata per mantenere le immagini decompresse e' superiore + // a un dato valore, comprimo alcune immagini non compresse non checked-out + // in modo da liberare memoria - // per il momento scorre tutte le immagini alla ricerca di immagini - // non compresse non checked-out + // per il momento scorre tutte le immagini alla ricerca di immagini + // non compresse non checked-out - TThread::MutexLocker sl(&m_mutex); + TThread::MutexLocker sl(&m_mutex); - std::map::iterator itu = m_itemHistory.begin(); + std::map::iterator itu = m_itemHistory.begin(); - for (; itu != m_itemHistory.end() && notEnoughMemory();) { - std::map::iterator it = m_uncompressedItems.find(itu->second); - assert(it != m_uncompressedItems.end()); - CacheItemP item = it->second; + for (; itu != m_itemHistory.end() && notEnoughMemory();) { + std::map::iterator it = + m_uncompressedItems.find(itu->second); + assert(it != m_uncompressedItems.end()); + CacheItemP item = it->second; - UncompressedOnMemoryCacheItemP uitem = item; - if (item->m_cantCompress || - (uitem && (!uitem->m_image || hasExternalReferences(uitem->m_image)))) { - ++itu; - continue; - } - std::string id = it->first; + UncompressedOnMemoryCacheItemP uitem = item; + if (item->m_cantCompress || + (uitem && (!uitem->m_image || hasExternalReferences(uitem->m_image)))) { + ++itu; + continue; + } + std::string id = it->first; #ifdef _WIN32 - assert(itu->first == it->second->m_historyCount); - itu = m_itemHistory.erase(itu); - m_itemsByImagePointer.erase(getPointer(item->getImage())); - m_uncompressedItems.erase(it); + assert(itu->first == it->second->m_historyCount); + itu = m_itemHistory.erase(itu); + m_itemsByImagePointer.erase(getPointer(item->getImage())); + m_uncompressedItems.erase(it); #else - std::map::iterator itu2 = itu; - itu++; - m_itemHistory.erase(itu2); - m_itemsByImagePointer.erase(item->getImage().getPointer()); - m_uncompressedItems.erase(it); + std::map::iterator itu2 = itu; + itu++; + m_itemHistory.erase(itu2); + m_itemsByImagePointer.erase(item->getImage().getPointer()); + m_uncompressedItems.erase(it); #endif - if (m_compressedItems.find(id) == m_compressedItems.end()) { - assert(uitem); - item->m_cantCompress = true; - CacheItemP newItem = new CompressedOnMemoryCacheItem(item->getImage()); //WARNING the codec buffer allocation can CHANGE the cache. - item->m_cantCompress = false; - if (newItem->getSize() == 0) ///non c'era memoria sufficiente per il buffer compresso.... - { - assert(m_rootDir != TFilePath()); - TFilePath fp = m_rootDir + TFilePath(std::to_string(TImageCache::Imp::m_fileid++)); - newItem = new UncompressedOnDiskCacheItem(fp, item->getImage()); - } - m_compressedItems[id] = newItem; - item = CacheItemP(); - uitem = UncompressedOnMemoryCacheItemP(); - //doCompress();//restart, since interators can have been changed (see comment above) - //return; - itu = m_itemHistory.begin(); - } - } - - // se il quantitativo di memoria utilizzata e' superiore a un dato valore, sposto - // su disco alcune immagini compresse in modo da liberare memoria - - if (itu != m_itemHistory.end()) //memory is enough! - return; - - std::map::iterator itc = m_compressedItems.begin(); - for (; itc != m_compressedItems.end() && notEnoughMemory(); ++itc) { - CacheItemP item = itc->second; - if (item->m_cantCompress) - continue; - - CompressedOnMemoryCacheItemP citem = itc->second; - if (citem) { - assert(m_rootDir != TFilePath()); - TFilePath fp = m_rootDir + TFilePath(std::to_string(TImageCache::Imp::m_fileid++)); - - CacheItemP newItem = new CompressedOnDiskCacheItem(fp, citem->m_compressedRas, - citem->m_builder->clone(), citem->m_imageInfo->clone()); - - itc->second = 0; - m_compressedItems[itc->first] = newItem; - } - } + if (m_compressedItems.find(id) == m_compressedItems.end()) { + assert(uitem); + item->m_cantCompress = true; + CacheItemP newItem = new CompressedOnMemoryCacheItem( + item->getImage()); // WARNING the codec buffer allocation can CHANGE + // the cache. + item->m_cantCompress = false; + if (newItem->getSize() == + 0) /// non c'era memoria sufficiente per il buffer compresso.... + { + assert(m_rootDir != TFilePath()); + TFilePath fp = + m_rootDir + TFilePath(std::to_string(TImageCache::Imp::m_fileid++)); + newItem = new UncompressedOnDiskCacheItem(fp, item->getImage()); + } + m_compressedItems[id] = newItem; + item = CacheItemP(); + uitem = UncompressedOnMemoryCacheItemP(); + // doCompress();//restart, since interators can have been changed (see + // comment above) + // return; + itu = m_itemHistory.begin(); + } + } + + // se il quantitativo di memoria utilizzata e' superiore a un dato valore, + // sposto + // su disco alcune immagini compresse in modo da liberare memoria + + if (itu != m_itemHistory.end()) // memory is enough! + return; + + std::map::iterator itc = m_compressedItems.begin(); + for (; itc != m_compressedItems.end() && notEnoughMemory(); ++itc) { + CacheItemP item = itc->second; + if (item->m_cantCompress) continue; + + CompressedOnMemoryCacheItemP citem = itc->second; + if (citem) { + assert(m_rootDir != TFilePath()); + TFilePath fp = + m_rootDir + TFilePath(std::to_string(TImageCache::Imp::m_fileid++)); + + CacheItemP newItem = new CompressedOnDiskCacheItem( + fp, citem->m_compressedRas, citem->m_builder->clone(), + citem->m_imageInfo->clone()); + + itc->second = 0; + m_compressedItems[itc->first] = newItem; + } + } } //------------------------------------------------------------------------------ -void TImageCache::Imp::doCompress(std::string id) -{ - TThread::MutexLocker sl(&m_mutex); - - // search id in m_uncompressedItems - std::map::iterator it = m_uncompressedItems.find(id); - if (it == m_uncompressedItems.end()) - return; // id not found: return - - // is item suitable for compression ? - CacheItemP item = it->second; - UncompressedOnMemoryCacheItemP uitem = item; - if (item->m_cantCompress || - (uitem && (!uitem->m_image || hasExternalReferences(uitem->m_image)))) - return; - - // search id in m_itemHistory - std::map::iterator itu = m_itemHistory.begin(); - while (itu != m_itemHistory.end() && itu->second != id) - ++itu; - if (itu == m_itemHistory.end()) - return; // id not found: return +void TImageCache::Imp::doCompress(std::string id) { + TThread::MutexLocker sl(&m_mutex); + + // search id in m_uncompressedItems + std::map::iterator it = m_uncompressedItems.find(id); + if (it == m_uncompressedItems.end()) return; // id not found: return + + // is item suitable for compression ? + CacheItemP item = it->second; + UncompressedOnMemoryCacheItemP uitem = item; + if (item->m_cantCompress || + (uitem && (!uitem->m_image || hasExternalReferences(uitem->m_image)))) + return; + + // search id in m_itemHistory + std::map::iterator itu = m_itemHistory.begin(); + while (itu != m_itemHistory.end() && itu->second != id) ++itu; + if (itu == m_itemHistory.end()) return; // id not found: return // delete itu from m_itemHistory #ifdef _WIN32 - assert(itu->first == it->second->m_historyCount); - itu = m_itemHistory.erase(itu); - m_itemsByImagePointer.erase(getPointer(item->getImage())); + assert(itu->first == it->second->m_historyCount); + itu = m_itemHistory.erase(itu); + m_itemsByImagePointer.erase(getPointer(item->getImage())); #else - std::map::iterator itu2 = itu; - itu++; - m_itemHistory.erase(itu2); - m_itemsByImagePointer.erase(item->getImage().getPointer()); + std::map::iterator itu2 = itu; + itu++; + m_itemHistory.erase(itu2); + m_itemsByImagePointer.erase(item->getImage().getPointer()); #endif - // delete item from m_uncompressedItems - m_uncompressedItems.erase(it); - - // check if item has been already compressed. this should never happen - if (m_compressedItems.find(id) != m_compressedItems.end()) - return; - - assert(uitem); - item->m_cantCompress = true; // ?? - CacheItemP newItem = new CompressedOnMemoryCacheItem(item->getImage()); //WARNING the codec buffer allocation can CHANGE the cache. - item->m_cantCompress = false; // ?? - if (newItem->getSize() == 0) ///non c'era memoria sufficiente per il buffer compresso.... - { - assert(m_rootDir != TFilePath()); - TFilePath fp = m_rootDir + TFilePath(std::to_string(TImageCache::Imp::m_fileid++)); - newItem = new UncompressedOnDiskCacheItem(fp, item->getImage()); - } - m_compressedItems[id] = newItem; - item = CacheItemP(); - uitem = UncompressedOnMemoryCacheItemP(); + // delete item from m_uncompressedItems + m_uncompressedItems.erase(it); + + // check if item has been already compressed. this should never happen + if (m_compressedItems.find(id) != m_compressedItems.end()) return; + + assert(uitem); + item->m_cantCompress = true; // ?? + CacheItemP newItem = new CompressedOnMemoryCacheItem( + item->getImage()); // WARNING the codec buffer allocation can CHANGE the + // cache. + item->m_cantCompress = false; // ?? + if (newItem->getSize() == + 0) /// non c'era memoria sufficiente per il buffer compresso.... + { + assert(m_rootDir != TFilePath()); + TFilePath fp = + m_rootDir + TFilePath(std::to_string(TImageCache::Imp::m_fileid++)); + newItem = new UncompressedOnDiskCacheItem(fp, item->getImage()); + } + m_compressedItems[id] = newItem; + item = CacheItemP(); + uitem = UncompressedOnMemoryCacheItemP(); } /* - // se il quantitativo di memoria utilizzata e' superiore a un dato valore, sposto + // se il quantitativo di memoria utilizzata e' superiore a un dato valore, + sposto // su disco alcune immagini compresse in modo da liberare memoria if (itu != m_itemHistory.end()) //memory is enough! return; - + std::map::iterator itc = m_compressedItems.begin(); for ( ; itc != m_compressedItems.end() && notEnoughMemory(); ++itc) - { - CacheItemP item = itc->second; - if (item->m_cantCompress) - continue; - - CompressedOnMemoryCacheItemP citem = itc->second; - if (citem) - { - assert(m_rootDir!=TFilePath()); - TFilePath fp = m_rootDir + TFilePath(toString(TImageCache::Imp::m_fileid++)); - - CacheItemP newItem = new CompressedOnDiskCacheItem(fp, citem->m_compressedRas, - citem->m_builder->clone(), citem->m_imageInfo->clone()); - - itc->second = 0; - m_compressedItems[itc->first] = newItem; - } - } + { + CacheItemP item = itc->second; + if (item->m_cantCompress) + continue; + + CompressedOnMemoryCacheItemP citem = itc->second; + if (citem) + { + assert(m_rootDir!=TFilePath()); + TFilePath fp = m_rootDir + + TFilePath(toString(TImageCache::Imp::m_fileid++)); + + CacheItemP newItem = new CompressedOnDiskCacheItem(fp, + citem->m_compressedRas, + citem->m_builder->clone(), citem->m_imageInfo->clone()); + + itc->second = 0; + m_compressedItems[itc->first] = newItem; + } + } */ //------------------------------------------------------------------------------ -UCHAR *TImageCache::Imp::compressAndMalloc(TUINT32 size) -{ - UCHAR *buf = 0; - - TThread::MutexLocker sl(&m_mutex); - - TheCodec::instance()->reset(); +UCHAR *TImageCache::Imp::compressAndMalloc(TUINT32 size) { + UCHAR *buf = 0; - //if (size!=0) - // size = size>>10; + TThread::MutexLocker sl(&m_mutex); - //assert(size==0 || TBigMemoryManager::instance()->isActive()); + TheCodec::instance()->reset(); - std::map::iterator itu = m_itemHistory.begin(); - while ((buf = TBigMemoryManager::instance()->getBuffer(size)) == 0 && - itu != m_itemHistory.end()) //>TBigMemoryManager::instance()->getAvailableMemoryinKb())) - { - std::map::iterator it = m_uncompressedItems.find(itu->second); - assert(it != m_uncompressedItems.end()); - CacheItemP item = it->second; + // if (size!=0) + // size = size>>10; - UncompressedOnMemoryCacheItemP uitem = item; - if (item->m_cantCompress || (uitem && (!uitem->m_image || hasExternalReferences(uitem->m_image)))) { - ++itu; - continue; - } + // assert(size==0 || TBigMemoryManager::instance()->isActive()); - if (m_compressedItems.find(it->first) == m_compressedItems.end()) { - assert(uitem); - CacheItemP newItem; - //newItem = new CompressedOnMemoryCacheItem(item->getImage()); - //if (newItem->getSize()==0) - // { - assert(m_rootDir != TFilePath()); - TFilePath fp = m_rootDir + TFilePath(std::to_string(TImageCache::Imp::m_fileid++)); - newItem = new UncompressedOnDiskCacheItem(fp, item->getImage()); - // } - - m_compressedItems[it->first] = newItem; - } + std::map::iterator itu = m_itemHistory.begin(); + while ( + (buf = TBigMemoryManager::instance()->getBuffer(size)) == 0 && + itu != + m_itemHistory + .end()) //>TBigMemoryManager::instance()->getAvailableMemoryinKb())) + { + std::map::iterator it = + m_uncompressedItems.find(itu->second); + assert(it != m_uncompressedItems.end()); + CacheItemP item = it->second; + + UncompressedOnMemoryCacheItemP uitem = item; + if (item->m_cantCompress || + (uitem && (!uitem->m_image || hasExternalReferences(uitem->m_image)))) { + ++itu; + continue; + } + + if (m_compressedItems.find(it->first) == m_compressedItems.end()) { + assert(uitem); + CacheItemP newItem; + // newItem = new CompressedOnMemoryCacheItem(item->getImage()); + // if (newItem->getSize()==0) + // { + assert(m_rootDir != TFilePath()); + TFilePath fp = + m_rootDir + TFilePath(std::to_string(TImageCache::Imp::m_fileid++)); + newItem = new UncompressedOnDiskCacheItem(fp, item->getImage()); + // } + + m_compressedItems[it->first] = newItem; + } #ifdef _WIN32 - assert(itu->first == it->second->m_historyCount); - itu = m_itemHistory.erase(itu); - m_itemsByImagePointer.erase(getPointer(item->getImage())); - m_uncompressedItems.erase(it); + assert(itu->first == it->second->m_historyCount); + itu = m_itemHistory.erase(itu); + m_itemsByImagePointer.erase(getPointer(item->getImage())); + m_uncompressedItems.erase(it); #else - std::map::iterator itu2 = itu; - itu++; - m_itemHistory.erase(itu2); - m_itemsByImagePointer.erase(item->getImage().getPointer()); - m_uncompressedItems.erase(it); + std::map::iterator itu2 = itu; + itu++; + m_itemHistory.erase(itu2); + m_itemsByImagePointer.erase(item->getImage().getPointer()); + m_uncompressedItems.erase(it); #endif - } - - if (buf != 0) - return buf; - - std::map::iterator itc = m_compressedItems.begin(); - for (; itc != m_compressedItems.end() && - (buf = TBigMemoryManager::instance()->getBuffer(size)) == 0; - ++itc) { - CacheItemP item = itc->second; - if (item->m_cantCompress) - continue; - - CompressedOnMemoryCacheItemP citem = itc->second; - if (citem) { - assert(m_rootDir != TFilePath()); - TFilePath fp = m_rootDir + TFilePath(std::to_string(TImageCache::Imp::m_fileid++)); - - CacheItemP newItem = new CompressedOnDiskCacheItem( - fp, citem->m_compressedRas, - citem->m_builder->clone(), citem->m_imageInfo->clone()); - - itc->second = 0; - m_compressedItems[itc->first] = newItem; - } - } - - return buf; + } + + if (buf != 0) return buf; + + std::map::iterator itc = m_compressedItems.begin(); + for (; itc != m_compressedItems.end() && + (buf = TBigMemoryManager::instance()->getBuffer(size)) == 0; + ++itc) { + CacheItemP item = itc->second; + if (item->m_cantCompress) continue; + + CompressedOnMemoryCacheItemP citem = itc->second; + if (citem) { + assert(m_rootDir != TFilePath()); + TFilePath fp = + m_rootDir + TFilePath(std::to_string(TImageCache::Imp::m_fileid++)); + + CacheItemP newItem = new CompressedOnDiskCacheItem( + fp, citem->m_compressedRas, citem->m_builder->clone(), + citem->m_imageInfo->clone()); + + itc->second = 0; + m_compressedItems[itc->first] = newItem; + } + } + + return buf; } //------------------------------------------------------------------------------ -namespace -{ +namespace { -int check = 0; +int check = 0; const int magic = 123456; } static TImageCache *CacheInstance = 0; -TImageCache *TImageCache::instance() +TImageCache *TImageCache::instance() { + if (CacheInstance == 0) CacheInstance = new TImageCache(); + return CacheInstance; + /* +if (!ImageCache::m_instance) { - if (CacheInstance == 0) - CacheInstance = new TImageCache(); - return CacheInstance; - /* - if (!ImageCache::m_instance) - { - ImageCache::m_instance = new ImageCache; - ImageCache::m_destroyer.m_imageCache = ImageCache::m_instance; - } - return ImageCache::m_instance; - */ +ImageCache::m_instance = new ImageCache; +ImageCache::m_destroyer.m_imageCache = ImageCache::m_instance; +} +return ImageCache::m_instance; + */ } //------------------------------------------------------------------------------ -TImageCache::TImageCache() - : m_imp(new Imp()) -{ - assert(check == 0); - check = magic; +TImageCache::TImageCache() : m_imp(new Imp()) { + assert(check == 0); + check = magic; } //------------------------------------------------------------------------------ -TImageCache::~TImageCache() -{ - assert(check == magic); - check = -1; - CacheInstance = 0; +TImageCache::~TImageCache() { + assert(check == magic); + check = -1; + CacheInstance = 0; } //------------------------------------------------------------------------------ -void TImageCache::setEnabled(bool isEnabled) -{ +void TImageCache::setEnabled(bool isEnabled) { #ifndef TNZCORE_LIGHT - QThreadStorage &storage = m_imp->m_isEnabled; - - if (storage.hasLocalData() && *(storage.localData()) == isEnabled) - return; - if (!storage.hasLocalData()) - storage.setLocalData(new bool(isEnabled)); - else - *(storage.localData()) = isEnabled; + QThreadStorage &storage = m_imp->m_isEnabled; + + if (storage.hasLocalData() && *(storage.localData()) == isEnabled) return; + if (!storage.hasLocalData()) + storage.setLocalData(new bool(isEnabled)); + else + *(storage.localData()) = isEnabled; #else - m_imp->m_isEnabled = isEnabled; + m_imp->m_isEnabled = isEnabled; #endif } //------------------------------------------------------------------------------ -bool TImageCache::isEnabled() -{ +bool TImageCache::isEnabled() { #ifndef TNZCORE_LIGHT - QThreadStorage &storage = m_imp->m_isEnabled; + QThreadStorage &storage = m_imp->m_isEnabled; - if (!storage.hasLocalData()) - return true; - return *(storage.localData()); + if (!storage.hasLocalData()) return true; + return *(storage.localData()); #else - return m_isEnabled; + return m_isEnabled; #endif } //------------------------------------------------------------------------------ -void TImageCache::setRootDir(const TFilePath &cacheDir) -{ - if (m_imp->m_rootDir != TFilePath()) - return; +void TImageCache::setRootDir(const TFilePath &cacheDir) { + if (m_imp->m_rootDir != TFilePath()) return; - m_imp->m_rootDir = cacheDir + TFilePath(std::to_string(TSystem::getProcessId())); + m_imp->m_rootDir = + cacheDir + TFilePath(std::to_string(TSystem::getProcessId())); #ifndef TNZCORE_LIGHT - TFileStatus fs1(m_imp->m_rootDir); + TFileStatus fs1(m_imp->m_rootDir); - if (!fs1.doesExist()) - TSystem::mkDir(m_imp->m_rootDir); + if (!fs1.doesExist()) TSystem::mkDir(m_imp->m_rootDir); #endif } @@ -1190,818 +1145,824 @@ return m_imp->m_rootDir; */ //------------------------------------------------------------------------------ -UCHAR *TImageCache::compressAndMalloc(TUINT32 requestedSize) -{ - return m_imp->compressAndMalloc(requestedSize); +UCHAR *TImageCache::compressAndMalloc(TUINT32 requestedSize) { + return m_imp->compressAndMalloc(requestedSize); } //------------------------------------------------------------------------------ -void TImageCache::add(const std::string &id, const TImageP &img, bool overwrite) -{ - if (!isEnabled()) - return; - m_imp->add(id, img, overwrite); +void TImageCache::add(const std::string &id, const TImageP &img, + bool overwrite) { + if (!isEnabled()) return; + m_imp->add(id, img, overwrite); } //------------------------------------------------------------------------------ -void TImageCache::Imp::add(const std::string &id, const TImageP &img, bool overwrite) -{ - - TThread::MutexLocker sl(&m_mutex); +void TImageCache::Imp::add(const std::string &id, const TImageP &img, + bool overwrite) { + TThread::MutexLocker sl(&m_mutex); #ifdef LEVO - std::map::iterator it1 = m_uncompressedItems.begin(); - - for (; it1 != m_uncompressedItems.end(); ++it1) { - UncompressedOnMemoryCacheItemP item = (UncompressedOnMemoryCacheItemP)it1->second; - //m_memUsage -= item->getSize(); - assert(item); - TImageP refImg = item->getImage(); - if (refImg.getPointer() == img.getPointer() && it1->first != id) - assert(!"opps gia' esiste in cache!"); - } + std::map::iterator it1 = m_uncompressedItems.begin(); + + for (; it1 != m_uncompressedItems.end(); ++it1) { + UncompressedOnMemoryCacheItemP item = + (UncompressedOnMemoryCacheItemP)it1->second; + // m_memUsage -= item->getSize(); + assert(item); + TImageP refImg = item->getImage(); + if (refImg.getPointer() == img.getPointer() && it1->first != id) + assert(!"opps gia' esiste in cache!"); + } #endif - std::map::iterator itUncompr = m_uncompressedItems.find(id); - std::map::iterator itCompr = m_compressedItems.find(id); + std::map::iterator itUncompr = + m_uncompressedItems.find(id); + std::map::iterator itCompr = + m_compressedItems.find(id); #ifdef _DEBUGTOONZ - TRasterImageP rimg = (TRasterImageP)img; - TToonzImageP timg = (TToonzImageP)img; + TRasterImageP rimg = (TRasterImageP)img; + TToonzImageP timg = (TToonzImageP)img; #endif - if (itUncompr != m_uncompressedItems.end() || - itCompr != m_compressedItems.end()) //already present in cache with same id... - { - if (overwrite) { + if (itUncompr != m_uncompressedItems.end() || + itCompr != + m_compressedItems.end()) // already present in cache with same id... + { + if (overwrite) { #ifdef _DEBUGTOONZ - if (rimg) - rimg->getRaster()->m_cashed = true; - else if (timg) - timg->getRaster()->m_cashed = true; + if (rimg) + rimg->getRaster()->m_cashed = true; + else if (timg) + timg->getRaster()->m_cashed = true; #endif - std::map::iterator it; - - if (itUncompr != m_uncompressedItems.end()) { - assert(m_itemHistory.find(itUncompr->second->m_historyCount) != m_itemHistory.end()); - m_itemHistory.erase(itUncompr->second->m_historyCount); - m_itemsByImagePointer.erase(getPointer(itUncompr->second->getImage())); - m_uncompressedItems.erase(itUncompr); - } - if (itCompr != m_compressedItems.end()) - m_compressedItems.erase(id); - } else - return; - } else { - std::map::iterator dt = m_duplicatedItems.find(id); - if ((dt != m_duplicatedItems.end()) && !overwrite) - return; - - std::map::iterator it; - if ((it = m_itemsByImagePointer.find(getPointer(img))) != m_itemsByImagePointer.end()) //already present in cache with another id... - { - m_duplicatedItems[id] = it->second; - return; - } - - if (dt != m_duplicatedItems.end()) - m_duplicatedItems.erase(dt); - } - - CacheItemP item; + std::map::iterator it; + + if (itUncompr != m_uncompressedItems.end()) { + assert(m_itemHistory.find(itUncompr->second->m_historyCount) != + m_itemHistory.end()); + m_itemHistory.erase(itUncompr->second->m_historyCount); + m_itemsByImagePointer.erase(getPointer(itUncompr->second->getImage())); + m_uncompressedItems.erase(itUncompr); + } + if (itCompr != m_compressedItems.end()) m_compressedItems.erase(id); + } else + return; + } else { + std::map::iterator dt = + m_duplicatedItems.find(id); + if ((dt != m_duplicatedItems.end()) && !overwrite) return; + + std::map::iterator it; + if ((it = m_itemsByImagePointer.find(getPointer(img))) != + m_itemsByImagePointer + .end()) // already present in cache with another id... + { + m_duplicatedItems[id] = it->second; + return; + } + + if (dt != m_duplicatedItems.end()) m_duplicatedItems.erase(dt); + } + + CacheItemP item; #ifdef _DEBUGTOONZ - if (rimg) - rimg->getRaster()->m_cashed = true; - else if (timg) - timg->getRaster()->m_cashed = true; + if (rimg) + rimg->getRaster()->m_cashed = true; + else if (timg) + timg->getRaster()->m_cashed = true; #endif - item = new UncompressedOnMemoryCacheItem(img); + item = new UncompressedOnMemoryCacheItem(img); #ifdef TNZCORE_LIGHT - item->m_cantCompress = false; + item->m_cantCompress = false; #else - item->m_cantCompress = (TVectorImageP(img) ? true : false); + item->m_cantCompress = (TVectorImageP(img) ? true : false); #endif - item->m_id = id; - m_uncompressedItems[id] = item; - m_itemsByImagePointer[getPointer(img)] = id; - item->m_historyCount = HistoryCount; - m_itemHistory[HistoryCount] = id; - HistoryCount++; + item->m_id = id; + m_uncompressedItems[id] = item; + m_itemsByImagePointer[getPointer(img)] = id; + item->m_historyCount = HistoryCount; + m_itemHistory[HistoryCount] = id; + HistoryCount++; - doCompress(); + doCompress(); #ifdef _DEBUGTOONZ -//int itemCount = m_imp->m_uncompressedItems.size()+m_imp->m_compressedItems.size(); -//m_imp->outputDebug(); +// int itemCount = +// m_imp->m_uncompressedItems.size()+m_imp->m_compressedItems.size(); +// m_imp->outputDebug(); #endif } -void TImageCache::remove(const std::string &id) -{ - m_imp->remove(id); -} +void TImageCache::remove(const std::string &id) { m_imp->remove(id); } //------------------------------------------------------------------------------ -void TImageCache::Imp::remove(const std::string &id) -{ - if (CacheInstance == 0) - return; //the remove can be called when exiting from toonz...after the imagecache was already freed! - - assert(check == magic); - TThread::MutexLocker sl(&m_mutex); - - std::map::iterator it1; - if ((it1 = m_duplicatedItems.find(id)) != m_duplicatedItems.end()) //it's a duplicated id... - { - m_duplicatedItems.erase(it1); - return; - } - - for (it1 = m_duplicatedItems.begin(); it1 != m_duplicatedItems.end(); ++it1) - if (it1->second == id) - break; - - if (it1 != m_duplicatedItems.end()) //it has duplicated, so cannot erase it; I erase the duplicate, and assign its id has the main id - { - std::string sonId = it1->first; - m_duplicatedItems.erase(it1); - remap(sonId, id); - return; - } - - std::map::iterator it = m_uncompressedItems.find(id); - std::map::iterator itc = m_compressedItems.find(id); - if (it != m_uncompressedItems.end()) { - const CacheItemP &item = it->second; - assert((UncompressedOnMemoryCacheItemP)item); - assert(m_itemHistory.find(it->second->m_historyCount) != m_itemHistory.end()); - m_itemHistory.erase(it->second->m_historyCount); - m_itemsByImagePointer.erase(getPointer(it->second->getImage())); +void TImageCache::Imp::remove(const std::string &id) { + if (CacheInstance == 0) + return; // the remove can be called when exiting from toonz...after the + // imagecache was already freed! + + assert(check == magic); + TThread::MutexLocker sl(&m_mutex); + + std::map::iterator it1; + if ((it1 = m_duplicatedItems.find(id)) != + m_duplicatedItems.end()) // it's a duplicated id... + { + m_duplicatedItems.erase(it1); + return; + } + + for (it1 = m_duplicatedItems.begin(); it1 != m_duplicatedItems.end(); ++it1) + if (it1->second == id) break; + + if (it1 != m_duplicatedItems.end()) // it has duplicated, so cannot erase it; + // I erase the duplicate, and assign its + // id has the main id + { + std::string sonId = it1->first; + m_duplicatedItems.erase(it1); + remap(sonId, id); + return; + } + + std::map::iterator it = m_uncompressedItems.find(id); + std::map::iterator itc = m_compressedItems.find(id); + if (it != m_uncompressedItems.end()) { + const CacheItemP &item = it->second; + assert((UncompressedOnMemoryCacheItemP)item); + assert(m_itemHistory.find(it->second->m_historyCount) != + m_itemHistory.end()); + m_itemHistory.erase(it->second->m_historyCount); + m_itemsByImagePointer.erase(getPointer(it->second->getImage())); #ifdef _DEBUGTOONZ - if ((TRasterImageP)it->second->getImage()) - ((TRasterImageP)it->second->getImage())->getRaster()->m_cashed = false; - else if ((TToonzImageP)it->second->getImage()) - ((TToonzImageP)it->second->getImage())->getRaster()->m_cashed = false; + if ((TRasterImageP)it->second->getImage()) + ((TRasterImageP)it->second->getImage())->getRaster()->m_cashed = false; + else if ((TToonzImageP)it->second->getImage()) + ((TToonzImageP)it->second->getImage())->getRaster()->m_cashed = false; #endif - m_uncompressedItems.erase(it); - } - if (itc != m_compressedItems.end()) - m_compressedItems.erase(itc); + m_uncompressedItems.erase(it); + } + if (itc != m_compressedItems.end()) m_compressedItems.erase(itc); } //------------------------------------------------------------------------------ -void TImageCache::remap(const std::string &dstId, const std::string &srcId) -{ - m_imp->remap(dstId, srcId); +void TImageCache::remap(const std::string &dstId, const std::string &srcId) { + m_imp->remap(dstId, srcId); } -void TImageCache::Imp::remap(const std::string &dstId, const std::string &srcId) -{ +void TImageCache::Imp::remap(const std::string &dstId, + const std::string &srcId) { + TThread::MutexLocker sl(&m_mutex); + std::map::iterator it = + m_uncompressedItems.find(srcId); + if (it != m_uncompressedItems.end()) { + CacheItemP citem = it->second; + assert(m_itemHistory.find(citem->m_historyCount) != m_itemHistory.end()); + m_itemHistory.erase(citem->m_historyCount); + m_itemsByImagePointer.erase(getPointer(citem->getImage())); + m_uncompressedItems.erase(it); - TThread::MutexLocker sl(&m_mutex); - std::map::iterator it = m_uncompressedItems.find(srcId); - if (it != m_uncompressedItems.end()) { - CacheItemP citem = it->second; - assert(m_itemHistory.find(citem->m_historyCount) != m_itemHistory.end()); - m_itemHistory.erase(citem->m_historyCount); - m_itemsByImagePointer.erase(getPointer(citem->getImage())); - m_uncompressedItems.erase(it); - - m_uncompressedItems[dstId] = citem; - m_itemHistory[citem->m_historyCount] = dstId; - m_itemsByImagePointer[getPointer(citem->getImage())] = dstId; - } - it = m_compressedItems.find(srcId); - if (it != m_compressedItems.end()) { - CacheItemP citem = it->second; - m_compressedItems.erase(it); - m_compressedItems[dstId] = citem; - } - std::map::iterator it2 = m_duplicatedItems.find(srcId); - if (it2 != m_duplicatedItems.end()) { - std::string id = it2->second; - m_duplicatedItems.erase(it2); - m_duplicatedItems[dstId] = id; - } - for (it2 = m_duplicatedItems.begin(); it2 != m_duplicatedItems.end(); ++it2) - if (it2->second == srcId) - it2->second = dstId; + m_uncompressedItems[dstId] = citem; + m_itemHistory[citem->m_historyCount] = dstId; + m_itemsByImagePointer[getPointer(citem->getImage())] = dstId; + } + it = m_compressedItems.find(srcId); + if (it != m_compressedItems.end()) { + CacheItemP citem = it->second; + m_compressedItems.erase(it); + m_compressedItems[dstId] = citem; + } + std::map::iterator it2 = + m_duplicatedItems.find(srcId); + if (it2 != m_duplicatedItems.end()) { + std::string id = it2->second; + m_duplicatedItems.erase(it2); + m_duplicatedItems[dstId] = id; + } + for (it2 = m_duplicatedItems.begin(); it2 != m_duplicatedItems.end(); ++it2) + if (it2->second == srcId) it2->second = dstId; } //------------------------------------------------------------------------------ -void TImageCache::remapIcons(const std::string &dstId, const std::string &srcId) -{ - std::map::iterator it; - std::map table; - std::string prefix = srcId + ":"; - int j = (int)prefix.length(); - for (it = m_imp->m_uncompressedItems.begin(); it != m_imp->m_uncompressedItems.end(); ++it) { - std::string id = it->first; - if (id.find(prefix) == 0) - table[id] = dstId + ":" + id.substr(j); - } - for (std::map::iterator it2 = table.begin(); - it2 != table.end(); ++it2) { - remap(it2->second, it2->first); - } +void TImageCache::remapIcons(const std::string &dstId, + const std::string &srcId) { + std::map::iterator it; + std::map table; + std::string prefix = srcId + ":"; + int j = (int)prefix.length(); + for (it = m_imp->m_uncompressedItems.begin(); + it != m_imp->m_uncompressedItems.end(); ++it) { + std::string id = it->first; + if (id.find(prefix) == 0) table[id] = dstId + ":" + id.substr(j); + } + for (std::map::iterator it2 = table.begin(); + it2 != table.end(); ++it2) { + remap(it2->second, it2->first); + } } //------------------------------------------------------------------------------ -void TImageCache::clear(bool deleteFolder) -{ - TThread::MutexLocker sl(&m_imp->m_mutex); - m_imp->m_uncompressedItems.clear(); - m_imp->m_itemHistory.clear(); - m_imp->m_compressedItems.clear(); - m_imp->m_duplicatedItems.clear(); - m_imp->m_itemsByImagePointer.clear(); - if (deleteFolder && m_imp->m_rootDir != TFilePath()) - TSystem::rmDirTree(m_imp->m_rootDir); +void TImageCache::clear(bool deleteFolder) { + TThread::MutexLocker sl(&m_imp->m_mutex); + m_imp->m_uncompressedItems.clear(); + m_imp->m_itemHistory.clear(); + m_imp->m_compressedItems.clear(); + m_imp->m_duplicatedItems.clear(); + m_imp->m_itemsByImagePointer.clear(); + if (deleteFolder && m_imp->m_rootDir != TFilePath()) + TSystem::rmDirTree(m_imp->m_rootDir); } //------------------------------------------------------------------------------ -void TImageCache::clearSceneImages() -{ - TThread::MutexLocker sl(&m_imp->m_mutex); - - //note the ';' - which follows ':' in the ascii table - m_imp->m_uncompressedItems.erase(m_imp->m_uncompressedItems.begin(), m_imp->m_uncompressedItems.lower_bound("$:")); - m_imp->m_uncompressedItems.erase(m_imp->m_uncompressedItems.lower_bound("$;"), m_imp->m_uncompressedItems.end()); - - m_imp->m_compressedItems.erase(m_imp->m_compressedItems.begin(), m_imp->m_compressedItems.lower_bound("$:")); - m_imp->m_compressedItems.erase(m_imp->m_compressedItems.lower_bound("$;"), m_imp->m_compressedItems.end()); - - m_imp->m_duplicatedItems.erase(m_imp->m_duplicatedItems.begin(), m_imp->m_duplicatedItems.lower_bound("$:")); - m_imp->m_duplicatedItems.erase(m_imp->m_duplicatedItems.lower_bound("$;"), m_imp->m_duplicatedItems.end()); - - //Clear maps whose id is on the second of map pairs. - - std::map::iterator it; - for (it = m_imp->m_itemHistory.begin(); it != m_imp->m_itemHistory.end();) { - if (it->second.size() >= 2 && it->second[0] == '$' && it->second[1] == ':') - ++it; - else { - std::map::iterator app = it; - app++; - m_imp->m_itemHistory.erase(it); - it = app; - } - } - - std::map::iterator jt; - for (jt = m_imp->m_itemsByImagePointer.begin(); jt != m_imp->m_itemsByImagePointer.end();) { - if (jt->second.size() >= 2 && jt->second[0] == '$' && jt->second[1] == ':') - ++jt; - else { - std::map::iterator app = jt; - app++; - m_imp->m_itemsByImagePointer.erase(jt); - jt = app; - } - } +void TImageCache::clearSceneImages() { + TThread::MutexLocker sl(&m_imp->m_mutex); + + // note the ';' - which follows ':' in the ascii table + m_imp->m_uncompressedItems.erase( + m_imp->m_uncompressedItems.begin(), + m_imp->m_uncompressedItems.lower_bound("$:")); + m_imp->m_uncompressedItems.erase(m_imp->m_uncompressedItems.lower_bound("$;"), + m_imp->m_uncompressedItems.end()); + + m_imp->m_compressedItems.erase(m_imp->m_compressedItems.begin(), + m_imp->m_compressedItems.lower_bound("$:")); + m_imp->m_compressedItems.erase(m_imp->m_compressedItems.lower_bound("$;"), + m_imp->m_compressedItems.end()); + + m_imp->m_duplicatedItems.erase(m_imp->m_duplicatedItems.begin(), + m_imp->m_duplicatedItems.lower_bound("$:")); + m_imp->m_duplicatedItems.erase(m_imp->m_duplicatedItems.lower_bound("$;"), + m_imp->m_duplicatedItems.end()); + + // Clear maps whose id is on the second of map pairs. + + std::map::iterator it; + for (it = m_imp->m_itemHistory.begin(); it != m_imp->m_itemHistory.end();) { + if (it->second.size() >= 2 && it->second[0] == '$' && it->second[1] == ':') + ++it; + else { + std::map::iterator app = it; + app++; + m_imp->m_itemHistory.erase(it); + it = app; + } + } + + std::map::iterator jt; + for (jt = m_imp->m_itemsByImagePointer.begin(); + jt != m_imp->m_itemsByImagePointer.end();) { + if (jt->second.size() >= 2 && jt->second[0] == '$' && jt->second[1] == ':') + ++jt; + else { + std::map::iterator app = jt; + app++; + m_imp->m_itemsByImagePointer.erase(jt); + jt = app; + } + } } //------------------------------------------------------------------------------ -bool TImageCache::isCached(const std::string &id) const -{ - TThread::MutexLocker sl(&m_imp->m_mutex); - return (m_imp->m_uncompressedItems.find(id) != m_imp->m_uncompressedItems.end() || - m_imp->m_compressedItems.find(id) != m_imp->m_compressedItems.end() || - m_imp->m_duplicatedItems.find(id) != m_imp->m_duplicatedItems.end()); +bool TImageCache::isCached(const std::string &id) const { + TThread::MutexLocker sl(&m_imp->m_mutex); + return (m_imp->m_uncompressedItems.find(id) != + m_imp->m_uncompressedItems.end() || + m_imp->m_compressedItems.find(id) != m_imp->m_compressedItems.end() || + m_imp->m_duplicatedItems.find(id) != m_imp->m_duplicatedItems.end()); } //------------------------------------------------------------------------------ #ifdef LEVO -bool TImageCache::getSize(const std::string &id, TDimension &size) const -{ - QMutexLocker sl(&m_imp->m_mutex); - - std::map::iterator it = m_imp->m_uncompressedItems.find(id); - if (it != m_imp->m_uncompressedItems.end()) { - - UncompressedOnMemoryCacheItemP uncompressed = it->second; - assert(uncompressed); - TToonzImageP ti = uncompressed->getImage(); - if (ti) { - size = ti->getSize(); - return true; - } - - TRasterImageP ri = uncompressed->getImage(); - if (ri && ri->getRaster()) { - size = ri->getRaster()->getSize(); - return true; - } - return false; - } - std::map::iterator itc = m_imp->m_compressedItems.find(id); - if (itc == m_imp->m_compressedItems.end()) - return false; - CacheItemP cacheItem = itc->second; - - if (cacheItem->m_imageInfo) { - RasterImageInfo *rimageInfo = dynamic_cast(cacheItem->m_imageInfo); - if (rimageInfo) { - size = rimageInfo->m_size; - return true; - } - ToonzImageInfo *timageInfo = dynamic_cast(cacheItem->m_imageInfo); - if (timageInfo) { - size = timageInfo->m_size; - return true; - } - } - - return false; +bool TImageCache::getSize(const std::string &id, TDimension &size) const { + QMutexLocker sl(&m_imp->m_mutex); + + std::map::iterator it = + m_imp->m_uncompressedItems.find(id); + if (it != m_imp->m_uncompressedItems.end()) { + UncompressedOnMemoryCacheItemP uncompressed = it->second; + assert(uncompressed); + TToonzImageP ti = uncompressed->getImage(); + if (ti) { + size = ti->getSize(); + return true; + } + + TRasterImageP ri = uncompressed->getImage(); + if (ri && ri->getRaster()) { + size = ri->getRaster()->getSize(); + return true; + } + return false; + } + std::map::iterator itc = + m_imp->m_compressedItems.find(id); + if (itc == m_imp->m_compressedItems.end()) return false; + CacheItemP cacheItem = itc->second; + + if (cacheItem->m_imageInfo) { + RasterImageInfo *rimageInfo = + dynamic_cast(cacheItem->m_imageInfo); + if (rimageInfo) { + size = rimageInfo->m_size; + return true; + } + ToonzImageInfo *timageInfo = + dynamic_cast(cacheItem->m_imageInfo); + if (timageInfo) { + size = timageInfo->m_size; + return true; + } + } + + return false; } //------------------------------------------------------------------------------ -bool TImageCache::getSavebox(const std::string &id, TRect &savebox) const -{ - QMutexLocker sl(&m_imp->m_mutex); - - std::map::iterator it = m_imp->m_uncompressedItems.find(id); - if (it != m_imp->m_uncompressedItems.end()) { - - UncompressedOnMemoryCacheItemP uncompressed = it->second; - assert(uncompressed); - - TToonzImageP ti = uncompressed->getImage(); - if (ti) { - savebox = ti->getSavebox(); - return true; - } - TRasterImageP ri = uncompressed->getImage(); - if (ri) { - savebox = ri->getSavebox(); - return true; - } - return false; - } - std::map::iterator itc = m_imp->m_compressedItems.find(id); - if (itc == m_imp->m_compressedItems.end()) - return false; - - CacheItemP cacheItem = itc->second; - - assert(cacheItem->m_imageInfo); - - RasterImageInfo *rimageInfo = dynamic_cast(cacheItem->m_imageInfo); - if (rimageInfo) { - savebox = rimageInfo->m_savebox; - return true; - } -#ifndef TNZCORE_LIGHT - ToonzImageInfo *timageInfo = dynamic_cast(cacheItem->m_imageInfo); - if (timageInfo) { - savebox = timageInfo->m_savebox; - return true; - } -#endif - return false; -} +bool TImageCache::getSavebox(const std::string &id, TRect &savebox) const { + QMutexLocker sl(&m_imp->m_mutex); -//------------------------------------------------------------------------------ + std::map::iterator it = + m_imp->m_uncompressedItems.find(id); + if (it != m_imp->m_uncompressedItems.end()) { + UncompressedOnMemoryCacheItemP uncompressed = it->second; + assert(uncompressed); -bool TImageCache::getDpi(const std::string &id, double &dpiX, double &dpiY) const -{ - QMutexLocker sl(&m_imp->m_mutex); - - std::map::iterator it = m_imp->m_uncompressedItems.find(id); - if (it != m_imp->m_uncompressedItems.end()) { - - UncompressedOnMemoryCacheItemP uncompressed = it->second; - assert(uncompressed); - TToonzImageP ti = uncompressed->getImage(); - if (ti) { - ti->getDpi(dpiX, dpiY); - return true; - } - TRasterImageP ri = uncompressed->getImage(); - if (ri) { - ri->getDpi(dpiX, dpiY); - return true; - } - return false; - } - std::map::iterator itc = m_imp->m_compressedItems.find(id); - if (itc == m_imp->m_compressedItems.end()) - return false; - CacheItemP cacheItem = itc->second; - assert(cacheItem->m_imageInfo); - - RasterImageInfo *rimageInfo = dynamic_cast(cacheItem->m_imageInfo); - if (rimageInfo) { - dpiX = rimageInfo->m_dpix; - dpiY = rimageInfo->m_dpiy; - return true; - } + TToonzImageP ti = uncompressed->getImage(); + if (ti) { + savebox = ti->getSavebox(); + return true; + } + TRasterImageP ri = uncompressed->getImage(); + if (ri) { + savebox = ri->getSavebox(); + return true; + } + return false; + } + std::map::iterator itc = + m_imp->m_compressedItems.find(id); + if (itc == m_imp->m_compressedItems.end()) return false; + + CacheItemP cacheItem = itc->second; + + assert(cacheItem->m_imageInfo); + + RasterImageInfo *rimageInfo = + dynamic_cast(cacheItem->m_imageInfo); + if (rimageInfo) { + savebox = rimageInfo->m_savebox; + return true; + } +#ifndef TNZCORE_LIGHT + ToonzImageInfo *timageInfo = + dynamic_cast(cacheItem->m_imageInfo); + if (timageInfo) { + savebox = timageInfo->m_savebox; + return true; + } +#endif + return false; +} + +//------------------------------------------------------------------------------ + +bool TImageCache::getDpi(const std::string &id, double &dpiX, + double &dpiY) const { + QMutexLocker sl(&m_imp->m_mutex); + + std::map::iterator it = + m_imp->m_uncompressedItems.find(id); + if (it != m_imp->m_uncompressedItems.end()) { + UncompressedOnMemoryCacheItemP uncompressed = it->second; + assert(uncompressed); + TToonzImageP ti = uncompressed->getImage(); + if (ti) { + ti->getDpi(dpiX, dpiY); + return true; + } + TRasterImageP ri = uncompressed->getImage(); + if (ri) { + ri->getDpi(dpiX, dpiY); + return true; + } + return false; + } + std::map::iterator itc = + m_imp->m_compressedItems.find(id); + if (itc == m_imp->m_compressedItems.end()) return false; + CacheItemP cacheItem = itc->second; + assert(cacheItem->m_imageInfo); + + RasterImageInfo *rimageInfo = + dynamic_cast(cacheItem->m_imageInfo); + if (rimageInfo) { + dpiX = rimageInfo->m_dpix; + dpiY = rimageInfo->m_dpiy; + return true; + } #ifndef TNZCORE_LIGHT - ToonzImageInfo *timageInfo = dynamic_cast(cacheItem->m_imageInfo); - if (timageInfo) { - dpiX = timageInfo->m_dpix; - dpiY = timageInfo->m_dpiy; - return true; - } + ToonzImageInfo *timageInfo = + dynamic_cast(cacheItem->m_imageInfo); + if (timageInfo) { + dpiX = timageInfo->m_dpix; + dpiY = timageInfo->m_dpiy; + return true; + } #endif - return false; + return false; } //------------------------------------------------------------------------------ #endif -bool TImageCache::getSubsampling(const std::string &id, int &subs) const -{ - - TThread::MutexLocker sl(&m_imp->m_mutex); +bool TImageCache::getSubsampling(const std::string &id, int &subs) const { + TThread::MutexLocker sl(&m_imp->m_mutex); - std::map::iterator it1; - if ((it1 = m_imp->m_duplicatedItems.find(id)) != m_imp->m_duplicatedItems.end()) { - assert(m_imp->m_duplicatedItems.find(it1->second) == m_imp->m_duplicatedItems.end()); - return getSubsampling(it1->second, subs); - } + std::map::iterator it1; + if ((it1 = m_imp->m_duplicatedItems.find(id)) != + m_imp->m_duplicatedItems.end()) { + assert(m_imp->m_duplicatedItems.find(it1->second) == + m_imp->m_duplicatedItems.end()); + return getSubsampling(it1->second, subs); + } - std::map::iterator it = m_imp->m_uncompressedItems.find(id); - if (it != m_imp->m_uncompressedItems.end()) { - UncompressedOnMemoryCacheItemP uncompressed = it->second; - assert(uncompressed); + std::map::iterator it = + m_imp->m_uncompressedItems.find(id); + if (it != m_imp->m_uncompressedItems.end()) { + UncompressedOnMemoryCacheItemP uncompressed = it->second; + assert(uncompressed); #ifndef TNZCORE_LIGHT - if (TToonzImageP ti = uncompressed->getImage()) { - subs = ti->getSubsampling(); - return true; - } + if (TToonzImageP ti = uncompressed->getImage()) { + subs = ti->getSubsampling(); + return true; + } - else + else #endif - if (TRasterImageP ri = uncompressed->getImage()) { - subs = ri->getSubsampling(); - return true; - } else - return false; - } - std::map::iterator itc = m_imp->m_compressedItems.find(id); - if (itc == m_imp->m_compressedItems.end()) - return false; - CacheItemP cacheItem = itc->second; - assert(cacheItem->m_imageInfo); - if (RasterImageInfo *rimageInfo = dynamic_cast(cacheItem->m_imageInfo)) { - subs = rimageInfo->m_subs; - return true; - } + if (TRasterImageP ri = uncompressed->getImage()) { + subs = ri->getSubsampling(); + return true; + } else + return false; + } + std::map::iterator itc = + m_imp->m_compressedItems.find(id); + if (itc == m_imp->m_compressedItems.end()) return false; + CacheItemP cacheItem = itc->second; + assert(cacheItem->m_imageInfo); + if (RasterImageInfo *rimageInfo = + dynamic_cast(cacheItem->m_imageInfo)) { + subs = rimageInfo->m_subs; + return true; + } #ifndef TNZCORE_LIGHT - else if (ToonzImageInfo *timageInfo = dynamic_cast(cacheItem->m_imageInfo)) { - subs = timageInfo->m_subs; - return true; - } + else if (ToonzImageInfo *timageInfo = + dynamic_cast(cacheItem->m_imageInfo)) { + subs = timageInfo->m_subs; + return true; + } #endif - else - return false; + else + return false; } //------------------------------------------------------------------------------ -bool TImageCache::hasBeenModified(const std::string &id, bool reset) const -{ - TThread::MutexLocker sl(&m_imp->m_mutex); - - std::map::iterator it; - if ((it = m_imp->m_duplicatedItems.find(id)) != m_imp->m_duplicatedItems.end()) { - assert(m_imp->m_duplicatedItems.find(it->second) == m_imp->m_duplicatedItems.end()); - return hasBeenModified(it->second, reset); - } - - TImageP img; - - std::map::iterator itu = m_imp->m_uncompressedItems.find(id); - if (itu != m_imp->m_uncompressedItems.end()) { - if (reset && itu->second->m_modified) { - itu->second->m_modified = false; - return true; - } else - return itu->second->m_modified; - } - return true; //not present in cache==modified (for particle purposes...) +bool TImageCache::hasBeenModified(const std::string &id, bool reset) const { + TThread::MutexLocker sl(&m_imp->m_mutex); + + std::map::iterator it; + if ((it = m_imp->m_duplicatedItems.find(id)) != + m_imp->m_duplicatedItems.end()) { + assert(m_imp->m_duplicatedItems.find(it->second) == + m_imp->m_duplicatedItems.end()); + return hasBeenModified(it->second, reset); + } + + TImageP img; + + std::map::iterator itu = + m_imp->m_uncompressedItems.find(id); + if (itu != m_imp->m_uncompressedItems.end()) { + if (reset && itu->second->m_modified) { + itu->second->m_modified = false; + return true; + } else + return itu->second->m_modified; + } + return true; // not present in cache==modified (for particle purposes...) } //------------------------------------------------------------------------------ -TImageP TImageCache::get(const std::string &id, bool toBeModified) const -{ - return m_imp->get(id, toBeModified); +TImageP TImageCache::get(const std::string &id, bool toBeModified) const { + return m_imp->get(id, toBeModified); } //------------------------------------------------------------------------------ -TImageP TImageCache::Imp::get(const std::string &id, bool toBeModified) -{ - TThread::MutexLocker sl(&m_mutex); - - std::map::const_iterator it; - if ((it = m_duplicatedItems.find(id)) != m_duplicatedItems.end()) { - assert(m_duplicatedItems.find(it->second) == m_duplicatedItems.end()); - return get(it->second, toBeModified); - } - - TImageP img; - - std::map::iterator itu = m_uncompressedItems.find(id); - if (itu != m_uncompressedItems.end()) { - img = itu->second->getImage(); - if (itu->second->m_historyCount != HistoryCount - 1) //significa che l'ultimo get non era sulla stessa immagine, quindi serve aggiornare l'history! - { - assert(m_itemHistory.find(itu->second->m_historyCount) != m_itemHistory.end()); - m_itemHistory.erase(itu->second->m_historyCount); - m_itemHistory[HistoryCount] = id; - itu->second->m_historyCount = HistoryCount; - HistoryCount++; - } - if (toBeModified) { - itu->second->m_modified = true; - std::map::iterator itc = m_compressedItems.find(id); - if (itc != m_compressedItems.end()) - m_compressedItems.erase(itc); - } - return img; - } - - std::map::iterator itc = m_compressedItems.find(id); - if (itc == m_compressedItems.end()) - return 0; - - CacheItemP cacheItem = itc->second; - - img = cacheItem->getImage(); - - CacheItemP uncompressed; - uncompressed = new UncompressedOnMemoryCacheItem(img); - m_uncompressedItems[itc->first] = uncompressed; - m_itemsByImagePointer[getPointer(img)] = itc->first; - - m_itemHistory[HistoryCount] = itc->first; - uncompressed->m_historyCount = HistoryCount; - HistoryCount++; - - if (CompressedOnMemoryCacheItemP(cacheItem)) - //l'immagine compressa non la tengo insieme alla - //uncompressa se e' troppo grande - { - if (10 * cacheItem->getSize() > uncompressed->getSize()) { - m_compressedItems.erase(itc); - itc = m_compressedItems.end(); - } - } else - assert((CompressedOnDiskCacheItemP)cacheItem || (UncompressedOnDiskCacheItemP)cacheItem); //deve essere compressa! - - if (toBeModified && itc != m_compressedItems.end()) { - uncompressed->m_modified = true; - m_compressedItems.erase(itc); - } - - uncompressed->m_cantCompress = toBeModified; - // se la memoria utilizzata e' superiore al massimo consentito, comprime - doCompress(); - - uncompressed->m_cantCompress = false; +TImageP TImageCache::Imp::get(const std::string &id, bool toBeModified) { + TThread::MutexLocker sl(&m_mutex); + + std::map::const_iterator it; + if ((it = m_duplicatedItems.find(id)) != m_duplicatedItems.end()) { + assert(m_duplicatedItems.find(it->second) == m_duplicatedItems.end()); + return get(it->second, toBeModified); + } + + TImageP img; + + std::map::iterator itu = + m_uncompressedItems.find(id); + if (itu != m_uncompressedItems.end()) { + img = itu->second->getImage(); + if (itu->second->m_historyCount != + HistoryCount - 1) // significa che l'ultimo get non era sulla stessa + // immagine, quindi serve aggiornare l'history! + { + assert(m_itemHistory.find(itu->second->m_historyCount) != + m_itemHistory.end()); + m_itemHistory.erase(itu->second->m_historyCount); + m_itemHistory[HistoryCount] = id; + itu->second->m_historyCount = HistoryCount; + HistoryCount++; + } + if (toBeModified) { + itu->second->m_modified = true; + std::map::iterator itc = + m_compressedItems.find(id); + if (itc != m_compressedItems.end()) m_compressedItems.erase(itc); + } + return img; + } + + std::map::iterator itc = m_compressedItems.find(id); + if (itc == m_compressedItems.end()) return 0; + + CacheItemP cacheItem = itc->second; + + img = cacheItem->getImage(); + + CacheItemP uncompressed; + uncompressed = new UncompressedOnMemoryCacheItem(img); + m_uncompressedItems[itc->first] = uncompressed; + m_itemsByImagePointer[getPointer(img)] = itc->first; + + m_itemHistory[HistoryCount] = itc->first; + uncompressed->m_historyCount = HistoryCount; + HistoryCount++; + + if (CompressedOnMemoryCacheItemP(cacheItem)) + // l'immagine compressa non la tengo insieme alla + // uncompressa se e' troppo grande + { + if (10 * cacheItem->getSize() > uncompressed->getSize()) { + m_compressedItems.erase(itc); + itc = m_compressedItems.end(); + } + } else + assert((CompressedOnDiskCacheItemP)cacheItem || + (UncompressedOnDiskCacheItemP)cacheItem); // deve essere compressa! + + if (toBeModified && itc != m_compressedItems.end()) { + uncompressed->m_modified = true; + m_compressedItems.erase(itc); + } + + uncompressed->m_cantCompress = toBeModified; + // se la memoria utilizzata e' superiore al massimo consentito, comprime + doCompress(); + + uncompressed->m_cantCompress = false; //#define DO_MEMCHECK #ifdef DO_MEMCHECK - assert(_CrtCheckMemory()); + assert(_CrtCheckMemory()); #endif - return img; + return img; } //------------------------------------------------------------------------------ -namespace -{ +namespace { -class AccumulateMemUsage -{ +class AccumulateMemUsage { public: - int operator()(int oldValue, std::pair item) - { - return oldValue + item.second->getSize(); - } + int operator()(int oldValue, std::pair item) { + return oldValue + item.second->getSize(); + } }; } -UINT TImageCache::getMemUsage() const -{ - TThread::MutexLocker sl(&m_imp->m_mutex); - - int ret = std::accumulate( - m_imp->m_uncompressedItems.begin(), - m_imp->m_uncompressedItems.end(), - 0, - AccumulateMemUsage()); - - return ret + std::accumulate( - m_imp->m_compressedItems.begin(), - m_imp->m_compressedItems.end(), - 0, - AccumulateMemUsage()); +UINT TImageCache::getMemUsage() const { + TThread::MutexLocker sl(&m_imp->m_mutex); + + int ret = std::accumulate(m_imp->m_uncompressedItems.begin(), + m_imp->m_uncompressedItems.end(), 0, + AccumulateMemUsage()); + + return ret + std::accumulate(m_imp->m_compressedItems.begin(), + m_imp->m_compressedItems.end(), 0, + AccumulateMemUsage()); } //------------------------------------------------------------------------------ -UINT TImageCache::getDiskUsage() const -{ - return 0; -} +UINT TImageCache::getDiskUsage() const { return 0; } //------------------------------------------------------------------------------ -UINT TImageCache::getMemUsage(const std::string &id) const -{ - std::map::iterator it = m_imp->m_uncompressedItems.find(id); - if (it != m_imp->m_uncompressedItems.end()) - return it->second->getSize(); - - it = m_imp->m_compressedItems.find(id); - if (it != m_imp->m_compressedItems.end()) - return it->second->getSize(); - return 0; +UINT TImageCache::getMemUsage(const std::string &id) const { + std::map::iterator it = + m_imp->m_uncompressedItems.find(id); + if (it != m_imp->m_uncompressedItems.end()) return it->second->getSize(); + + it = m_imp->m_compressedItems.find(id); + if (it != m_imp->m_compressedItems.end()) return it->second->getSize(); + return 0; } //------------------------------------------------------------------------------ //! Returns the uncompressed image size (in KB) of the image associated with //! passd id, or 0 if none was found. -UINT TImageCache::getUncompressedMemUsage(const std::string &id) const -{ - std::map::iterator it = m_imp->m_uncompressedItems.find(id); - if (it != m_imp->m_uncompressedItems.end()) - return it->second->getSize(); +UINT TImageCache::getUncompressedMemUsage(const std::string &id) const { + std::map::iterator it = + m_imp->m_uncompressedItems.find(id); + if (it != m_imp->m_uncompressedItems.end()) return it->second->getSize(); - it = m_imp->m_compressedItems.find(id); - if (it != m_imp->m_compressedItems.end()) - return it->second->getSize(); + it = m_imp->m_compressedItems.find(id); + if (it != m_imp->m_compressedItems.end()) return it->second->getSize(); - return 0; + return 0; } //------------------------------------------------------------------------------ /* -int TImageCache::getItemCount() const +int TImageCache::getItemCount() const { return m_imp->m_uncompressedItems.size()+m_imp->m_compressedItems.size(); } */ //------------------------------------------------------------------------------ -UINT TImageCache::getDiskUsage(const std::string &id) const -{ - return 0; -} +UINT TImageCache::getDiskUsage(const std::string &id) const { return 0; } //------------------------------------------------------------------------------ -void TImageCache::dump(std::ostream &os) const -{ - os << "mem: " << getMemUsage() << std::endl; - std::map::iterator it = m_imp->m_uncompressedItems.begin(); - for (; it != m_imp->m_uncompressedItems.end(); ++it) { - os << it->first << std::endl; - } +void TImageCache::dump(std::ostream &os) const { + os << "mem: " << getMemUsage() << std::endl; + std::map::iterator it = + m_imp->m_uncompressedItems.begin(); + for (; it != m_imp->m_uncompressedItems.end(); ++it) { + os << it->first << std::endl; + } } //------------------------------------------------------------------------------ -void TImageCache::outputMap(UINT chunkRequested, std::string filename) -{ - m_imp->outputMap(chunkRequested, filename); +void TImageCache::outputMap(UINT chunkRequested, std::string filename) { + m_imp->outputMap(chunkRequested, filename); } //------------------------------------------------------------------------------ -void TImageCache::Imp::outputMap(UINT chunkRequested, std::string filename) -{ - TThread::MutexLocker sl(&m_mutex); - //#ifdef _DEBUG - //static int Count = 0; - - std::string st = filename /*+toString(Count++)*/ + ".txt"; - TFilePath fp(st); - Tofstream os(fp); - - int umcount1 = 0; - int umcount2 = 0; - int umcount3 = 0; - int cmcount = 0; - int cdcount = 0; - int umcount = 0; - int udcount = 0; - - TUINT64 umsize1 = 0; - TUINT64 umsize2 = 0; - TUINT64 umsize3 = 0; - TUINT64 cmsize = 0; - TUINT64 cdsize = 0; - TUINT64 umsize = 0; - TUINT64 udsize = 0; - - std::map::iterator itu = m_uncompressedItems.begin(); - - for (; itu != m_uncompressedItems.end(); ++itu) { - UncompressedOnMemoryCacheItemP uitem = itu->second; - if (uitem->m_image && hasExternalReferences(uitem->m_image)) { - umcount1++; - umsize1 += (TUINT64)(itu->second->getSize() / 1024.0); - } else if (uitem->m_cantCompress) { - umcount2++; - umsize2 += (TUINT64)(itu->second->getSize() / 1024.0); - } else { - umcount3++; - umsize3 += (TUINT64)(itu->second->getSize() / 1024.0); - } - } - std::map::iterator itc = m_compressedItems.begin(); - for (; itc != m_compressedItems.end(); ++itc) { - CacheItemP boh = itc->second; - CompressedOnMemoryCacheItemP cmitem = itc->second; - CompressedOnDiskCacheItemP cditem = itc->second; - UncompressedOnDiskCacheItemP uditem = itc->second; - if (cmitem) { - cmcount++; - cmsize += cmitem->getSize(); - } else if (cditem) { - cdcount++; - cdsize += cditem->getSize(); - } else { - assert(uditem); - udcount++; - udsize += uditem->getSize(); - } - } - - TUINT64 currPhisMemoryAvail = (TUINT64)(TSystem::getFreeMemorySize(true) / 1024.0); - //TUINT64 currVirtualMemoryAvail = TSystem::getFreeMemorySize(false)/1024.0; - - os << "************************************************************\n"; - - os << "***requested memory: " + std::to_string((int)chunkRequested / 1048576.0) + " MB\n"; - //os<<"*** memory in rasters: " + std::to_string((int)TRaster::getTotalMemoryInKB()/1024.0) + " MB\n"; - //os<<"***virtualmem " + std::to_string((int)currVirtualMemoryAvail) + " MB\n"; - os << "***phismem " + std::to_string((int)currPhisMemoryAvail) + " MB; percent of tot:" + std::to_string((int)((currPhisMemoryAvail * 100) / m_reservedMemory)) + "\n"; - //os<<"***bigmem available" + std::to_string((int)TBigMemoryManager::instance()->getAvailableMemoryinKb()); - os << "***uncompressed NOT compressable(refcount>1) " + std::to_string(umcount1) + " " + std::to_string(umsize1 / 1024.0) + " MB\n"; - os << "***uncompressed NOT compressable(cantCompress) " + std::to_string(umcount2) + " " + std::to_string(umsize2 / 1024.0) + " MB\n"; - os << "***uncompressed compressable " + std::to_string(umcount3) + " " + std::to_string(umsize3 / 1024.0) + " MB\n"; - os << "***compressed on mem " + std::to_string(cmcount) + " " + std::to_string((int)cmsize / 1048576.0) + " MB\n"; - os << "***compressed on disk " + std::to_string(cdcount) + " " + std::to_string((int)cdsize / 1048576.0) + " MB\n"; - os << "***uncompressed on disk " + std::to_string(udcount) + " " + std::to_string((int)udsize / 1048576.0) + " MB\n"; - - //TBigMemoryManager::instance()->printMap(); - - //#endif +void TImageCache::Imp::outputMap(UINT chunkRequested, std::string filename) { + TThread::MutexLocker sl(&m_mutex); + //#ifdef _DEBUG + // static int Count = 0; + + std::string st = filename /*+toString(Count++)*/ + ".txt"; + TFilePath fp(st); + Tofstream os(fp); + + int umcount1 = 0; + int umcount2 = 0; + int umcount3 = 0; + int cmcount = 0; + int cdcount = 0; + int umcount = 0; + int udcount = 0; + + TUINT64 umsize1 = 0; + TUINT64 umsize2 = 0; + TUINT64 umsize3 = 0; + TUINT64 cmsize = 0; + TUINT64 cdsize = 0; + TUINT64 umsize = 0; + TUINT64 udsize = 0; + + std::map::iterator itu = m_uncompressedItems.begin(); + + for (; itu != m_uncompressedItems.end(); ++itu) { + UncompressedOnMemoryCacheItemP uitem = itu->second; + if (uitem->m_image && hasExternalReferences(uitem->m_image)) { + umcount1++; + umsize1 += (TUINT64)(itu->second->getSize() / 1024.0); + } else if (uitem->m_cantCompress) { + umcount2++; + umsize2 += (TUINT64)(itu->second->getSize() / 1024.0); + } else { + umcount3++; + umsize3 += (TUINT64)(itu->second->getSize() / 1024.0); + } + } + std::map::iterator itc = m_compressedItems.begin(); + for (; itc != m_compressedItems.end(); ++itc) { + CacheItemP boh = itc->second; + CompressedOnMemoryCacheItemP cmitem = itc->second; + CompressedOnDiskCacheItemP cditem = itc->second; + UncompressedOnDiskCacheItemP uditem = itc->second; + if (cmitem) { + cmcount++; + cmsize += cmitem->getSize(); + } else if (cditem) { + cdcount++; + cdsize += cditem->getSize(); + } else { + assert(uditem); + udcount++; + udsize += uditem->getSize(); + } + } + + TUINT64 currPhisMemoryAvail = + (TUINT64)(TSystem::getFreeMemorySize(true) / 1024.0); + // TUINT64 currVirtualMemoryAvail = TSystem::getFreeMemorySize(false)/1024.0; + + os << "************************************************************\n"; + + os << "***requested memory: " + + std::to_string((int)chunkRequested / 1048576.0) + " MB\n"; + // os<<"*** memory in rasters: " + + // std::to_string((int)TRaster::getTotalMemoryInKB()/1024.0) + " MB\n"; + // os<<"***virtualmem " + std::to_string((int)currVirtualMemoryAvail) + " + // MB\n"; + os << "***phismem " + std::to_string((int)currPhisMemoryAvail) + + " MB; percent of tot:" + + std::to_string( + (int)((currPhisMemoryAvail * 100) / m_reservedMemory)) + + "\n"; + // os<<"***bigmem available" + + // std::to_string((int)TBigMemoryManager::instance()->getAvailableMemoryinKb()); + os << "***uncompressed NOT compressable(refcount>1) " + + std::to_string(umcount1) + " " + std::to_string(umsize1 / 1024.0) + + " MB\n"; + os << "***uncompressed NOT compressable(cantCompress) " + + std::to_string(umcount2) + " " + std::to_string(umsize2 / 1024.0) + + " MB\n"; + os << "***uncompressed compressable " + std::to_string(umcount3) + " " + + std::to_string(umsize3 / 1024.0) + " MB\n"; + os << "***compressed on mem " + std::to_string(cmcount) + " " + + std::to_string((int)cmsize / 1048576.0) + " MB\n"; + os << "***compressed on disk " + std::to_string(cdcount) + " " + + std::to_string((int)cdsize / 1048576.0) + " MB\n"; + os << "***uncompressed on disk " + std::to_string(udcount) + " " + + std::to_string((int)udsize / 1048576.0) + " MB\n"; + + // TBigMemoryManager::instance()->printMap(); + + //#endif } //------------------------------------------------------------------------------ -void TImageCache::compress(const std::string &id) -{ - m_imp->doCompress(id); -} +void TImageCache::compress(const std::string &id) { m_imp->doCompress(id); } //------------------------------------------------------------------------------ #ifndef TNZCORE_LIGHT -void TImageCache::add(const QString &id, const TImageP &img, bool overwrite) -{ - if (!isEnabled()) - return; - m_imp->add(id.toStdString(), img, overwrite); +void TImageCache::add(const QString &id, const TImageP &img, bool overwrite) { + if (!isEnabled()) return; + m_imp->add(id.toStdString(), img, overwrite); } //------------------------------------------------------------------------------ -void TImageCache::remove(const QString &id) -{ - m_imp->remove(id.toStdString()); -} +void TImageCache::remove(const QString &id) { m_imp->remove(id.toStdString()); } //------------------------------------------------------------------------------ -TImageP TImageCache::get(const QString &id, bool toBeModified) const -{ - return get(id.toStdString(), toBeModified); +TImageP TImageCache::get(const QString &id, bool toBeModified) const { + return get(id.toStdString(), toBeModified); } #endif @@ -2013,35 +1974,28 @@ TImageP TImageCache::get(const QString &id, bool toBeModified) const DEFINE_CLASS_CODE(TCachedImage, 103) TCachedImage::TCachedImage() - : TSmartObject(m_classCode), m_ref(TImageCache::instance()->getUniqueId()) -{ -} + : TSmartObject(m_classCode) + , m_ref(TImageCache::instance()->getUniqueId()) {} //------------------------------------------------------------------------------ TCachedImage::TCachedImage(const TImageP &img) - : TSmartObject(m_classCode), m_ref(TImageCache::instance()->getUniqueId()) -{ - setImage(img); + : TSmartObject(m_classCode), m_ref(TImageCache::instance()->getUniqueId()) { + setImage(img); } //------------------------------------------------------------------------------ -TCachedImage::~TCachedImage() -{ - TImageCache::instance()->remove(m_ref); -} +TCachedImage::~TCachedImage() { TImageCache::instance()->remove(m_ref); } //------------------------------------------------------------------------------ -void TCachedImage::setImage(const TImageP &img, bool overwrite) -{ - TImageCache::instance()->add(m_ref, img, overwrite); +void TCachedImage::setImage(const TImageP &img, bool overwrite) { + TImageCache::instance()->add(m_ref, img, overwrite); } //------------------------------------------------------------------------------ -TImageP TCachedImage::image(bool toBeModified) -{ - return TImageCache::instance()->get(m_ref, toBeModified); +TImageP TCachedImage::image(bool toBeModified) { + return TImageCache::instance()->get(m_ref, toBeModified); } diff --git a/toonz/sources/common/tcolor/tcolorfunctions.cpp b/toonz/sources/common/tcolor/tcolorfunctions.cpp index 75e1c74..95f7112 100644 --- a/toonz/sources/common/tcolor/tcolorfunctions.cpp +++ b/toonz/sources/common/tcolor/tcolorfunctions.cpp @@ -3,84 +3,75 @@ #include "tcolorfunctions.h" #include "tpixelutils.h" -TPixel32 TColorFader::operator()(const TPixel32 &color) const -{ - TPixel32 ret = blend(color, m_color, m_fade); - return ret; +TPixel32 TColorFader::operator()(const TPixel32 &color) const { + TPixel32 ret = blend(color, m_color, m_fade); + return ret; } -bool TColorFader::getParameters(Parameters &p) const -{ - p.m_mR = p.m_mG = p.m_mB = p.m_mM = (1 - m_fade); - p.m_cR = m_fade * m_color.r; - p.m_cG = m_fade * m_color.g; - p.m_cB = m_fade * m_color.b; - p.m_cM = m_fade * m_color.m; - return true; +bool TColorFader::getParameters(Parameters &p) const { + p.m_mR = p.m_mG = p.m_mB = p.m_mM = (1 - m_fade); + p.m_cR = m_fade * m_color.r; + p.m_cG = m_fade * m_color.g; + p.m_cB = m_fade * m_color.b; + p.m_cM = m_fade * m_color.m; + return true; } //--------------------------------------- -TGenericColorFunction::TGenericColorFunction(const double m[4], const double c[4]) -{ - memcpy(m_m, m, 4 * sizeof(double)); - memcpy(m_c, c, 4 * sizeof(double)); +TGenericColorFunction::TGenericColorFunction(const double m[4], + const double c[4]) { + memcpy(m_m, m, 4 * sizeof(double)); + memcpy(m_c, c, 4 * sizeof(double)); } //--------------------------------------- -TPixel32 TGenericColorFunction::operator()(const TPixel32 &color) const -{ - return TPixel32(tcrop(m_m[0] * color.r + m_c[0], 0.0, 255.0), - tcrop(m_m[1] * color.g + m_c[1], 0.0, 255.0), - tcrop(m_m[2] * color.b + m_c[2], 0.0, 255.0), - tcrop(m_m[3] * color.m + m_c[3], 0.0, 255.0)); +TPixel32 TGenericColorFunction::operator()(const TPixel32 &color) const { + return TPixel32(tcrop(m_m[0] * color.r + m_c[0], 0.0, 255.0), + tcrop(m_m[1] * color.g + m_c[1], 0.0, 255.0), + tcrop(m_m[2] * color.b + m_c[2], 0.0, 255.0), + tcrop(m_m[3] * color.m + m_c[3], 0.0, 255.0)); } //--------------------------------------- -bool TGenericColorFunction::getParameters(Parameters &p) const -{ - p.m_mR = m_m[0], p.m_mG = m_m[1], p.m_mB = m_m[2], p.m_mM = m_m[3]; - p.m_cR = m_c[0], p.m_cG = m_c[1], p.m_cB = m_c[2], p.m_cM = m_c[3]; +bool TGenericColorFunction::getParameters(Parameters &p) const { + p.m_mR = m_m[0], p.m_mG = m_m[1], p.m_mB = m_m[2], p.m_mM = m_m[3]; + p.m_cR = m_c[0], p.m_cG = m_c[1], p.m_cB = m_c[2], p.m_cM = m_c[3]; - return true; + return true; } //--------------------------------------- -TPixel32 TTranspFader::operator()(const TPixel32 &color) const -{ - return TPixel32(color.r, color.g, color.b, m_transp * color.m); +TPixel32 TTranspFader::operator()(const TPixel32 &color) const { + return TPixel32(color.r, color.g, color.b, m_transp * color.m); } //--------------------------------------- -bool TTranspFader::getParameters(Parameters &p) const -{ - assert(false); - return true; +bool TTranspFader::getParameters(Parameters &p) const { + assert(false); + return true; } //---------------------------------- -TPixel32 TOnionFader::operator()(const TPixel32 &color) const -{ - if (color.m == 0) - return color; +TPixel32 TOnionFader::operator()(const TPixel32 &color) const { + if (color.m == 0) return color; - TPixel32 blendColor = blend(color, m_color, m_fade); - blendColor.m = 180; - return blendColor; + TPixel32 blendColor = blend(color, m_color, m_fade); + blendColor.m = 180; + return blendColor; } -bool TOnionFader::getParameters(Parameters &p) const -{ - p.m_mR = p.m_mG = p.m_mB = (1 - m_fade); - p.m_mM = 1; - p.m_cR = m_fade * m_color.r; - p.m_cG = m_fade * m_color.g; - p.m_cB = m_fade * m_color.b; - p.m_cM = m_color.m; - return true; +bool TOnionFader::getParameters(Parameters &p) const { + p.m_mR = p.m_mG = p.m_mB = (1 - m_fade); + p.m_mM = 1; + p.m_cR = m_fade * m_color.r; + p.m_cG = m_fade * m_color.g; + p.m_cB = m_fade * m_color.b; + p.m_cM = m_color.m; + return true; } diff --git a/toonz/sources/common/tcolor/tcolorvalue.cpp b/toonz/sources/common/tcolor/tcolorvalue.cpp index 5d4f794..4e84009 100644 --- a/toonz/sources/common/tcolor/tcolorvalue.cpp +++ b/toonz/sources/common/tcolor/tcolorvalue.cpp @@ -4,182 +4,172 @@ //=================================================================== -void TColorValue::getHsv(int &ih, int &is, int &iv) const -{ - double max, min; - double delta; - double r, g, b; - double v, s, h; - r = m_r; - g = m_g; - b = m_b; - assert(0 <= r && r <= 1); - assert(0 <= g && g <= 1); - assert(0 <= b && b <= 1); - - max = std::max({r, g, b}); - min = std::min({r, g, b}); - - v = max; - - if (max != 0) - s = (max - min) / max; - else - s = 0; - - if (s == 0) - h = 0; - else { - delta = max - min; - - if (r == max) - h = (g - b) / delta; - else if (g == max) - h = 2 + (b - r) / delta; - else if (b == max) - h = 4 + (r - g) / delta; - h = h * 60; - if (h < 0) - h += 360; - } - assert(0 <= h && h <= 360); - assert(0 <= s && s <= 1); - assert(0 <= v && v <= 1); - ih = (int)h; - is = (int)(s * 100); - iv = (int)(v * 100); +void TColorValue::getHsv(int &ih, int &is, int &iv) const { + double max, min; + double delta; + double r, g, b; + double v, s, h; + r = m_r; + g = m_g; + b = m_b; + assert(0 <= r && r <= 1); + assert(0 <= g && g <= 1); + assert(0 <= b && b <= 1); + + max = std::max({r, g, b}); + min = std::min({r, g, b}); + + v = max; + + if (max != 0) + s = (max - min) / max; + else + s = 0; + + if (s == 0) + h = 0; + else { + delta = max - min; + + if (r == max) + h = (g - b) / delta; + else if (g == max) + h = 2 + (b - r) / delta; + else if (b == max) + h = 4 + (r - g) / delta; + h = h * 60; + if (h < 0) h += 360; + } + assert(0 <= h && h <= 360); + assert(0 <= s && s <= 1); + assert(0 <= v && v <= 1); + ih = (int)h; + is = (int)(s * 100); + iv = (int)(v * 100); } //=================================================================== -void TColorValue::getHls(double &h, double &l, double &s) const -{ - double max, min; - double delta; - - max = std::max({m_r, m_g, m_b}); - min = std::min({m_r, m_g, m_b}); - - l = (max + min) / 2; - - if (max == min) { - s = 0; - h = 0; - } else { - if (l <= 0.5) - s = (max - min) / (max + min); - else - s = (max - min) / (2 - max - min); - - delta = max - min; - if (m_r == max) - h = (m_g - m_b) / delta; - else if (m_g == max) - h = 2 + (m_b - m_r) / delta; - else if (m_b == max) - h = 4 + (m_r - m_g) / delta; - - h = h * 60; - if (h < 0) - h += 360; - } +void TColorValue::getHls(double &h, double &l, double &s) const { + double max, min; + double delta; + + max = std::max({m_r, m_g, m_b}); + min = std::min({m_r, m_g, m_b}); + + l = (max + min) / 2; + + if (max == min) { + s = 0; + h = 0; + } else { + if (l <= 0.5) + s = (max - min) / (max + min); + else + s = (max - min) / (2 - max - min); + + delta = max - min; + if (m_r == max) + h = (m_g - m_b) / delta; + else if (m_g == max) + h = 2 + (m_b - m_r) / delta; + else if (m_b == max) + h = 4 + (m_r - m_g) / delta; + + h = h * 60; + if (h < 0) h += 360; + } } //=================================================================== -void TColorValue::setHsv(int h, int s, int v) -{ - int i; - double p, q, t, f; - double hue, sat, value; - - hue = h; - sat = 0.01 * s; - value = 0.01 * v; - - assert(0 <= hue && hue <= 360); - assert(0 <= sat && sat <= 1); - assert(0 <= value && value <= 1); - - if (sat == 0) { - m_r = m_g = m_b = value; - } else { - if (hue == 360) - hue = 0; - - hue = hue / 60; - i = (int)hue; - f = hue - i; - p = tcrop(value * (1 - sat), 0., 1.); - q = tcrop(value * (1 - (sat * f)), 0., 1.); - t = tcrop(value * (1 - (sat * (1 - f))), 0., 1.); - - switch (i) { - case 0: - m_r = value; - m_g = t; - m_b = p; - break; - case 1: - m_r = q; - m_g = value; - m_b = p; - break; - case 2: - m_r = p; - m_g = value; - m_b = t; - break; - case 3: - m_r = p; - m_g = q; - m_b = value; - break; - case 4: - m_r = t; - m_g = p; - m_b = value; - break; - case 5: - m_r = value; - m_g = p; - m_b = q; - break; - } - } +void TColorValue::setHsv(int h, int s, int v) { + int i; + double p, q, t, f; + double hue, sat, value; + + hue = h; + sat = 0.01 * s; + value = 0.01 * v; + + assert(0 <= hue && hue <= 360); + assert(0 <= sat && sat <= 1); + assert(0 <= value && value <= 1); + + if (sat == 0) { + m_r = m_g = m_b = value; + } else { + if (hue == 360) hue = 0; + + hue = hue / 60; + i = (int)hue; + f = hue - i; + p = tcrop(value * (1 - sat), 0., 1.); + q = tcrop(value * (1 - (sat * f)), 0., 1.); + t = tcrop(value * (1 - (sat * (1 - f))), 0., 1.); + + switch (i) { + case 0: + m_r = value; + m_g = t; + m_b = p; + break; + case 1: + m_r = q; + m_g = value; + m_b = p; + break; + case 2: + m_r = p; + m_g = value; + m_b = t; + break; + case 3: + m_r = p; + m_g = q; + m_b = value; + break; + case 4: + m_r = t; + m_g = p; + m_b = value; + break; + case 5: + m_r = value; + m_g = p; + m_b = q; + break; + } + } } //=================================================================== -void TColorValue::getRgb(int &r, int &g, int &b) const -{ - r = (int)(m_r * 255 + 0.5); - g = (int)(m_g * 255 + 0.5); - b = (int)(m_b * 255 + 0.5); +void TColorValue::getRgb(int &r, int &g, int &b) const { + r = (int)(m_r * 255 + 0.5); + g = (int)(m_g * 255 + 0.5); + b = (int)(m_b * 255 + 0.5); } //=================================================================== -TPixel32 TColorValue::getPixel() const -{ - int r, g, b; - getRgb(r, g, b); - return TPixel32(r, g, b, (int)(m_m * 255.0 + 0.5)); +TPixel32 TColorValue::getPixel() const { + int r, g, b; + getRgb(r, g, b); + return TPixel32(r, g, b, (int)(m_m * 255.0 + 0.5)); } //=================================================================== -void TColorValue::setRgb(int r, int g, int b) -{ - m_r = r / 255.0; - m_g = g / 255.0; - m_b = b / 255.0; +void TColorValue::setRgb(int r, int g, int b) { + m_r = r / 255.0; + m_g = g / 255.0; + m_b = b / 255.0; } //=================================================================== -void TColorValue::setPixel(const TPixel32 &src) -{ - setRgb(src.r, src.g, src.b); - m_m = src.m / 255.0; +void TColorValue::setPixel(const TPixel32 &src) { + setRgb(src.r, src.g, src.b); + m_m = src.m / 255.0; } diff --git a/toonz/sources/common/tcolor/tpixel.cpp b/toonz/sources/common/tcolor/tpixel.cpp index c2f9a4e..30a97de 100644 --- a/toonz/sources/common/tcolor/tpixel.cpp +++ b/toonz/sources/common/tcolor/tpixel.cpp @@ -5,8 +5,8 @@ const int TPixelRGBM32::maxChannelValue = 0xff; const int TPixelRGBM64::maxChannelValue = 0xffff; -const int TPixelGR8::maxChannelValue = 0xff; -const int TPixelGR16::maxChannelValue = 0xffff; +const int TPixelGR8::maxChannelValue = 0xff; +const int TPixelGR16::maxChannelValue = 0xffff; const TPixelRGBM32 TPixelRGBM32::Red(maxChannelValue, 0, 0); const TPixelRGBM32 TPixelRGBM32::Green(0, maxChannelValue, 0); @@ -14,7 +14,8 @@ const TPixelRGBM32 TPixelRGBM32::Blue(0, 0, maxChannelValue); const TPixelRGBM32 TPixelRGBM32::Yellow(maxChannelValue, maxChannelValue, 0); const TPixelRGBM32 TPixelRGBM32::Cyan(0, maxChannelValue, maxChannelValue); const TPixelRGBM32 TPixelRGBM32::Magenta(maxChannelValue, 0, maxChannelValue); -const TPixelRGBM32 TPixelRGBM32::White(maxChannelValue, maxChannelValue, maxChannelValue); +const TPixelRGBM32 TPixelRGBM32::White(maxChannelValue, maxChannelValue, + maxChannelValue); const TPixelRGBM32 TPixelRGBM32::Black(0, 0, 0); const TPixelRGBM32 TPixelRGBM32::Transparent(0, 0, 0, 0); //--------------------------------------------------- @@ -25,7 +26,8 @@ const TPixelRGBM64 TPixelRGBM64::Blue(0, 0, maxChannelValue); const TPixelRGBM64 TPixelRGBM64::Yellow(maxChannelValue, maxChannelValue, 0); const TPixelRGBM64 TPixelRGBM64::Cyan(0, maxChannelValue, maxChannelValue); const TPixelRGBM64 TPixelRGBM64::Magenta(maxChannelValue, 0, maxChannelValue); -const TPixelRGBM64 TPixelRGBM64::White(maxChannelValue, maxChannelValue, maxChannelValue); +const TPixelRGBM64 TPixelRGBM64::White(maxChannelValue, maxChannelValue, + maxChannelValue); const TPixelRGBM64 TPixelRGBM64::Black(0, 0, 0); const TPixelRGBM64 TPixelRGBM64::Transparent(0, 0, 0, 0); //--------------------------------------------------- @@ -45,25 +47,19 @@ const TPixelGR8 TPixelGR8::Black(0); const TPixelGR16 TPixelGR16::White(maxChannelValue); const TPixelGR16 TPixelGR16::Black(0); -std::ostream &operator<<(std::ostream &out, const TPixel32 &pixel) -{ - return out << "PixRGBM32(" - << (int)pixel.r << ", " << (int)pixel.g << ", " - << (int)pixel.b << ", " << (int)pixel.m << ")"; +std::ostream &operator<<(std::ostream &out, const TPixel32 &pixel) { + return out << "PixRGBM32(" << (int)pixel.r << ", " << (int)pixel.g << ", " + << (int)pixel.b << ", " << (int)pixel.m << ")"; } -std::ostream &operator<<(std::ostream &out, const TPixel64 &pixel) -{ - return out - << "PixRGBM64(" << pixel.r << ", " << pixel.g - << ", " << pixel.b << ", " << pixel.m << ")"; +std::ostream &operator<<(std::ostream &out, const TPixel64 &pixel) { + return out << "PixRGBM64(" << pixel.r << ", " << pixel.g << ", " << pixel.b + << ", " << pixel.m << ")"; } -std::ostream &operator<<(std::ostream &out, const TPixelD &pixel) -{ - return out - << "PixD(" << pixel.r << ", " << pixel.g << ", " - << pixel.b << ", " << pixel.m << ")"; +std::ostream &operator<<(std::ostream &out, const TPixelD &pixel) { + return out << "PixD(" << pixel.r << ", " << pixel.g << ", " << pixel.b << ", " + << pixel.m << ")"; } //============================================================================= @@ -103,30 +99,24 @@ TPixelD DVAPI TPixelD::from(const TPixelGR16 &pix) */ //----------------------------------------------------------------------------- -//TPixelGR8 TPixelGR8::from(const TPixelD &pix) +// TPixelGR8 TPixelGR8::from(const TPixelD &pix) //{ // return from(TPixel32::from(pix)); //} //----------------------------------------------------------------------------- -TPixelGR8 DVAPI TPixelGR8::from(const TPixel32 &pix) -{ - return TPixelGR8((((UINT)(pix.r) * 19594 + - (UINT)(pix.g) * 38472 + - (UINT)(pix.b) * 7470 + - (UINT)(1 << 15)) >> - 16)); +TPixelGR8 DVAPI TPixelGR8::from(const TPixel32 &pix) { + return TPixelGR8((((UINT)(pix.r) * 19594 + (UINT)(pix.g) * 38472 + + (UINT)(pix.b) * 7470 + (UINT)(1 << 15)) >> + 16)); } //----------------------------------------------------------------------------- -TPixelGR16 DVAPI TPixelGR16::from(const TPixel64 &pix) -{ - return TPixelGR16((((UINT)(pix.r) * 19594 + - (UINT)(pix.g) * 38472 + - (UINT)(pix.b) * 7470 + - (UINT)(1 << 15)) >> - 16)); +TPixelGR16 DVAPI TPixelGR16::from(const TPixel64 &pix) { + return TPixelGR16((((UINT)(pix.r) * 19594 + (UINT)(pix.g) * 38472 + + (UINT)(pix.b) * 7470 + (UINT)(1 << 15)) >> + 16)); } //----------------------------------------------------------------------------- diff --git a/toonz/sources/common/tcolor/tpixelutils.cpp b/toonz/sources/common/tcolor/tpixelutils.cpp index 4ab8e89..e04ea8e 100644 --- a/toonz/sources/common/tcolor/tpixelutils.cpp +++ b/toonz/sources/common/tcolor/tpixelutils.cpp @@ -2,398 +2,350 @@ #include "tpixelutils.h" -// /*!This method is used to produce current palette colors for cm24 Toonz images.*/ -// static inline TPixelRGBM32 combine(const TPixelRGBM32 &a, const TPixelRGBM32 &b) { +// /*!This method is used to produce current palette colors for cm24 Toonz +// images.*/ +// static inline TPixelRGBM32 combine(const TPixelRGBM32 &a, const TPixelRGBM32 +// &b) { // return (*(TUINT32*)&a + *(TUINT32*)&b); // } //----------------------------------------------------------------------------- -namespace -{ -int byteCrop(int v) -{ - return (unsigned int)v <= 255 ? v : v > 255 ? 255 : 0; -} -int wordCrop(int v) -{ - return (unsigned int)v <= 65535 ? v : v > 65535 ? 65535 : 0; -} -} // namespace - -//----------------------------------------------------------------------------- - -void hsv2rgb(TPixel32 &dstRgb, int srcHsv[3], int maxHsv) -{ - int i; - double p, q, t, f; - double hue, sat, value; - assert(maxHsv); - hue = ((double)srcHsv[0] / maxHsv) * 360.; - sat = (double)srcHsv[1] / maxHsv; - value = (double)srcHsv[2] / maxHsv; - - if (hue > 360) - hue -= 360; - if (hue < 0) - hue += 360; - if (sat < 0) - sat = 0; - if (sat > 1) - sat = 1; - if (value < 0) - value = 0; - if (value > 1) - value = 1; - if (sat == 0) { - dstRgb.r = dstRgb.g = dstRgb.b = tcrop((int)(value * 255), 0, 255); - } else { - if (hue == 360) - hue = 0; - - hue = hue / 60; - i = (int)hue; - f = hue - i; - p = value * (1 - sat); - q = value * (1 - (sat * f)); - t = value * (1 - (sat * (1 - f))); - - if (i == 0) { - dstRgb.r = tcrop((int)(value * 255), 0, 255); - dstRgb.g = tcrop((int)(t * 255), 0, 255); - dstRgb.b = tcrop((int)(p * 255), 0, 255); - } else if (i == 1) { - - dstRgb.r = tcrop((int)(q * 255), 0, 255); - dstRgb.g = tcrop((int)(value * 255), 0, 255); - dstRgb.b = tcrop((int)(p * 255), 0, 255); - } else if (i == 2) { - dstRgb.r = tcrop((int)(p * 255), 0, 255); - dstRgb.g = tcrop((int)(value * 255), 0, 255); - dstRgb.b = tcrop((int)(t * 255), 0, 255); - } else if (i == 3) { - dstRgb.r = tcrop((int)(p * 255), 0, 255); - dstRgb.g = tcrop((int)(q * 255), 0, 255); - dstRgb.b = tcrop((int)(value * 255), 0, 255); - } else if (i == 4) { - dstRgb.r = tcrop((int)(t * 255), 0, 255); - dstRgb.g = tcrop((int)(p * 255), 0, 255); - dstRgb.b = tcrop((int)(value * 255), 0, 255); - } else if (i == 5) { - dstRgb.r = tcrop((int)(value * 255), 0, 255); - dstRgb.g = tcrop((int)(p * 255), 0, 255); - dstRgb.b = tcrop((int)(q * 255), 0, 255); - } - } - dstRgb.m = 255; //matte -} -//----------------------------------------------------------------------------- - -void HSV2RGB(double hue, double sat, double value, - double *red, double *green, double *blue) -{ - int i; - double p, q, t, f; - - // if (hue > 360 || hue < 0) - // hue=0; - if (hue > 360) - hue -= 360; - if (hue < 0) - hue += 360; - if (sat < 0) - sat = 0; - if (sat > 1) - sat = 1; - if (value < 0) - value = 0; - if (value > 1) - value = 1; - if (sat == 0) { - *red = value; - *green = value; - *blue = value; - } else { - if (hue == 360) - hue = 0; - - hue = hue / 60; - i = (int)hue; - f = hue - i; - p = value * (1 - sat); - q = value * (1 - (sat * f)); - t = value * (1 - (sat * (1 - f))); - - switch (i) { - case 0: - *red = value; - *green = t; - *blue = p; - break; - case 1: - *red = q; - *green = value; - *blue = p; - break; - case 2: - *red = p; - *green = value; - *blue = t; - break; - case 3: - *red = p; - *green = q; - *blue = value; - break; - case 4: - *red = t; - *green = p; - *blue = value; - break; - case 5: - *red = value; - *green = p; - *blue = q; - break; - } - } -} - -void RGB2HSV(double r, double g, double b, - double *h, double *s, double *v) -{ - double max, min; - double delta; - - max = std::max({r, g, b}); - min = std::min({r, g, b}); - - *v = max; - - if (max != 0) - *s = (max - min) / max; - else - *s = 0; - - if (*s == 0) - *h = 0; - else { - delta = max - min; - - if (r == max) - *h = (g - b) / delta; - else if (g == max) - *h = 2 + (b - r) / delta; - else if (b == max) - *h = 4 + (r - g) / delta; - *h = *h * 60; - if (*h < 0) - *h += 360; - } -} -void rgb2hsv(int dstHsv[3], const TPixel32 &srcRgb, int maxHsv) -{ - double max, min; - double delta; - double r, g, b; - double v, s, h; - r = srcRgb.r / 255.; - g = srcRgb.g / 255.; - b = srcRgb.b / 255.; - - max = std::max({r, g, b}); - min = std::min({r, g, b}); - - v = max; - - if (max != 0) - s = (max - min) / max; - else - s = 0; - - if (s == 0) - h = 0; - else { - delta = max - min; - - if (r == max) - h = (g - b) / delta; - else if (g == max) - h = 2 + (b - r) / delta; - else if (b == max) - h = 4 + (r - g) / delta; - h = h * 60; - if (h < 0) - h += 360; - } - - dstHsv[0] = tcrop((int)((h / 360.) * maxHsv), 0, maxHsv); - dstHsv[1] = tcrop((int)(s * maxHsv), 0, maxHsv); - dstHsv[2] = tcrop((int)(v * maxHsv), 0, maxHsv); +namespace { +int byteCrop(int v) { return (unsigned int)v <= 255 ? v : v > 255 ? 255 : 0; } +int wordCrop(int v) { + return (unsigned int)v <= 65535 ? v : v > 65535 ? 65535 : 0; +} +} // namespace + +//----------------------------------------------------------------------------- + +void hsv2rgb(TPixel32 &dstRgb, int srcHsv[3], int maxHsv) { + int i; + double p, q, t, f; + double hue, sat, value; + assert(maxHsv); + hue = ((double)srcHsv[0] / maxHsv) * 360.; + sat = (double)srcHsv[1] / maxHsv; + value = (double)srcHsv[2] / maxHsv; + + if (hue > 360) hue -= 360; + if (hue < 0) hue += 360; + if (sat < 0) sat = 0; + if (sat > 1) sat = 1; + if (value < 0) value = 0; + if (value > 1) value = 1; + if (sat == 0) { + dstRgb.r = dstRgb.g = dstRgb.b = tcrop((int)(value * 255), 0, 255); + } else { + if (hue == 360) hue = 0; + + hue = hue / 60; + i = (int)hue; + f = hue - i; + p = value * (1 - sat); + q = value * (1 - (sat * f)); + t = value * (1 - (sat * (1 - f))); + + if (i == 0) { + dstRgb.r = tcrop((int)(value * 255), 0, 255); + dstRgb.g = tcrop((int)(t * 255), 0, 255); + dstRgb.b = tcrop((int)(p * 255), 0, 255); + } else if (i == 1) { + dstRgb.r = tcrop((int)(q * 255), 0, 255); + dstRgb.g = tcrop((int)(value * 255), 0, 255); + dstRgb.b = tcrop((int)(p * 255), 0, 255); + } else if (i == 2) { + dstRgb.r = tcrop((int)(p * 255), 0, 255); + dstRgb.g = tcrop((int)(value * 255), 0, 255); + dstRgb.b = tcrop((int)(t * 255), 0, 255); + } else if (i == 3) { + dstRgb.r = tcrop((int)(p * 255), 0, 255); + dstRgb.g = tcrop((int)(q * 255), 0, 255); + dstRgb.b = tcrop((int)(value * 255), 0, 255); + } else if (i == 4) { + dstRgb.r = tcrop((int)(t * 255), 0, 255); + dstRgb.g = tcrop((int)(p * 255), 0, 255); + dstRgb.b = tcrop((int)(value * 255), 0, 255); + } else if (i == 5) { + dstRgb.r = tcrop((int)(value * 255), 0, 255); + dstRgb.g = tcrop((int)(p * 255), 0, 255); + dstRgb.b = tcrop((int)(q * 255), 0, 255); + } + } + dstRgb.m = 255; // matte +} +//----------------------------------------------------------------------------- + +void HSV2RGB(double hue, double sat, double value, double *red, double *green, + double *blue) { + int i; + double p, q, t, f; + + // if (hue > 360 || hue < 0) + // hue=0; + if (hue > 360) hue -= 360; + if (hue < 0) hue += 360; + if (sat < 0) sat = 0; + if (sat > 1) sat = 1; + if (value < 0) value = 0; + if (value > 1) value = 1; + if (sat == 0) { + *red = value; + *green = value; + *blue = value; + } else { + if (hue == 360) hue = 0; + + hue = hue / 60; + i = (int)hue; + f = hue - i; + p = value * (1 - sat); + q = value * (1 - (sat * f)); + t = value * (1 - (sat * (1 - f))); + + switch (i) { + case 0: + *red = value; + *green = t; + *blue = p; + break; + case 1: + *red = q; + *green = value; + *blue = p; + break; + case 2: + *red = p; + *green = value; + *blue = t; + break; + case 3: + *red = p; + *green = q; + *blue = value; + break; + case 4: + *red = t; + *green = p; + *blue = value; + break; + case 5: + *red = value; + *green = p; + *blue = q; + break; + } + } +} + +void RGB2HSV(double r, double g, double b, double *h, double *s, double *v) { + double max, min; + double delta; + + max = std::max({r, g, b}); + min = std::min({r, g, b}); + + *v = max; + + if (max != 0) + *s = (max - min) / max; + else + *s = 0; + + if (*s == 0) + *h = 0; + else { + delta = max - min; + + if (r == max) + *h = (g - b) / delta; + else if (g == max) + *h = 2 + (b - r) / delta; + else if (b == max) + *h = 4 + (r - g) / delta; + *h = *h * 60; + if (*h < 0) *h += 360; + } +} +void rgb2hsv(int dstHsv[3], const TPixel32 &srcRgb, int maxHsv) { + double max, min; + double delta; + double r, g, b; + double v, s, h; + r = srcRgb.r / 255.; + g = srcRgb.g / 255.; + b = srcRgb.b / 255.; + + max = std::max({r, g, b}); + min = std::min({r, g, b}); + + v = max; + + if (max != 0) + s = (max - min) / max; + else + s = 0; + + if (s == 0) + h = 0; + else { + delta = max - min; + + if (r == max) + h = (g - b) / delta; + else if (g == max) + h = 2 + (b - r) / delta; + else if (b == max) + h = 4 + (r - g) / delta; + h = h * 60; + if (h < 0) h += 360; + } + + dstHsv[0] = tcrop((int)((h / 360.) * maxHsv), 0, maxHsv); + dstHsv[1] = tcrop((int)(s * maxHsv), 0, maxHsv); + dstHsv[2] = tcrop((int)(v * maxHsv), 0, maxHsv); } /*! Conversion between RGB and HLS colorspace */ -namespace -{ -//helper function -inline double HLSValue(double n1, double n2, double h) -{ - if (h > 360) - h -= 360; - else if (h < 0) - h += 360; - if (h < 60) - return n1 + (n2 - n1) * h / 60; - else if (h < 180) - return n2; - else if (h < 240) - return n1 + (n2 - n1) * (240 - h) / 60; - else - return n1; -} -} -void HLS2RGB(double h, double l, double s, - double *r, double *g, double *b) -{ - if (s == 0) { - *r = *g = *b = l; - return; - } +namespace { +// helper function +inline double HLSValue(double n1, double n2, double h) { + if (h > 360) + h -= 360; + else if (h < 0) + h += 360; + if (h < 60) + return n1 + (n2 - n1) * h / 60; + else if (h < 180) + return n2; + else if (h < 240) + return n1 + (n2 - n1) * (240 - h) / 60; + else + return n1; +} +} +void HLS2RGB(double h, double l, double s, double *r, double *g, double *b) { + if (s == 0) { + *r = *g = *b = l; + return; + } - double m1, m2; + double m1, m2; - if (l < 0.5) - m2 = l * (1 + s); - else - m2 = l + s + l * s; - m1 = 2 * l - m2; + if (l < 0.5) + m2 = l * (1 + s); + else + m2 = l + s + l * s; + m1 = 2 * l - m2; - *r = HLSValue(m1, m2, h + 120); - *g = HLSValue(m1, m2, h); - *b = HLSValue(m1, m2, h - 120); + *r = HLSValue(m1, m2, h + 120); + *g = HLSValue(m1, m2, h); + *b = HLSValue(m1, m2, h - 120); } -void rgb2hls(double r, double g, double b, - double *h, double *l, double *s) +void rgb2hls(double r, double g, double b, double *h, double *l, double *s) { - double max, min; - double delta; + double max, min; + double delta; - max = std::max({r, g, b}); - min = std::min({r, g, b}); + max = std::max({r, g, b}); + min = std::min({r, g, b}); - *l = (max + min) / 2; + *l = (max + min) / 2; - if (max == min) { - *s = 0; - *h = 0; - } else { - if (*l <= 0.5) - *s = (max - min) / (max + min); - else - *s = (max - min) / (2 - max - min); + if (max == min) { + *s = 0; + *h = 0; + } else { + if (*l <= 0.5) + *s = (max - min) / (max + min); + else + *s = (max - min) / (2 - max - min); - delta = max - min; - if (r == max) - *h = (g - b) / delta; - else if (g == max) - *h = 2 + (b - r) / delta; - else if (b == max) - *h = 4 + (r - g) / delta; + delta = max - min; + if (r == max) + *h = (g - b) / delta; + else if (g == max) + *h = 2 + (b - r) / delta; + else if (b == max) + *h = 4 + (r - g) / delta; - *h = *h * 60; - if (*h < 0) - *h += 360; - } + *h = *h * 60; + if (*h < 0) *h += 360; + } } //----------------------------------------------------------------------------- -TPixel32 toPixel32(const TPixel64 &src) -{ - return TPixelRGBM32( - byteFromUshort(src.r), - byteFromUshort(src.g), - byteFromUshort(src.b), - byteFromUshort(src.m)); +TPixel32 toPixel32(const TPixel64 &src) { + return TPixelRGBM32(byteFromUshort(src.r), byteFromUshort(src.g), + byteFromUshort(src.b), byteFromUshort(src.m)); } //----------------------------------------------------------------------------- -TPixel32 toPixel32(const TPixelD &src) -{ - const double factor = 255.0; - return TPixel32( - byteCrop(tround(src.r * factor)), - byteCrop(tround(src.g * factor)), - byteCrop(tround(src.b * factor)), - byteCrop(tround(src.m * factor))); +TPixel32 toPixel32(const TPixelD &src) { + const double factor = 255.0; + return TPixel32( + byteCrop(tround(src.r * factor)), byteCrop(tround(src.g * factor)), + byteCrop(tround(src.b * factor)), byteCrop(tround(src.m * factor))); } //----------------------------------------------------------------------------- -TPixel32 toPixel32(const TPixelGR8 &src) -{ - return TPixel32(src.value, src.value, src.value); +TPixel32 toPixel32(const TPixelGR8 &src) { + return TPixel32(src.value, src.value, src.value); } //----------------------------------------------------------------------------- -TPixel64 toPixel64(const TPixel32 &src) -{ - return TPixelRGBM64( - ushortFromByte(src.r), - ushortFromByte(src.g), - ushortFromByte(src.b), - ushortFromByte(src.m)); +TPixel64 toPixel64(const TPixel32 &src) { + return TPixelRGBM64(ushortFromByte(src.r), ushortFromByte(src.g), + ushortFromByte(src.b), ushortFromByte(src.m)); } //----------------------------------------------------------------------------- -TPixel64 toPixel64(const TPixelD &src) -{ - const double factor = 65535.0; - return TPixel64( - wordCrop(tround(src.r * factor)), - wordCrop(tround(src.g * factor)), - wordCrop(tround(src.b * factor)), - wordCrop(tround(src.m * factor))); +TPixel64 toPixel64(const TPixelD &src) { + const double factor = 65535.0; + return TPixel64( + wordCrop(tround(src.r * factor)), wordCrop(tround(src.g * factor)), + wordCrop(tround(src.b * factor)), wordCrop(tround(src.m * factor))); } //----------------------------------------------------------------------------- -TPixel64 toPixel64(const TPixelGR8 &src) -{ - int v = ushortFromByte(src.value); - return TPixel64(v, v, v); +TPixel64 toPixel64(const TPixelGR8 &src) { + int v = ushortFromByte(src.value); + return TPixel64(v, v, v); } //----------------------------------------------------------------------------- -TPixelD toPixelD(const TPixel32 &src) -{ - const double factor = 1.0 / 255.0; - return TPixelD(factor * src.r, factor * src.g, factor * src.b, factor * src.m); +TPixelD toPixelD(const TPixel32 &src) { + const double factor = 1.0 / 255.0; + return TPixelD(factor * src.r, factor * src.g, factor * src.b, + factor * src.m); } //----------------------------------------------------------------------------- -TPixelD toPixelD(const TPixel64 &src) -{ - const double factor = 1.0 / 65535.0; - return TPixelD(factor * src.r, factor * src.g, factor * src.b, factor * src.m); +TPixelD toPixelD(const TPixel64 &src) { + const double factor = 1.0 / 65535.0; + return TPixelD(factor * src.r, factor * src.g, factor * src.b, + factor * src.m); } //----------------------------------------------------------------------------- -TPixelD toPixelD(const TPixelGR8 &src) -{ - const double v = (double)src.value / 255.0; - return TPixelD(v, v, v); +TPixelD toPixelD(const TPixelGR8 &src) { + const double v = (double)src.value / 255.0; + return TPixelD(v, v, v); } //----------------------------------------------------------------------------- @@ -407,276 +359,247 @@ TPixelD toPixelD(const TPixelGR8 &src) //----------------------------------------------------------------------------- /*!toonz color-map, 16 bits 7+5+4 bits (paint, ink, tone)*/ -class DVAPI TPixelCM16 -{ // 754 - static const int maxChannelValue; +class DVAPI TPixelCM16 { // 754 + static const int maxChannelValue; public: - USHORT value; + USHORT value; - TPixelCM16(int v = 0) : value(v){}; - TPixelCM16(int ink, int paint, int tone) : value(tone | ink << 9 | paint << 4){}; - TPixelCM16(const TPixelCM16 &pix) : value(pix.value){}; + TPixelCM16(int v = 0) : value(v){}; + TPixelCM16(int ink, int paint, int tone) + : value(tone | ink << 9 | paint << 4){}; + TPixelCM16(const TPixelCM16 &pix) : value(pix.value){}; - inline bool operator==(const TPixelCM16 &p) const { return value == p.value; }; + inline bool operator==(const TPixelCM16 &p) const { + return value == p.value; + }; - int getInkId() { return value >> 9; }; - int getPaintId() { return (value >> 4) & 0x1F; }; - int getToneId() { return value & 0xF; }; + int getInkId() { return value >> 9; }; + int getPaintId() { return (value >> 4) & 0x1F; }; + int getToneId() { return value & 0xF; }; - static TPixelCM16 pureInk(int ink) { return TPixelCM16(ink, 0, 0); }; - static TPixelCM16 purePaint(int paint) { return TPixelCM16(0, paint, 255); }; + static TPixelCM16 pureInk(int ink) { return TPixelCM16(ink, 0, 0); }; + static TPixelCM16 purePaint(int paint) { return TPixelCM16(0, paint, 255); }; }; //----------------------------------------------------------------------------- /*!cmapped, 16 bits, standard SGI 256-color colormap */ -class DVAPI TPixelCM16S8 -{ - static const int maxChannelValue; +class DVAPI TPixelCM16S8 { + static const int maxChannelValue; public: - USHORT value; - TPixelCM16S8(int v = 0) : value(v){}; + USHORT value; + TPixelCM16S8(int v = 0) : value(v){}; }; //----------------------------------------------------------------------------- /*cmapped, 16 bits, standard SGI+Toonz 4096-color colormap */ -class DVAPI TPixelCM16S12 -{ - static const int maxChannelValue; +class DVAPI TPixelCM16S12 { + static const int maxChannelValue; public: - USHORT value; - TPixelCM16S12(int v = 0) : value(v){}; + USHORT value; + TPixelCM16S12(int v = 0) : value(v){}; }; //----------------------------------------------------------------------------- /*!Toonz color-map, 8+8+8 bits (col, pen, tone) + 8 msb bits extra*/ -class DVAPI TPixelCM24 -{ - static const int maxChannelValue; +class DVAPI TPixelCM24 { + static const int maxChannelValue; public: - /* serve m_value come membro? vincenzo */ - TUINT32 m_value; - UCHAR m_ink, m_paint, m_tone; + /* serve m_value come membro? vincenzo */ + TUINT32 m_value; + UCHAR m_ink, m_paint, m_tone; + + TPixelCM24(int v = 0) + : m_ink((v >> 8) & 0xff), m_paint((v >> 16) & 0xff), m_tone(v & 0xff){}; + TPixelCM24(int ink, int paint, int tone) + : m_value(0), m_ink(ink), m_paint(paint), m_tone(tone){}; + TPixelCM24(const TPixelCM24 &pix) + : m_value(pix.m_value) + , m_ink(pix.m_ink) + , m_paint(pix.m_paint) + , m_tone(pix.m_tone){}; + + inline bool operator==(const TPixelCM24 &p) const { + return m_paint == p.m_paint && m_ink == p.m_ink && m_tone == p.m_tone; + }; + // rivedere + int getPaintIdx() { return m_paint << 16 | m_tone; }; + int getInkIdx() { return m_ink << 16 | m_tone; }; + // int getTone () {return m_tone;}; m_tone e' pubblico! + + // static inline TPixelRGBM from(const TPixelCM24 &pix); + + static TPixelCM24 pureInk(int ink) { return TPixelCM24(ink, 0, 0); }; + static TPixelCM24 purePaint(int paint) { return TPixelCM24(0, paint, 255); }; +}; +//----------------------------------------------------------------------------- - TPixelCM24(int v = 0) : m_ink((v >> 8) & 0xff), m_paint((v >> 16) & 0xff), m_tone(v & 0xff){}; - TPixelCM24(int ink, int paint, int tone) : m_value(0), m_ink(ink), m_paint(paint), m_tone(tone){}; - TPixelCM24(const TPixelCM24 &pix) : m_value(pix.m_value), m_ink(pix.m_ink), m_paint(pix.m_paint), m_tone(pix.m_tone){}; +//! Toonz5.0 color-map, 12+12+8 bits (ink,paint,tone) +class DVAPI TPixelCM32 { +public: + TUINT32 m_value; - inline bool operator==(const TPixelCM24 &p) const { return m_paint == p.m_paint && m_ink == p.m_ink && m_tone == p.m_tone; }; - //rivedere - int getPaintIdx() { return m_paint << 16 | m_tone; }; - int getInkIdx() { return m_ink << 16 | m_tone; }; - // int getTone () {return m_tone;}; m_tone e' pubblico! + TPixelCM32(TUINT32 v = 0) : m_value{}; + TPixelCM32(int ink, int paint, int tone) + : m_value(ink << 20 | paint << 8 | tone) { + assert(0 <= ink && ink < 4096); + assert(0 <= paint && paint < 4096); + assert(0 <= tone && tone < 256); + }; + TPixelCM32(const TPixelCM32 &pix) : m_value(pix.m_value){}; - //static inline TPixelRGBM from(const TPixelCM24 &pix); + inline bool operator==(const TPixelCM32 &p) const { + return m_value == p.m_value; + }; - static TPixelCM24 pureInk(int ink) { return TPixelCM24(ink, 0, 0); }; - static TPixelCM24 purePaint(int paint) { return TPixelCM24(0, paint, 255); }; -}; -//----------------------------------------------------------------------------- + inline bool operator<(const TPixelCM32 &p) const { + return m_value < p.m_value; + }; -//!Toonz5.0 color-map, 12+12+8 bits (ink,paint,tone) -class DVAPI TPixelCM32 -{ + int getPaint() const { return m_paint >> 16 | m_tone; }; + int getInk() const { return m_ink << 16 | m_tone; }; + int getTone() const { return m_tone; }; -public: - TUINT32 m_value; - - TPixelCM32(TUINT32 v = 0) : m_value{}; - TPixelCM32(int ink, int paint, int tone) - : m_value(ink << 20 | paint << 8 | tone) - { - assert(0 <= ink && ink < 4096); - assert(0 <= paint && paint < 4096); - assert(0 <= tone && tone < 256); - }; - TPixelCM32(const TPixelCM32 &pix) - : m_value(pix.m_value){}; - - inline bool operator==(const TPixelCM32 &p) const - { - return m_value == p.m_value; - }; - - inline bool operator<(const TPixelCM32 &p) const - { - return m_value < p.m_value; - }; - - int getPaint() const { return m_paint >> 16 | m_tone; }; - int getInk() const { return m_ink << 16 | m_tone; }; - int getTone() const { return m_tone; }; - - //static inline TPixelRGBM from(const TPixelCM24 &pix); - - static TPixelCM24 pureInk(int ink) { return TPixelCM24(ink, 0, 0); }; - static TPixelCM24 purePaint(int paint) { return TPixelCM24(0, paint, 255); }; + // static inline TPixelRGBM from(const TPixelCM24 &pix); + + static TPixelCM24 pureInk(int ink) { return TPixelCM24(ink, 0, 0); }; + static TPixelCM24 purePaint(int paint) { return TPixelCM24(0, paint, 255); }; }; //----------------------------------------------------------------------------- /*!RGB 5+6+5 bits, red most significant */ -class DVAPI TPixelRGB565 -{ +class DVAPI TPixelRGB565 { public: - TUINT32 r : 5; - TUINT32 g : 6; - TUINT32 b : 5; - TPixelRGB565(int rr, int gg, int bb) : r(rr), g(gg), b(bb) - { - assert(0 <= rr && rr < (1 << 5)); - assert(0 <= gg && gg < (1 << 6)); - assert(0 <= bb && bb < (1 << 5)); - }; - inline bool operator==(const TPixelRGB565 &p) const - { - return r == p.r && g == p.g && b == p.b; - }; - inline bool operator<(const TPixelRGB565 &p) const - { - return r < p.r || r == p.r && (g < p.g || g == p.g && (b < p.b)); - }; - - //!Converts TPixelCM8 into TPixelRGB565 - static inline TPixelRGB565 from(const TPixelCM8 &pix); - //!Returns itself - static inline TPixelRGB565 from(const TPixelRGB565 &pix) { return pix; }; - //!Converts TPixelRGBM32 into TPixelRGB565 - static inline TPixelRGB565 from(const TPixelRGBM32 &pix); - //!Converts TPixelRGBM64 into TPixelRGB565 - static inline TPixelRGB565 from(const TPixelRGBM64 &pix); - //!Converts TPixelGR8 into TPixelRGB565 - static inline TPixelRGB565 from(const TPixelGR8 &pix); - //!Converts TPixelGR16 into TPixelRGB565 - static inline TPixelRGB565 from(const TPixelGR16 &pix); - /* - static const TPixelRGB565 Red; - static const TPixelRGB565 Green; - static const TPixelRGB565 Blue; - static const TPixelRGB565 White; - static const TPixelRGB565 Black; + TUINT32 r : 5; + TUINT32 g : 6; + TUINT32 b : 5; + TPixelRGB565(int rr, int gg, int bb) : r(rr), g(gg), b(bb) { + assert(0 <= rr && rr < (1 << 5)); + assert(0 <= gg && gg < (1 << 6)); + assert(0 <= bb && bb < (1 << 5)); + }; + inline bool operator==(const TPixelRGB565 &p) const { + return r == p.r && g == p.g && b == p.b; + }; + inline bool operator<(const TPixelRGB565 &p) const { + return r < p.r || r == p.r && (g < p.g || g == p.g && (b < p.b)); + }; + + //! Converts TPixelCM8 into TPixelRGB565 + static inline TPixelRGB565 from(const TPixelCM8 &pix); + //! Returns itself + static inline TPixelRGB565 from(const TPixelRGB565 &pix) { return pix; }; + //! Converts TPixelRGBM32 into TPixelRGB565 + static inline TPixelRGB565 from(const TPixelRGBM32 &pix); + //! Converts TPixelRGBM64 into TPixelRGB565 + static inline TPixelRGB565 from(const TPixelRGBM64 &pix); + //! Converts TPixelGR8 into TPixelRGB565 + static inline TPixelRGB565 from(const TPixelGR8 &pix); + //! Converts TPixelGR16 into TPixelRGB565 + static inline TPixelRGB565 from(const TPixelGR16 &pix); + /* +static const TPixelRGB565 Red; +static const TPixelRGB565 Green; +static const TPixelRGB565 Blue; +static const TPixelRGB565 White; +static const TPixelRGB565 Black; */ }; //----------------------------------------------------------------------------- -TPixelRGBM32 DVAPI TPixelRGBM32::from(const TPixelCM8 &pix) -{ - return TPixelRGBM32(pix.value, pix.value, pix.value); +TPixelRGBM32 DVAPI TPixelRGBM32::from(const TPixelCM8 &pix) { + return TPixelRGBM32(pix.value, pix.value, pix.value); } //----------------------------------------------------------------------------- -TPixelRGBM64 DVAPI TPixelRGBM64::from(const TPixelRGBM32 &pix) -{ - return TPixelRGBM64( - ushortFromByte(pix.r), - ushortFromByte(pix.g), - ushortFromByte(pix.b), - ushortFromByte(pix.m)); +TPixelRGBM64 DVAPI TPixelRGBM64::from(const TPixelRGBM32 &pix) { + return TPixelRGBM64(ushortFromByte(pix.r), ushortFromByte(pix.g), + ushortFromByte(pix.b), ushortFromByte(pix.m)); } //----------------------------------------------------------------------------- -TPixelRGBM32 DVAPI TPixelRGBM32::from(const TPixelRGBM64 &pix) -{ - return TPixelRGBM32( - byteFromUshort(pix.r), - byteFromUshort(pix.g), - byteFromUshort(pix.b), - byteFromUshort(pix.m)); +TPixelRGBM32 DVAPI TPixelRGBM32::from(const TPixelRGBM64 &pix) { + return TPixelRGBM32(byteFromUshort(pix.r), byteFromUshort(pix.g), + byteFromUshort(pix.b), byteFromUshort(pix.m)); } //----------------------------------------------------------------------------- -TPixelRGBM32 DVAPI TPixelRGBM32::from(const TPixelGR8 &pix) -{ - return TPixelRGBM32(pix.value, pix.value, pix.value, maxChannelValue); +TPixelRGBM32 DVAPI TPixelRGBM32::from(const TPixelGR8 &pix) { + return TPixelRGBM32(pix.value, pix.value, pix.value, maxChannelValue); } //----------------------------------------------------------------------------- -TPixelRGBM32 DVAPI TPixelRGBM32::from(const TPixelGR16 &pix) -{ - UCHAR value = byteFromUshort(pix.value); - return TPixelRGBM32(value, value, value, maxChannelValue); +TPixelRGBM32 DVAPI TPixelRGBM32::from(const TPixelGR16 &pix) { + UCHAR value = byteFromUshort(pix.value); + return TPixelRGBM32(value, value, value, maxChannelValue); } -TPixelD DVAPI TPixelD::from(const TPixelCM8 &pix) -{ - double v = (double)pix.value * (1.0 / 255.0); - return TPixelD(v, v, v, v); +TPixelD DVAPI TPixelD::from(const TPixelCM8 &pix) { + double v = (double)pix.value * (1.0 / 255.0); + return TPixelD(v, v, v, v); } -TPixelD DVAPI TPixelD::from(const TPixelGR8 &pix) -{ - double v = (double)pix.value * (1.0 / 255.0); - return TPixelD(v, v, v, v); +TPixelD DVAPI TPixelD::from(const TPixelGR8 &pix) { + double v = (double)pix.value * (1.0 / 255.0); + return TPixelD(v, v, v, v); } -TPixelD DVAPI TPixelD::from(const TPixelRGBM32 &pix) -{ - const double k = 1.0 / 255.0; - return TPixelD(k * pix.r, k * pix.g, k * pix.b, k * pix.m); +TPixelD DVAPI TPixelD::from(const TPixelRGBM32 &pix) { + const double k = 1.0 / 255.0; + return TPixelD(k * pix.r, k * pix.g, k * pix.b, k * pix.m); } -TPixelD DVAPI TPixelD::from(const TPixelRGBM64 &pix) -{ - const double k = 1.0 / 65535.0; - return TPixelD(k * pix.r, k * pix.g, k * pix.b, k * pix.m); +TPixelD DVAPI TPixelD::from(const TPixelRGBM64 &pix) { + const double k = 1.0 / 65535.0; + return TPixelD(k * pix.r, k * pix.g, k * pix.b, k * pix.m); } -TPixelD DVAPI TPixelD::from(const TPixelGR16 &pix) -{ - double v = (double)pix.value * (1.0 / 65535.0); - return TPixelD(v, v, v, v); +TPixelD DVAPI TPixelD::from(const TPixelGR16 &pix) { + double v = (double)pix.value * (1.0 / 65535.0); + return TPixelD(v, v, v, v); } -TPixel32 DVAPI TPixel32::from(const TPixelD &pix) -{ - const int max = 255; - return TPixel32( - tcrop((int)(pix.r * max + .5), 0, max), - tcrop((int)(pix.g * max + .5), 0, max), - tcrop((int)(pix.b * max + .5), 0, max), - tcrop((int)(pix.m * max + .5), 0, max)); +TPixel32 DVAPI TPixel32::from(const TPixelD &pix) { + const int max = 255; + return TPixel32(tcrop((int)(pix.r * max + .5), 0, max), + tcrop((int)(pix.g * max + .5), 0, max), + tcrop((int)(pix.b * max + .5), 0, max), + tcrop((int)(pix.m * max + .5), 0, max)); } -TPixel64 DVAPI TPixel64::from(const TPixelD &pix) -{ - const int max = 65535; - return TPixel64( - tcrop((int)(pix.r * max + .5), 0, max), - tcrop((int)(pix.g * max + .5), 0, max), - tcrop((int)(pix.b * max + .5), 0, max), - tcrop((int)(pix.m * max + .5), 0, max)); +TPixel64 DVAPI TPixel64::from(const TPixelD &pix) { + const int max = 65535; + return TPixel64(tcrop((int)(pix.r * max + .5), 0, max), + tcrop((int)(pix.g * max + .5), 0, max), + tcrop((int)(pix.b * max + .5), 0, max), + tcrop((int)(pix.m * max + .5), 0, max)); } -//TPixelGR8 TPixelGR8::from(const TPixelD &pix) +// TPixelGR8 TPixelGR8::from(const TPixelD &pix) //{ // return from(TPixel32::from(pix)); //} -TPixelGR8 DVAPI TPixelGR8::from(const TPixel32 &pix) -{ - return TPixelGR8((((UINT)(pix.r) * 19594 + - (UINT)(pix.g) * 38472 + - (UINT)(pix.b) * 7470 + - (UINT)(1 << 15)) >> - 16)); +TPixelGR8 DVAPI TPixelGR8::from(const TPixel32 &pix) { + return TPixelGR8((((UINT)(pix.r) * 19594 + (UINT)(pix.g) * 38472 + + (UINT)(pix.b) * 7470 + (UINT)(1 << 15)) >> + 16)); } //----------------------------------------------------------------------------- -TPixelGR16 DVAPI TPixelGR16::from(const TPixel64 &pix) -{ - return TPixelGR16((((UINT)(pix.r) * 19594 + - (UINT)(pix.g) * 38472 + - (UINT)(pix.b) * 7470 + - (UINT)(1 << 15)) >> - 16)); +TPixelGR16 DVAPI TPixelGR16::from(const TPixel64 &pix) { + return TPixelGR16((((UINT)(pix.r) * 19594 + (UINT)(pix.g) * 38472 + + (UINT)(pix.b) * 7470 + (UINT)(1 << 15)) >> + 16)); } //----------------------------------------------------------------------------- @@ -691,12 +614,14 @@ DVAPI ostream &operator<<(ostream &out, const TPixelCM8 &pixel); TPixel64 inline TPixel32::to64() const { - return TPixel64(ushortFromByte(r), ushortFromByte(g), ushortFromByte(b),ushortFromByte(m)); + return TPixel64(ushortFromByte(r), ushortFromByte(g), +ushortFromByte(b),ushortFromByte(m)); }; TPixel32 inline TPixel64::to32() const { - return TPixel32(byteFromUshort(r), byteFromUshort(g), byteFromUshort(b), byteFromUshort(m)); + return TPixel32(byteFromUshort(r), byteFromUshort(g), byteFromUshort(b), +byteFromUshort(m)); }; */ diff --git a/toonz/sources/common/tcolor/tspectrum.cpp b/toonz/sources/common/tcolor/tspectrum.cpp index e6a6152..cbf41ca 100644 --- a/toonz/sources/common/tcolor/tspectrum.cpp +++ b/toonz/sources/common/tcolor/tspectrum.cpp @@ -6,15 +6,12 @@ //------------------------------------------------------------------- -DVAPI TSpectrumT convert(const TSpectrumT &s) -{ - std::vector keys; - for (int i = 0; i < s.getKeyCount(); i++) { - TSpectrumT::Key key = s.getKey(i); - TSpectrum64::ColorKey key64( - key.first, - toPixel64(key.second)); - keys.push_back(key64); - } - return TSpectrumT(keys.size(), &keys[0]); +DVAPI TSpectrumT convert(const TSpectrumT &s) { + std::vector keys; + for (int i = 0; i < s.getKeyCount(); i++) { + TSpectrumT::Key key = s.getKey(i); + TSpectrum64::ColorKey key64(key.first, toPixel64(key.second)); + keys.push_back(key64); + } + return TSpectrumT(keys.size(), &keys[0]); } diff --git a/toonz/sources/common/tcontenthistory.cpp b/toonz/sources/common/tcontenthistory.cpp index b4ad776..6eada27 100644 --- a/toonz/sources/common/tcontenthistory.cpp +++ b/toonz/sources/common/tcontenthistory.cpp @@ -27,30 +27,24 @@ using namespace std; //------------------------------------------------------- TContentHistory::TContentHistory(bool isLevel) - : m_isLevel(isLevel), m_frozenHistory() -{ -} + : m_isLevel(isLevel), m_frozenHistory() {} //------------------------------------------------------- -TContentHistory::~TContentHistory() -{ -} +TContentHistory::~TContentHistory() {} //------------------------------------------------------- -TContentHistory *TContentHistory::clone() const -{ - TContentHistory *history = new TContentHistory(m_isLevel); - history->deserialize(serialize()); - return history; +TContentHistory *TContentHistory::clone() const { + TContentHistory *history = new TContentHistory(m_isLevel); + history->deserialize(serialize()); + return history; } //------------------------------------------------------- -void TContentHistory::deserialize(const QString ¤tHistory) -{ - m_frozenHistory = currentHistory; +void TContentHistory::deserialize(const QString ¤tHistory) { + m_frozenHistory = currentHistory; } /* @@ -67,247 +61,241 @@ for (i=1; i= count) - res.truncate(count); - else - res += QString(count - str.size(), ' '); - return res; +inline QString blanks(const QString &str, int count = 15) { + QString res = str; + if (res.size() >= count) + res.truncate(count); + else + res += QString(count - str.size(), ' '); + return res; } //-------------------------------------------------------------------- -inline QString getStr(const TFrameId &id) -{ - if (id.getLetter() != 0) - return QString::number(id.getNumber()) + id.getLetter(); - else - return QString::number(id.getNumber()); +inline QString getStr(const TFrameId &id) { + if (id.getLetter() != 0) + return QString::number(id.getNumber()) + id.getLetter(); + else + return QString::number(id.getNumber()); } //-------------------------------------------------------------------- const QString Fmt = "dd MMM yy hh:mm"; -QString getLine(int counter, const QDateTime &date, const set &frames) -{ - static QString user; - static QString machine; - if (user == "") { - QStringList list = QProcess::systemEnvironment(); - int j; - for (j = 0; j < list.size(); j++) { - QString value = list.at(j); - if (value.startsWith("USERNAME=")) - user = blanks(value.right(value.size() - 9)); - else if (value.startsWith("COMPUTERNAME=")) - machine = blanks(value.right(value.size() - 13)); - } - } - - if (frames.empty()) - return "| #" + blanks(QString::number(counter), 4) + blanks(date.toString(Fmt), 20) + blanks(machine, 12) + user + " |"; - - QString framesStr; - - set::const_iterator it = frames.begin(); - TFrameId first, last; - while (it != frames.end()) { - first = last = *it; - ++it; - while (it != frames.end() && - ((*it).getNumber() == last.getNumber() || // 1a, 1b.... - (*it).getNumber() == last.getNumber() + 1)) { - assert(*it > last); - last = *it, ++it; - } - framesStr += getStr(first) + ((first != last) ? "-" + getStr(last) : ""); - if (it != frames.end()) - framesStr += ", "; - } - - return "| #" + blanks(QString::number(counter), 4) + blanks(date.toString(Fmt), 20) + blanks(machine, 12) + user + blanks(framesStr, 20) + " |"; +QString getLine(int counter, const QDateTime &date, + const set &frames) { + static QString user; + static QString machine; + if (user == "") { + QStringList list = QProcess::systemEnvironment(); + int j; + for (j = 0; j < list.size(); j++) { + QString value = list.at(j); + if (value.startsWith("USERNAME=")) + user = blanks(value.right(value.size() - 9)); + else if (value.startsWith("COMPUTERNAME=")) + machine = blanks(value.right(value.size() - 13)); + } + } + + if (frames.empty()) + return "| #" + blanks(QString::number(counter), 4) + + blanks(date.toString(Fmt), 20) + blanks(machine, 12) + user + " |"; + + QString framesStr; + + set::const_iterator it = frames.begin(); + TFrameId first, last; + while (it != frames.end()) { + first = last = *it; + ++it; + while (it != frames.end() && + ((*it).getNumber() == last.getNumber() || // 1a, 1b.... + (*it).getNumber() == last.getNumber() + 1)) { + assert(*it > last); + last = *it, ++it; + } + framesStr += getStr(first) + ((first != last) ? "-" + getStr(last) : ""); + if (it != frames.end()) framesStr += ", "; + } + + return "| #" + blanks(QString::number(counter), 4) + + blanks(date.toString(Fmt), 20) + blanks(machine, 12) + user + + blanks(framesStr, 20) + " |"; } //-------------------------------------------------------------------- -int getCurrentCount(const QString &str) -{ - if (str == "") - return 0; +int getCurrentCount(const QString &str) { + if (str == "") return 0; - int from = str.lastIndexOf('#') + 1; - assert(from != -1); + int from = str.lastIndexOf('#') + 1; + assert(from != -1); - int to = str.indexOf(" ", from) - 1; - assert(to != -1); - assert(from <= to); + int to = str.indexOf(" ", from) - 1; + assert(to != -1); + assert(from <= to); - return (str.mid(from, to - from + 1)).toInt(); + return (str.mid(from, to - from + 1)).toInt(); } //-------------------------------------------------------------------- -const QString TContentHistory::currentToString() const -{ - if (m_records.empty()) - return ""; - - int counter = getCurrentCount(m_frozenHistory); - - if (!m_isLevel) { - assert(m_records.size() == 1); - return getLine(++counter, m_records.begin()->second, set()); - } - - QString out; - std::multimap dateSorted; - std::map::const_iterator it; - for (it = m_records.begin(); it != m_records.end(); ++it) - dateSorted.insert(pair(it->second, it->first)); - - std::multimap::const_iterator it1 = dateSorted.begin(); - QDateTime currDate = it1->first; - - while (it1 != dateSorted.end()) { - set frames; - while (it1 != dateSorted.end() && currDate == it1->first) { - frames.insert(it1->second); - ++it1; - } - assert(!frames.empty()); - out += getLine(++counter, currDate, frames); - if (it1 != dateSorted.end()) - currDate = it1->first; - } - - return out; +const QString TContentHistory::currentToString() const { + if (m_records.empty()) return ""; + + int counter = getCurrentCount(m_frozenHistory); + + if (!m_isLevel) { + assert(m_records.size() == 1); + return getLine(++counter, m_records.begin()->second, set()); + } + + QString out; + std::multimap dateSorted; + std::map::const_iterator it; + for (it = m_records.begin(); it != m_records.end(); ++it) + dateSorted.insert(pair(it->second, it->first)); + + std::multimap::const_iterator it1 = dateSorted.begin(); + QDateTime currDate = it1->first; + + while (it1 != dateSorted.end()) { + set frames; + while (it1 != dateSorted.end() && currDate == it1->first) { + frames.insert(it1->second); + ++it1; + } + assert(!frames.empty()); + out += getLine(++counter, currDate, frames); + if (it1 != dateSorted.end()) currDate = it1->first; + } + + return out; } //-------------------------------------------------------------------- -const QString TContentHistory::serialize() const -{ - const QString currentHistory = currentToString(); - - if (m_frozenHistory != "") - return m_frozenHistory + currentHistory; - else if (currentHistory != "") { - if (m_isLevel) - return "| # DATE: Time: MACHINE: USER: FRAMES MODIFIED: |" + currentHistory; - else - return "| # DATE: Time: MACHINE: USER: |" + currentHistory; - } else - return ""; +const QString TContentHistory::serialize() const { + const QString currentHistory = currentToString(); + + if (m_frozenHistory != "") + return m_frozenHistory + currentHistory; + else if (currentHistory != "") { + if (m_isLevel) + return "| # DATE: Time: MACHINE: USER: FRAMES " + "MODIFIED: |" + + currentHistory; + else + return "| # DATE: Time: MACHINE: USER: |" + + currentHistory; + } else + return ""; } //-------------------------------------------------------------------- -void TContentHistory::fixCurrentHistory() -{ - m_frozenHistory = serialize(); - m_records.clear(); +void TContentHistory::fixCurrentHistory() { + m_frozenHistory = serialize(); + m_records.clear(); } //-------------------------------------------------------------------- -void TContentHistory::frameRangeModifiedNow(const TFrameId &fromId, const TFrameId &toId) -{ - assert(m_isLevel); - QDateTime date = QDateTime::currentDateTime(); - QDateTime dateNoSecs(date.date(), date.time().addSecs(-date.time().second())); - assert(dateNoSecs.secsTo(date) == date.time().second()); +void TContentHistory::frameRangeModifiedNow(const TFrameId &fromId, + const TFrameId &toId) { + assert(m_isLevel); + QDateTime date = QDateTime::currentDateTime(); + QDateTime dateNoSecs(date.date(), date.time().addSecs(-date.time().second())); + assert(dateNoSecs.secsTo(date) == date.time().second()); - int i; - m_records[fromId] = dateNoSecs; + int i; + m_records[fromId] = dateNoSecs; - if (fromId == toId) - return; + if (fromId == toId) return; - for (i = fromId.getNumber() + 1; i <= toId.getNumber() - 1; i++) - m_records[TFrameId(i)] = dateNoSecs; + for (i = fromId.getNumber() + 1; i <= toId.getNumber() - 1; i++) + m_records[TFrameId(i)] = dateNoSecs; - m_records[toId] = dateNoSecs; + m_records[toId] = dateNoSecs; } //-------------------------------------------------------------------- -void TContentHistory::modifiedNow() -{ - assert(!m_isLevel); - QDateTime date = QDateTime::currentDateTime(); - QDateTime dateNoSecs(date.date(), date.time().addSecs(-date.time().second())); - assert(dateNoSecs.secsTo(date) == date.time().second()); +void TContentHistory::modifiedNow() { + assert(!m_isLevel); + QDateTime date = QDateTime::currentDateTime(); + QDateTime dateNoSecs(date.date(), date.time().addSecs(-date.time().second())); + assert(dateNoSecs.secsTo(date) == date.time().second()); - m_records[0] = dateNoSecs; + m_records[0] = dateNoSecs; } /* void testHistory() { - { - TContentHistory ch(true); - - ch.frameModifiedNow(TFrameId(13)); - Sleep(1000); - - ch.frameModifiedNow(TFrameId(3, 'c')); - ch.frameRangeModifiedNow(TFrameId(5), TFrameId(7)); - ch.fixCurrentHistory(); - Sleep(2000); - ch.frameRangeModifiedNow(TFrameId(6), TFrameId(9)); - ch.frameModifiedNow(TFrameId(11)); - QString str1 = ch.serialize(); - - TContentHistory ch1(true); - ch1.deserialize(str1); - ch1.frameRangeModifiedNow(TFrameId(2), TFrameId(3, 'c')); - Sleep(2000); - ch1.frameModifiedNow(TFrameId(3, 'a')); - ch1.fixCurrentHistory(); - Sleep(2000); - ch1.frameModifiedNow(TFrameId(11, 'b')); - ch1.frameModifiedNow(TFrameId(12)); - QString str2 = ch1.serialize(); - - QFile f("C:\\temp\\out.txt"); - f.open(QIODevice::WriteOnly | QIODevice::Text); - QTextStream out(&f); - out << str2; - } + { + TContentHistory ch(true); + + ch.frameModifiedNow(TFrameId(13)); + Sleep(1000); + + ch.frameModifiedNow(TFrameId(3, 'c')); + ch.frameRangeModifiedNow(TFrameId(5), TFrameId(7)); + ch.fixCurrentHistory(); + Sleep(2000); + ch.frameRangeModifiedNow(TFrameId(6), TFrameId(9)); + ch.frameModifiedNow(TFrameId(11)); + QString str1 = ch.serialize(); + + TContentHistory ch1(true); + ch1.deserialize(str1); + ch1.frameRangeModifiedNow(TFrameId(2), TFrameId(3, 'c')); + Sleep(2000); + ch1.frameModifiedNow(TFrameId(3, 'a')); + ch1.fixCurrentHistory(); + Sleep(2000); + ch1.frameModifiedNow(TFrameId(11, 'b')); + ch1.frameModifiedNow(TFrameId(12)); + QString str2 = ch1.serialize(); + + QFile f("C:\\temp\\out.txt"); + f.open(QIODevice::WriteOnly | QIODevice::Text); + QTextStream out(&f); + out << str2; + } { - TContentHistory ch(false); - - ch.modifiedNow(); - Sleep(1000); - - ch.modifiedNow(); - ch.modifiedNow(); - ch.fixCurrentHistory(); - Sleep(2000); - ch.modifiedNow(); - ch.modifiedNow(); - QString str1 = ch.serialize(); - - TContentHistory ch1(false); - ch1.deserialize(str1); - ch1.modifiedNow(); - Sleep(2000); - ch1.modifiedNow(); - ch1.fixCurrentHistory(); - Sleep(2000); - ch1.modifiedNow(); - ch1.modifiedNow(); - QString str2 = ch1.serialize(); - - QFile f("C:\\temp\\out1.txt"); - f.open(QIODevice::WriteOnly | QIODevice::Text); - QTextStream out(&f); - out << str2; - } + TContentHistory ch(false); + + ch.modifiedNow(); + Sleep(1000); + + ch.modifiedNow(); + ch.modifiedNow(); + ch.fixCurrentHistory(); + Sleep(2000); + ch.modifiedNow(); + ch.modifiedNow(); + QString str1 = ch.serialize(); + + TContentHistory ch1(false); + ch1.deserialize(str1); + ch1.modifiedNow(); + Sleep(2000); + ch1.modifiedNow(); + ch1.fixCurrentHistory(); + Sleep(2000); + ch1.modifiedNow(); + ch1.modifiedNow(); + QString str2 = ch1.serialize(); + + QFile f("C:\\temp\\out1.txt"); + f.open(QIODevice::WriteOnly | QIODevice::Text); + QTextStream out(&f); + out << str2; + } } */ diff --git a/toonz/sources/common/tcore/tdata.cpp b/toonz/sources/common/tcore/tdata.cpp index b131f52..0434292 100644 --- a/toonz/sources/common/tcore/tdata.cpp +++ b/toonz/sources/common/tcore/tdata.cpp @@ -5,23 +5,15 @@ DEFINE_CLASS_CODE(TData, 16) -TTextData::TTextData(std::string text) - : m_text(::to_wstring(text)) -{ -} +TTextData::TTextData(std::string text) : m_text(::to_wstring(text)) {} -TDataP TTextData::clone() const -{ - return new TTextData(m_text); -} +TDataP TTextData::clone() const { return new TTextData(m_text); } -TDataP TFilePathListData::clone() const -{ - return new TFilePathListData(m_filePaths); +TDataP TFilePathListData::clone() const { + return new TFilePathListData(m_filePaths); } -TFilePath TFilePathListData::getFilePath(int i) const -{ - assert(0 <= i && i < (int)m_filePaths.size()); - return m_filePaths[i]; +TFilePath TFilePathListData::getFilePath(int i) const { + assert(0 <= i && i < (int)m_filePaths.size()); + return m_filePaths[i]; } diff --git a/toonz/sources/common/tcore/tdebugmessage.cpp b/toonz/sources/common/tcore/tdebugmessage.cpp index 5ff57c9..0ef937b 100644 --- a/toonz/sources/common/tcore/tdebugmessage.cpp +++ b/toonz/sources/common/tcore/tdebugmessage.cpp @@ -5,29 +5,25 @@ using namespace std; -namespace -{ +namespace { TDebugMessage::Manager *debugManagerInstance = 0; } -void TDebugMessage::setManager(Manager *manager) -{ - debugManagerInstance = manager; +void TDebugMessage::setManager(Manager *manager) { + debugManagerInstance = manager; } -ostream &TDebugMessage::getStream() -{ - if (debugManagerInstance) - return debugManagerInstance->getStream(); - else - return cout; +ostream &TDebugMessage::getStream() { + if (debugManagerInstance) + return debugManagerInstance->getStream(); + else + return cout; } -void TDebugMessage::flush(int code) -{ - if (debugManagerInstance) - debugManagerInstance->flush(code); - else - cout << endl; +void TDebugMessage::flush(int code) { + if (debugManagerInstance) + debugManagerInstance->flush(code); + else + cout << endl; } diff --git a/toonz/sources/common/tcore/texception.cpp b/toonz/sources/common/tcore/texception.cpp index 539cc68..c5cab15 100644 --- a/toonz/sources/common/tcore/texception.cpp +++ b/toonz/sources/common/tcore/texception.cpp @@ -3,10 +3,7 @@ #include "texception.h" #include "tconvert.h" -TException::TException(const std::string &msg) -{ - m_msg = ::to_wstring(msg); -} +TException::TException(const std::string &msg) { m_msg = ::to_wstring(msg); } /* ostream& operator<<(ostream &out, const TException &e) { diff --git a/toonz/sources/common/tcore/tfunctorinvoker.cpp b/toonz/sources/common/tcore/tfunctorinvoker.cpp index 8a69dc9..7c76617 100644 --- a/toonz/sources/common/tcore/tfunctorinvoker.cpp +++ b/toonz/sources/common/tcore/tfunctorinvoker.cpp @@ -9,16 +9,14 @@ // TFunctorInvoker definition //******************************************************************************** -TFunctorInvoker *TFunctorInvoker::instance() -{ - static TFunctorInvoker theInstance; - return &theInstance; +TFunctorInvoker *TFunctorInvoker::instance() { + static TFunctorInvoker theInstance; + return &theInstance; } //----------------------------------------------------------------- -void TFunctorInvoker::invokeQueued(BaseFunctor *functor) -{ - QMetaObject::invokeMethod( - this, "invoke", Qt::QueuedConnection, Q_ARG(void *, functor)); +void TFunctorInvoker::invokeQueued(BaseFunctor *functor) { + QMetaObject::invokeMethod(this, "invoke", Qt::QueuedConnection, + Q_ARG(void *, functor)); } diff --git a/toonz/sources/common/tcore/threadmessage.cpp b/toonz/sources/common/tcore/threadmessage.cpp index aeb7bf3..7c17373 100644 --- a/toonz/sources/common/tcore/threadmessage.cpp +++ b/toonz/sources/common/tcore/threadmessage.cpp @@ -6,86 +6,74 @@ QThread *MainThread = QThread::currentThread(); -TThreadMessageDispatcher *Dispatcher; //MUST BE CREATED in the main thread!!!!!! +TThreadMessageDispatcher + *Dispatcher; // MUST BE CREATED in the main thread!!!!!! //------------------------------------------------------------------------------ -bool TThread::isMainThread() -{ - return MainThread == QThread::currentThread(); -} +bool TThread::isMainThread() { return MainThread == QThread::currentThread(); } //------------------------------------------------------------------------------ -TThreadMessageDispatcher::TThreadMessageDispatcher() -{ - connect(this, SIGNAL(signaled(TThread::Message *)), this, SLOT(onSignal(TThread::Message *))); - connect(this, SIGNAL(blockingSignaled(TThread::Message *)), this, SLOT(onSignal(TThread::Message *)), Qt::BlockingQueuedConnection); +TThreadMessageDispatcher::TThreadMessageDispatcher() { + connect(this, SIGNAL(signaled(TThread::Message *)), this, + SLOT(onSignal(TThread::Message *))); + connect(this, SIGNAL(blockingSignaled(TThread::Message *)), this, + SLOT(onSignal(TThread::Message *)), Qt::BlockingQueuedConnection); } //------------------------------------------------------------------------------ -void TThreadMessageDispatcher::init() -{ - if (!TThread::isMainThread()) - return; - if (Dispatcher == 0) - Dispatcher = new TThreadMessageDispatcher(); +void TThreadMessageDispatcher::init() { + if (!TThread::isMainThread()) return; + if (Dispatcher == 0) Dispatcher = new TThreadMessageDispatcher(); } //------------------------------------------------------------------------------ -TThreadMessageDispatcher *TThreadMessageDispatcher::instance() -{ - assert(Dispatcher); - return Dispatcher; +TThreadMessageDispatcher *TThreadMessageDispatcher::instance() { + assert(Dispatcher); + return Dispatcher; } //------------------------------------------------------------------------------ -void TThreadMessageDispatcher::emitSignaled(TThread::Message *msg) -{ - Q_EMIT signaled(msg); +void TThreadMessageDispatcher::emitSignaled(TThread::Message *msg) { + Q_EMIT signaled(msg); } //------------------------------------------------------------------------------ -void TThreadMessageDispatcher::emitBlockingSignaled(TThread::Message *msg) -{ - Q_EMIT blockingSignaled(msg); +void TThreadMessageDispatcher::emitBlockingSignaled(TThread::Message *msg) { + Q_EMIT blockingSignaled(msg); } //------------------------------------------------------------------------------ -void TThreadMessageDispatcher::onSignal(TThread::Message *msg) -{ - msg->onDeliver(); - delete msg; +void TThreadMessageDispatcher::onSignal(TThread::Message *msg) { + msg->onDeliver(); + delete msg; } //------------------------------------------------------------------------------ -TThread::Message::Message() -{ -} +TThread::Message::Message() {} //------------------------------------------------------------------------------ -void TThread::Message::send() -{ - if (isMainThread()) - onDeliver(); - else - TThreadMessageDispatcher::instance()->emitSignaled(clone()); +void TThread::Message::send() { + if (isMainThread()) + onDeliver(); + else + TThreadMessageDispatcher::instance()->emitSignaled(clone()); } //------------------------------------------------------------------------------ -void TThread::Message::sendBlocking() -{ - if (isMainThread()) - onDeliver(); - else - TThreadMessageDispatcher::instance()->emitBlockingSignaled(clone()); +void TThread::Message::sendBlocking() { + if (isMainThread()) + onDeliver(); + else + TThreadMessageDispatcher::instance()->emitBlockingSignaled(clone()); } //------------------------------------------------------------------------------ diff --git a/toonz/sources/common/tcore/tidentifiable.cpp b/toonz/sources/common/tcore/tidentifiable.cpp index 6737e54..a58c29f 100644 --- a/toonz/sources/common/tcore/tidentifiable.cpp +++ b/toonz/sources/common/tcore/tidentifiable.cpp @@ -3,114 +3,85 @@ #include "tidentifiable.h" #include -namespace -{ +namespace { -class IdentifierTable -{ // singleton +class IdentifierTable { // singleton - unsigned long m_lastId; - std::map m_table; - std::set m_objects; + unsigned long m_lastId; + std::map m_table; + std::set m_objects; - IdentifierTable() : m_lastId(0) {} + IdentifierTable() : m_lastId(0) {} public: - static IdentifierTable *instance() - { - // NON DEVE MORIRE - //static IdentifierTable _instance; - //return &_instance; - static IdentifierTable *_instance = 0; - if (!_instance) - _instance = new IdentifierTable; - return _instance; - } - - unsigned long getNextId() - { - return ++m_lastId; - } - - void insert(TIdentifiable *o) - { - - unsigned long id = o->getIdentifier(); - std::map::iterator it = m_table.find(id); - if (it != m_table.end()) { - if (it->second == o) - return; - m_objects.erase(it->second); - it->second = o; - } else { - m_table[id] = o; - } - m_objects.insert(o); - } - - void erase(TIdentifiable *o) - { - - unsigned long id = o->getIdentifier(); - m_table.erase(id); - m_objects.erase(o); - } - - TIdentifiable *fetch(unsigned long id) - { - std::map::iterator it = m_table.find(id); - return it == m_table.end() ? 0 : it->second; - } + static IdentifierTable *instance() { + // NON DEVE MORIRE + // static IdentifierTable _instance; + // return &_instance; + static IdentifierTable *_instance = 0; + if (!_instance) _instance = new IdentifierTable; + return _instance; + } + + unsigned long getNextId() { return ++m_lastId; } + + void insert(TIdentifiable *o) { + unsigned long id = o->getIdentifier(); + std::map::iterator it = m_table.find(id); + if (it != m_table.end()) { + if (it->second == o) return; + m_objects.erase(it->second); + it->second = o; + } else { + m_table[id] = o; + } + m_objects.insert(o); + } + + void erase(TIdentifiable *o) { + unsigned long id = o->getIdentifier(); + m_table.erase(id); + m_objects.erase(o); + } + + TIdentifiable *fetch(unsigned long id) { + std::map::iterator it = m_table.find(id); + return it == m_table.end() ? 0 : it->second; + } }; -} // namespace +} // namespace -TIdentifiable::TIdentifiable() - : m_id(0) -{ -} +TIdentifiable::TIdentifiable() : m_id(0) {} -TIdentifiable::~TIdentifiable() -{ - if (m_id != 0) - IdentifierTable::instance()->erase(this); +TIdentifiable::~TIdentifiable() { + if (m_id != 0) IdentifierTable::instance()->erase(this); } -TIdentifiable::TIdentifiable(const TIdentifiable &src) - : m_id(src.m_id) -{ -} +TIdentifiable::TIdentifiable(const TIdentifiable &src) : m_id(src.m_id) {} -const TIdentifiable &TIdentifiable::operator=(const TIdentifiable &src) -{ - if (src.m_id != m_id && m_id != 0) - IdentifierTable::instance()->erase(this); - m_id = src.m_id; - return *this; +const TIdentifiable &TIdentifiable::operator=(const TIdentifiable &src) { + if (src.m_id != m_id && m_id != 0) IdentifierTable::instance()->erase(this); + m_id = src.m_id; + return *this; } -void TIdentifiable::setIdentifier(unsigned long id) -{ - bool wasStored = m_id > 0 && IdentifierTable::instance()->fetch(m_id) == this; - if (m_id != id && m_id != 0) - IdentifierTable::instance()->erase(this); - m_id = id; - if (wasStored) - IdentifierTable::instance()->insert(this); +void TIdentifiable::setIdentifier(unsigned long id) { + bool wasStored = m_id > 0 && IdentifierTable::instance()->fetch(m_id) == this; + if (m_id != id && m_id != 0) IdentifierTable::instance()->erase(this); + m_id = id; + if (wasStored) IdentifierTable::instance()->insert(this); } -void TIdentifiable::setNewIdentifier() -{ - setIdentifier(IdentifierTable::instance()->getNextId()); +void TIdentifiable::setNewIdentifier() { + setIdentifier(IdentifierTable::instance()->getNextId()); } -void TIdentifiable::storeByIdentifier() -{ - assert(getIdentifier() >= 1); - IdentifierTable::instance()->insert(this); +void TIdentifiable::storeByIdentifier() { + assert(getIdentifier() >= 1); + IdentifierTable::instance()->insert(this); } -TIdentifiable *TIdentifiable::fetchByIdentifier(unsigned long id) -{ - return IdentifierTable::instance()->fetch(id); +TIdentifiable *TIdentifiable::fetchByIdentifier(unsigned long id) { + return IdentifierTable::instance()->fetch(id); } diff --git a/toonz/sources/common/tcore/tmathutil.cpp b/toonz/sources/common/tcore/tmathutil.cpp index 342520a..67c3773 100644 --- a/toonz/sources/common/tcore/tmathutil.cpp +++ b/toonz/sources/common/tcore/tmathutil.cpp @@ -7,13 +7,9 @@ using TConsts::epsilon; -TMathException::TMathException(std::string msg) - : m_msg(::to_wstring(msg)) -{ -} +TMathException::TMathException(std::string msg) : m_msg(::to_wstring(msg)) {} -namespace -{ +namespace { //------------------------------------------------------------------------- @@ -26,7 +22,7 @@ const double RELERROR = 1.0e-14; //! max power of 10 we wish to search to const int MAXPOW = 32; -//!max number of iterations +//! max number of iterations const int MAXIT = 800; //! a coefficient smaller than SMALL_ENOUGH is considered to be zero (0.0). @@ -34,17 +30,13 @@ const double SMALL_ENOUGH = 1.0e-12; //------------------------------------------------------------------------- -inline int getEl(int i, int j, int n) -{ - return (j - 1) + (i - 1) * n; -} +inline int getEl(int i, int j, int n) { return (j - 1) + (i - 1) * n; } //------------------------------------------------------------------------- //! structure type for representing a polynomial -typedef struct - { - int ord; - double coef[MAX_ORDER + 1]; +typedef struct { + int ord; + double coef[MAX_ORDER + 1]; } poly; //------------------------------------------------------------------------- @@ -57,22 +49,19 @@ int modrf(int ord, double *coef, double a, double b, double *val); //------------------------------------------------------------------------- -void convert(const std::vector &v, poly &p) -{ - assert((int)v.size() <= MAX_ORDER); - if ((int)v.size() > MAX_ORDER) - return; +void convert(const std::vector &v, poly &p) { + assert((int)v.size() <= MAX_ORDER); + if ((int)v.size() > MAX_ORDER) return; - p.ord = v.size() - 1; + p.ord = v.size() - 1; - std::copy(v.begin(), v.end(), p.coef); + std::copy(v.begin(), v.end(), p.coef); } //------------------------------------------------------------------------- -void convert(const poly &p, std::vector &v) -{ - v.resize(p.ord); - std::copy(p.coef, p.coef + p.ord, v.begin()); +void convert(const poly &p, std::vector &v) { + v.resize(p.ord); + std::copy(p.coef, p.coef + p.ord, v.begin()); } //------------------------------------------------------------------------- @@ -82,43 +71,40 @@ void convert(const poly &p, std::vector &v) * * calculates the modulus of u(x) / v(x) leaving it in r, it * returns 0 if r(x) is a constant. - * note: this function assumes the leading coefficient of v + * note: this function assumes the leading coefficient of v * is 1 or -1 */ -int modp(poly *u, poly *v, poly *r) -{ - int k, j; - double *nr, *end, *uc; - - nr = r->coef; - end = &u->coef[u->ord]; - - uc = u->coef; - while (uc <= end) - *nr++ = *uc++; - - if (v->coef[v->ord] < 0.0) { - for (k = u->ord - v->ord - 1; k >= 0; k -= 2) - r->coef[k] = -r->coef[k]; - - for (k = u->ord - v->ord; k >= 0; k--) - for (j = v->ord + k - 1; j >= k; j--) - r->coef[j] = -r->coef[j] - r->coef[v->ord + k] * v->coef[j - k]; - } else { - for (k = u->ord - v->ord; k >= 0; k--) - for (j = v->ord + k - 1; j >= k; j--) - r->coef[j] -= r->coef[v->ord + k] * v->coef[j - k]; - } - - k = v->ord - 1; - while (k >= 0 && fabs(r->coef[k]) < SMALL_ENOUGH) { - r->coef[k] = 0.0; - k--; - } - - r->ord = (k < 0) ? 0 : k; - - return (r->ord); +int modp(poly *u, poly *v, poly *r) { + int k, j; + double *nr, *end, *uc; + + nr = r->coef; + end = &u->coef[u->ord]; + + uc = u->coef; + while (uc <= end) *nr++ = *uc++; + + if (v->coef[v->ord] < 0.0) { + for (k = u->ord - v->ord - 1; k >= 0; k -= 2) r->coef[k] = -r->coef[k]; + + for (k = u->ord - v->ord; k >= 0; k--) + for (j = v->ord + k - 1; j >= k; j--) + r->coef[j] = -r->coef[j] - r->coef[v->ord + k] * v->coef[j - k]; + } else { + for (k = u->ord - v->ord; k >= 0; k--) + for (j = v->ord + k - 1; j >= k; j--) + r->coef[j] -= r->coef[v->ord + k] * v->coef[j - k]; + } + + k = v->ord - 1; + while (k >= 0 && fabs(r->coef[k]) < SMALL_ENOUGH) { + r->coef[k] = 0.0; + k--; + } + + r->ord = (k < 0) ? 0 : k; + + return (r->ord); } //------------------------------------------------------------------------- @@ -129,33 +115,30 @@ int modp(poly *u, poly *v, poly *r) * build up a sturm sequence for a polynomial in sseq, returning * the number of polynomials in the sequence */ -int buildsturm(int ord, poly *sseq) -{ - int i; - double f, *fp, *fc; - poly *sp; - - sseq[0].ord = ord; - sseq[1].ord = ord - 1; - - // calculate the derivative and normalise the leadingcoefficient. - f = fabs(sseq[0].coef[ord] * ord); - fp = sseq[1].coef; - fc = sseq[0].coef + 1; - for (i = 1; i <= ord; i++) - *fp++ = *fc++ * i / f; - - // construct the rest of the Sturm sequence - for (sp = sseq + 2; modp(sp - 2, sp - 1, sp); sp++) { - // reverse the sign and normalise - f = -fabs(sp->coef[sp->ord]); - for (fp = &sp->coef[sp->ord]; fp >= sp->coef; fp--) - *fp /= f; - } - - sp->coef[0] = -sp->coef[0]; // reverse the sign - - return (sp - sseq); +int buildsturm(int ord, poly *sseq) { + int i; + double f, *fp, *fc; + poly *sp; + + sseq[0].ord = ord; + sseq[1].ord = ord - 1; + + // calculate the derivative and normalise the leadingcoefficient. + f = fabs(sseq[0].coef[ord] * ord); + fp = sseq[1].coef; + fc = sseq[0].coef + 1; + for (i = 1; i <= ord; i++) *fp++ = *fc++ * i / f; + + // construct the rest of the Sturm sequence + for (sp = sseq + 2; modp(sp - 2, sp - 1, sp); sp++) { + // reverse the sign and normalise + f = -fabs(sp->coef[sp->ord]); + for (fp = &sp->coef[sp->ord]; fp >= sp->coef; fp--) *fp /= f; + } + + sp->coef[0] = -sp->coef[0]; // reverse the sign + + return (sp - sseq); } //------------------------------------------------------------------------- @@ -164,46 +147,41 @@ int buildsturm(int ord, poly *sseq) return the number of distinct real roots of the polynomial described in sseq */ -int numroots(int np, poly *sseq, int &atneg, int &atpos) -{ - int - atposinf = 0, - atneginf = 0; - - poly *s; - double f, lf; - - // change at positive infinity - lf = sseq[0].coef[sseq[0].ord]; - - for (s = sseq + 1; s <= sseq + np; ++s) { - f = s->coef[s->ord]; - if (0.0 == lf || lf * f < 0.0) - ++atposinf; - lf = f; - } - - // change at negative infinity - if (sseq[0].ord & 1) - lf = -sseq[0].coef[sseq[0].ord]; - else - lf = sseq[0].coef[sseq[0].ord]; - - for (s = sseq + 1; s <= sseq + np; ++s) { - if (s->ord & 1) - f = -s->coef[s->ord]; - else - f = s->coef[s->ord]; - - if (0.0 == lf || lf * f < 0.0) - ++atneginf; - lf = f; - } - - atneg = atneginf; - atpos = atposinf; - - return atneginf - atposinf; +int numroots(int np, poly *sseq, int &atneg, int &atpos) { + int atposinf = 0, atneginf = 0; + + poly *s; + double f, lf; + + // change at positive infinity + lf = sseq[0].coef[sseq[0].ord]; + + for (s = sseq + 1; s <= sseq + np; ++s) { + f = s->coef[s->ord]; + if (0.0 == lf || lf * f < 0.0) ++atposinf; + lf = f; + } + + // change at negative infinity + if (sseq[0].ord & 1) + lf = -sseq[0].coef[sseq[0].ord]; + else + lf = sseq[0].coef[sseq[0].ord]; + + for (s = sseq + 1; s <= sseq + np; ++s) { + if (s->ord & 1) + f = -s->coef[s->ord]; + else + f = s->coef[s->ord]; + + if (0.0 == lf || lf * f < 0.0) ++atneginf; + lf = f; + } + + atneg = atneginf; + atpos = atposinf; + + return atneginf - atposinf; } //------------------------------------------------------------------------- @@ -214,24 +192,22 @@ int numroots(int np, poly *sseq, int &atneg, int &atpos) * return the number of sign changes in the Sturm sequence in * sseq at the value a. */ -int numchanges(int np, poly *sseq, double a) -{ - int changes; - double f, lf; - poly *s; +int numchanges(int np, poly *sseq, double a) { + int changes; + double f, lf; + poly *s; - changes = 0; + changes = 0; - lf = evalpoly(sseq[0].ord, sseq[0].coef, a); + lf = evalpoly(sseq[0].ord, sseq[0].coef, a); - for (s = sseq + 1; s <= sseq + np; s++) { - f = evalpoly(s->ord, s->coef, a); - if (lf == 0.0 || lf * f < 0) - changes++; - lf = f; - } + for (s = sseq + 1; s <= sseq + np; s++) { + f = evalpoly(s->ord, s->coef, a); + if (lf == 0.0 || lf * f < 0) changes++; + lf = f; + } - return (changes); + return (changes); } //------------------------------------------------------------------------- @@ -243,93 +219,85 @@ int numchanges(int np, poly *sseq, double a) * described in sseq to isolate intervals in which roots occur, * the roots are returned in the roots array in order of magnitude. */ -void sbisect(int np, - poly *sseq, - double min, - double max, - int atmin, - int atmax, - double *roots) -{ - double mid; - int n1 = 0, n2 = 0, its, atmid; - - if ((atmin - atmax) == 1) { - //first try a less expensive technique. - - if (modrf(sseq->ord, sseq->coef, min, max, &roots[0])) - return; - - /* - * if we get here we have to evaluate the root the hard - * way by using the Sturm sequence. - */ - for (its = 0; its < MAXIT; its++) { - mid = (min + max) / 2; - - atmid = numchanges(np, sseq, mid); - - if (fabs(mid) > RELERROR) { - if (fabs((max - min) / mid) < RELERROR) { - roots[0] = mid; - return; - } - } else if (fabs(max - min) < RELERROR) { - roots[0] = mid; - return; - } - - if ((atmin - atmid) == 0) - min = mid; - else - max = mid; - } - - if (its == MAXIT) { - /* - fprintf(stderr, "sbisect: overflow min %f max %f\ - diff %e nroot %d n1 %d n2 %d\n", - min, max, max - min, nroot, n1, n2); - */ - roots[0] = mid; - } - - return; - } - - /* - * more than one root in the interval, we have to bisect... - */ - for (its = 0; its < MAXIT; its++) { - mid = (min + max) / 2; - - atmid = numchanges(np, sseq, mid); - - n1 = atmin - atmid; - n2 = atmid - atmax; - - if (n1 != 0 && n2 != 0) { - sbisect(np, sseq, min, mid, atmin, atmid, roots); - sbisect(np, sseq, mid, max, atmid, atmax, &roots[n1]); - break; - } - - if (n1 == 0) - min = mid; - else - max = mid; - } - - if (its == MAXIT) { - /* - fprintf(stderr, "sbisect: roots too close together\n"); - fprintf(stderr, "sbisect: overflow min %f max %f diff %e\ - nroot %d n1 %d n2 %d\n", - min, max, max - min, nroot, n1, n2); - */ - for (n1 = atmax; n1 < atmin; n1++) - roots[n1 - atmax] = mid; - } +void sbisect(int np, poly *sseq, double min, double max, int atmin, int atmax, + double *roots) { + double mid; + int n1 = 0, n2 = 0, its, atmid; + + if ((atmin - atmax) == 1) { + // first try a less expensive technique. + + if (modrf(sseq->ord, sseq->coef, min, max, &roots[0])) return; + + /* +* if we get here we have to evaluate the root the hard +* way by using the Sturm sequence. +*/ + for (its = 0; its < MAXIT; its++) { + mid = (min + max) / 2; + + atmid = numchanges(np, sseq, mid); + + if (fabs(mid) > RELERROR) { + if (fabs((max - min) / mid) < RELERROR) { + roots[0] = mid; + return; + } + } else if (fabs(max - min) < RELERROR) { + roots[0] = mid; + return; + } + + if ((atmin - atmid) == 0) + min = mid; + else + max = mid; + } + + if (its == MAXIT) { + /* +fprintf(stderr, "sbisect: overflow min %f max %f\ +diff %e nroot %d n1 %d n2 %d\n", +min, max, max - min, nroot, n1, n2); +*/ + roots[0] = mid; + } + + return; + } + + /* +* more than one root in the interval, we have to bisect... +*/ + for (its = 0; its < MAXIT; its++) { + mid = (min + max) / 2; + + atmid = numchanges(np, sseq, mid); + + n1 = atmin - atmid; + n2 = atmid - atmax; + + if (n1 != 0 && n2 != 0) { + sbisect(np, sseq, min, mid, atmin, atmid, roots); + sbisect(np, sseq, mid, max, atmid, atmax, &roots[n1]); + break; + } + + if (n1 == 0) + min = mid; + else + max = mid; + } + + if (its == MAXIT) { + /* +fprintf(stderr, "sbisect: roots too close together\n"); +fprintf(stderr, "sbisect: overflow min %f max %f diff %e\ +nroot %d n1 %d n2 %d\n", +min, max, max - min, nroot, n1, n2); +*/ + for (n1 = atmax; n1 < atmin; n1++) roots[n1 - atmax] = mid; + } } //------------------------------------------------------------------------- @@ -339,17 +307,15 @@ void sbisect(int np, * * evaluate polynomial defined in coef returning its value. */ -double evalpoly(int ord, double *coef, double x) -{ - double *fp, f; +double evalpoly(int ord, double *coef, double x) { + double *fp, f; - fp = &coef[ord]; - f = *fp; + fp = &coef[ord]; + f = *fp; - for (fp--; fp >= coef; fp--) - f = x * f + *fp; + for (fp--; fp >= coef; fp--) f = x * f + *fp; - return (f); + return (f); } //------------------------------------------------------------------------- @@ -362,564 +328,511 @@ double evalpoly(int ord, double *coef, double x) * root is returned is returned in *val. The routine returns zero * if it can't converge. */ -int modrf(int ord, double *coef, double a, double b, double *val) -{ - int its; - double fa, fb, x, fx, lfx; - double *fp, *scoef, *ecoef; - - scoef = coef; - ecoef = &coef[ord]; - - fb = fa = *ecoef; - for (fp = ecoef - 1; fp >= scoef; fp--) { - fa = a * fa + *fp; - fb = b * fb + *fp; - } - - // if there is no sign difference the method won't work - if (fa * fb > 0.0) - return (0); - - if (fabs(fa) < RELERROR) { - *val = a; - return (1); - } - - if (fabs(fb) < RELERROR) { - *val = b; - return (1); - } - - lfx = fa; - - for (its = 0; its < MAXIT; its++) { - x = (fb * a - fa * b) / (fb - fa); - - fx = *ecoef; - for (fp = ecoef - 1; fp >= scoef; fp--) - fx = x * fx + *fp; - - if (fabs(x) > RELERROR) { - if (fabs(fx / x) < RELERROR) { - *val = x; - return (1); - } - } else if (fabs(fx) < RELERROR) { - *val = x; - return (1); - } - - if ((fa * fx) < 0) { - b = x; - fb = fx; - if ((lfx * fx) > 0) - fa /= 2; - } else { - a = x; - fa = fx; - if ((lfx * fx) > 0) - fb /= 2; - } - - lfx = fx; - } - - // fprintf(stderr, "modrf overflow %f %f %f\n", a, b, fx); - - return (0); +int modrf(int ord, double *coef, double a, double b, double *val) { + int its; + double fa, fb, x, fx, lfx; + double *fp, *scoef, *ecoef; + + scoef = coef; + ecoef = &coef[ord]; + + fb = fa = *ecoef; + for (fp = ecoef - 1; fp >= scoef; fp--) { + fa = a * fa + *fp; + fb = b * fb + *fp; + } + + // if there is no sign difference the method won't work + if (fa * fb > 0.0) return (0); + + if (fabs(fa) < RELERROR) { + *val = a; + return (1); + } + + if (fabs(fb) < RELERROR) { + *val = b; + return (1); + } + + lfx = fa; + + for (its = 0; its < MAXIT; its++) { + x = (fb * a - fa * b) / (fb - fa); + + fx = *ecoef; + for (fp = ecoef - 1; fp >= scoef; fp--) fx = x * fx + *fp; + + if (fabs(x) > RELERROR) { + if (fabs(fx / x) < RELERROR) { + *val = x; + return (1); + } + } else if (fabs(fx) < RELERROR) { + *val = x; + return (1); + } + + if ((fa * fx) < 0) { + b = x; + fb = fx; + if ((lfx * fx) > 0) fa /= 2; + } else { + a = x; + fa = fx; + if ((lfx * fx) > 0) fb /= 2; + } + + lfx = fx; + } + + // fprintf(stderr, "modrf overflow %f %f %f\n", a, b, fx); + + return (0); } //------------------------------------------------------------------------- /*! a x^2 + b x + c - - Remark: - poly[0] = c + + Remark: + poly[0] = c poly[1] = b - poly[2] = a + poly[2] = a */ -int rootForQuadraticEquation(const std::vector &v, std::vector &sol) +int rootForQuadraticEquation(const std::vector &v, + std::vector &sol) { + double q, delta; + + /* +if( isAlmostZero(v[2])) { - double q, delta; - - /* - if( isAlmostZero(v[2])) - { - if ( isAlmostZero(v[1]) ) - return -1; - - sol.push_back(-v[0]/v[1]); - return 1; - } - */ +if ( isAlmostZero(v[1]) ) +return -1; + + sol.push_back(-v[0]/v[1]); + return 1; + } +*/ - if (isAlmostZero(v[1])) { - q = -v[0] / v[2]; - if (q < 0) - return 0; - else if (isAlmostZero(q)) { - sol.push_back(0); - return 1; - } + if (isAlmostZero(v[1])) { + q = -v[0] / v[2]; + if (q < 0) + return 0; + else if (isAlmostZero(q)) { + sol.push_back(0); + return 1; + } - q = sqrt(q); - sol.push_back(-q); - sol.push_back(q); + q = sqrt(q); + sol.push_back(-q); + sol.push_back(q); - return 2; - } + return 2; + } - delta = sq(v[1]) - 4.0 * v[0] * v[2]; + delta = sq(v[1]) - 4.0 * v[0] * v[2]; - if (delta < 0.0) - return 0; + if (delta < 0.0) return 0; - assert(v[2] != 0); + assert(v[2] != 0); - if (isAlmostZero(delta)) { - sol.push_back(-v[1] / (v[2] * 2.0)); - return 1; - } + if (isAlmostZero(delta)) { + sol.push_back(-v[1] / (v[2] * 2.0)); + return 1; + } - q = -0.5 * (v[1] + tsign(v[1]) * sqrt(delta)); + q = -0.5 * (v[1] + tsign(v[1]) * sqrt(delta)); - assert(q != 0); + assert(q != 0); - sol.push_back(v[0] / q); - sol.push_back(q / v[2]); + sol.push_back(v[0] / q); + sol.push_back(q / v[2]); - return 2; + return 2; } //----------------------------------------------------------------------------- /* a x^3+b x^2 + c x + d - - Remark: - poly[0] = d + + Remark: + poly[0] = d poly[1] = c - poly[2] = b - poly[3] = a + poly[2] = b + poly[3] = a */ -int rootForCubicEquation(const std::vector &p, std::vector &sol) -{ - /* - if( isAlmostZero(p[3]) ) - return rootForQuadraticEquation(p,sol); - */ - - if (isAlmostZero(p[0])) { - int numberOfSol; - std::vector redPol(3); - redPol[0] = p[1]; - redPol[1] = p[2]; - redPol[2] = p[3]; - - numberOfSol = rootForQuadraticEquation(redPol, sol); - - for (int i = 0; i < numberOfSol; ++i) - if (0.0 == sol[i]) - return numberOfSol; - - // altrimenti devo contare la soluzione nulla - ++numberOfSol; - sol.push_back(0); - return numberOfSol; - } - - double - inv_v3 = 1.0 / p[3], - a = p[2] * inv_v3, - b = p[1] * inv_v3, - c = p[0] * inv_v3; - - static const double inv_3 = 1.0 / 3.0; - static const double inv_9 = 1.0 / 9.0; - static const double inv_54 = 1.0 / 54.0; - - double - Q = (sq(a) - 3.0 * b) * inv_9, - R = (2.0 * sq(a) * a - 9.0 * a * b + 27.0 * c) * inv_54; - - double - R_2 = sq(R), - Q_3 = sq(Q) * Q; - - if (R_2 < Q_3) { - double Q_sqrt = sqrt(Q); - double theta = acos(R / (Q * Q_sqrt)); - sol.push_back(-2 * Q_sqrt * cos(theta * inv_3) - a * inv_3); - sol.push_back(-2 * Q_sqrt * cos((theta - TConsts::pi * 2.0) * inv_3) - a * inv_3); - sol.push_back(-2 * Q_sqrt * cos((theta + TConsts::pi * 2.0) * inv_3) - a * inv_3); - std::sort(sol.begin(), sol.end()); - return 3; - } - - double A = -tsign(R) * pow((fabs(R) + sqrt(R_2 - Q_3)), inv_3); - double B = A != 0 ? Q / A : 0; - sol.push_back((A + B) - a * inv_3); - return 1; +int rootForCubicEquation(const std::vector &p, + std::vector &sol) { + /* +if( isAlmostZero(p[3]) ) +return rootForQuadraticEquation(p,sol); +*/ + + if (isAlmostZero(p[0])) { + int numberOfSol; + std::vector redPol(3); + redPol[0] = p[1]; + redPol[1] = p[2]; + redPol[2] = p[3]; + + numberOfSol = rootForQuadraticEquation(redPol, sol); + + for (int i = 0; i < numberOfSol; ++i) + if (0.0 == sol[i]) return numberOfSol; + + // altrimenti devo contare la soluzione nulla + ++numberOfSol; + sol.push_back(0); + return numberOfSol; + } + + double inv_v3 = 1.0 / p[3], a = p[2] * inv_v3, b = p[1] * inv_v3, + c = p[0] * inv_v3; + + static const double inv_3 = 1.0 / 3.0; + static const double inv_9 = 1.0 / 9.0; + static const double inv_54 = 1.0 / 54.0; + + double Q = (sq(a) - 3.0 * b) * inv_9, + R = (2.0 * sq(a) * a - 9.0 * a * b + 27.0 * c) * inv_54; + + double R_2 = sq(R), Q_3 = sq(Q) * Q; + + if (R_2 < Q_3) { + double Q_sqrt = sqrt(Q); + double theta = acos(R / (Q * Q_sqrt)); + sol.push_back(-2 * Q_sqrt * cos(theta * inv_3) - a * inv_3); + sol.push_back(-2 * Q_sqrt * cos((theta - M_2PI) * inv_3) - a * inv_3); + sol.push_back(-2 * Q_sqrt * cos((theta + M_2PI) * inv_3) - a * inv_3); + std::sort(sol.begin(), sol.end()); + return 3; + } + + double A = -tsign(R) * pow((fabs(R) + sqrt(R_2 - Q_3)), inv_3); + double B = A != 0 ? Q / A : 0; + sol.push_back((A + B) - a * inv_3); + return 1; } //----------------------------------------------------------------------------- -int rootForGreaterThanThreeEquation(const std::vector &p, std::vector &sol) -{ - poly sseq[MAX_ORDER]; +int rootForGreaterThanThreeEquation(const std::vector &p, + std::vector &sol) { + poly sseq[MAX_ORDER]; - convert(p, sseq[0]); + convert(p, sseq[0]); - int np = buildsturm(p.size() - 1, sseq); + int np = buildsturm(p.size() - 1, sseq); - int atmin, atmax; + int atmin, atmax; - int nroot = numroots(np, sseq, atmin, atmax); + int nroot = numroots(np, sseq, atmin, atmax); - if (nroot == 0) - return 0; + if (nroot == 0) return 0; - double minVal = -1.0; + double minVal = -1.0; - UINT i = 0; + UINT i = 0; - int nchanges = numchanges(np, sseq, minVal); + int nchanges = numchanges(np, sseq, minVal); - for (i = 0; nchanges != atmin && i != (UINT)MAXPOW; ++i) { - minVal *= 10.0; - nchanges = numchanges(np, sseq, minVal); - } + for (i = 0; nchanges != atmin && i != (UINT)MAXPOW; ++i) { + minVal *= 10.0; + nchanges = numchanges(np, sseq, minVal); + } - if (nchanges != atmin) { - atmin = nchanges; - } + if (nchanges != atmin) { + atmin = nchanges; + } - double maxVal = 1.0; - nchanges = numchanges(np, sseq, maxVal); + double maxVal = 1.0; + nchanges = numchanges(np, sseq, maxVal); - for (i = 0; nchanges != atmax && i != (UINT)MAXPOW; ++i) { - maxVal *= 10.0; - nchanges = numchanges(np, sseq, maxVal); - } + for (i = 0; nchanges != atmax && i != (UINT)MAXPOW; ++i) { + maxVal *= 10.0; + nchanges = numchanges(np, sseq, maxVal); + } - if (nchanges != atmax) { - atmax = nchanges; - } + if (nchanges != atmax) { + atmax = nchanges; + } - nroot = atmin - atmax; + nroot = atmin - atmax; - assert(nroot > 0); + assert(nroot > 0); - poly outPoly; + poly outPoly; - outPoly.ord = nroot; + outPoly.ord = nroot; - sbisect(np, sseq, minVal, maxVal, atmin, atmax, outPoly.coef); + sbisect(np, sseq, minVal, maxVal, atmin, atmax, outPoly.coef); - convert(outPoly, sol); + convert(outPoly, sol); - return nroot < 0 ? -1 : nroot; + return nroot < 0 ? -1 : nroot; } //----------------------------------------------------------------------------- -} // end of unnamed namespace +} // end of unnamed namespace //----------------------------------------------------------------------------- -void tLUDecomposition(double *a, int n, int *indx, double &d) -{ - int i, imax, j, k; - double big, dum, sum, temp; - std::vector vv(n); - - d = 1.0; - for (i = 1; i <= n; i++) { - big = 0.0; - for (j = 1; j <= n; j++) - if ((temp = fabs(a[getEl(i, j, n)])) > big) - big = temp; - - if (big == 0.0) - throw TMathException("Singular matrix in routine tLUDecomposition\n"); - - vv[i - 1] = 1.0 / big; - } - - for (j = 1; j <= n; j++) { - for (i = 1; i < j; i++) { - sum = a[getEl(i, j, n)]; - for (k = 1; k < i; k++) - sum -= a[getEl(i, k, n)] * a[getEl(k, j, n)]; - a[getEl(i, j, n)] = sum; - } - big = 0.0; - for (i = j; i <= n; i++) { - sum = a[getEl(i, j, n)]; - for (k = 1; k < j; k++) - sum -= a[getEl(i, k, n)] * a[getEl(k, j, n)]; - a[getEl(i, j, n)] = sum; - if ((dum = vv[i - 1] * fabs(sum)) >= big) { - big = dum; - imax = i; - } - } - - if (j != imax) { - for (k = 1; k <= n; k++) { - dum = a[getEl(imax, k, n)]; - a[getEl(imax, k, n)] = a[getEl(j, k, n)]; - a[getEl(j, k, n)] = dum; - } - d = -(d); - vv[imax - 1] = vv[j - 1]; - } - - indx[j - 1] = imax; - - if (a[getEl(j, j, n)] == 0.0) - a[getEl(j, j, n)] = TConsts::epsilon; - - if (j != n) { - dum = 1.0 / (a[getEl(j, j, n)]); - for (i = j + 1; i <= n; i++) - a[getEl(i, j, n)] *= dum; - } - } +void tLUDecomposition(double *a, int n, int *indx, double &d) { + int i, imax, j, k; + double big, dum, sum, temp; + std::vector vv(n); + + d = 1.0; + for (i = 1; i <= n; i++) { + big = 0.0; + for (j = 1; j <= n; j++) + if ((temp = fabs(a[getEl(i, j, n)])) > big) big = temp; + + if (big == 0.0) + throw TMathException("Singular matrix in routine tLUDecomposition\n"); + + vv[i - 1] = 1.0 / big; + } + + for (j = 1; j <= n; j++) { + for (i = 1; i < j; i++) { + sum = a[getEl(i, j, n)]; + for (k = 1; k < i; k++) sum -= a[getEl(i, k, n)] * a[getEl(k, j, n)]; + a[getEl(i, j, n)] = sum; + } + big = 0.0; + for (i = j; i <= n; i++) { + sum = a[getEl(i, j, n)]; + for (k = 1; k < j; k++) sum -= a[getEl(i, k, n)] * a[getEl(k, j, n)]; + a[getEl(i, j, n)] = sum; + if ((dum = vv[i - 1] * fabs(sum)) >= big) { + big = dum; + imax = i; + } + } + + if (j != imax) { + for (k = 1; k <= n; k++) { + dum = a[getEl(imax, k, n)]; + a[getEl(imax, k, n)] = a[getEl(j, k, n)]; + a[getEl(j, k, n)] = dum; + } + d = -(d); + vv[imax - 1] = vv[j - 1]; + } + + indx[j - 1] = imax; + + if (a[getEl(j, j, n)] == 0.0) a[getEl(j, j, n)] = TConsts::epsilon; + + if (j != n) { + dum = 1.0 / (a[getEl(j, j, n)]); + for (i = j + 1; i <= n; i++) a[getEl(i, j, n)] *= dum; + } + } } //----------------------------------------------------------------------------- -void tbackSubstitution(double *a, int n, int *indx, double *b) -{ - int i, ii = 0, ip, j; - double sum; - - for (i = 1; i <= n; i++) { - ip = indx[i - 1]; - sum = b[ip - 1]; - b[ip - 1] = b[i - 1]; - if (ii) - for (j = ii; j <= i - 1; j++) - sum -= a[getEl(i, j, n)] * b[j - 1]; - else if (sum) - ii = i; - b[i - 1] = sum; - } - for (i = n; i >= 1; i--) { - sum = b[i - 1]; - for (j = i + 1; j <= n; j++) - sum -= a[getEl(i, j, n)] * b[j - 1]; - b[i - 1] = sum / a[getEl(i, i, n)]; - } +void tbackSubstitution(double *a, int n, int *indx, double *b) { + int i, ii = 0, ip, j; + double sum; + + for (i = 1; i <= n; i++) { + ip = indx[i - 1]; + sum = b[ip - 1]; + b[ip - 1] = b[i - 1]; + if (ii) + for (j = ii; j <= i - 1; j++) sum -= a[getEl(i, j, n)] * b[j - 1]; + else if (sum) + ii = i; + b[i - 1] = sum; + } + for (i = n; i >= 1; i--) { + sum = b[i - 1]; + for (j = i + 1; j <= n; j++) sum -= a[getEl(i, j, n)] * b[j - 1]; + b[i - 1] = sum / a[getEl(i, i, n)]; + } } //----------------------------------------------------------------------------- -double tdet(double *LUa, int n, double d) -{ - for (int i = 1; i <= n; ++i) - d *= LUa[getEl(i, i, n)]; +double tdet(double *LUa, int n, double d) { + for (int i = 1; i <= n; ++i) d *= LUa[getEl(i, i, n)]; - return d; + return d; } //----------------------------------------------------------------------------- -double tdet(double *a, int n) -{ - double d; - std::vector indx(n); +double tdet(double *a, int n) { + double d; + std::vector indx(n); - tLUDecomposition(a, n, &indx[0], d); - for (int i = 1; i <= n; ++i) - d *= a[getEl(i, i, n)]; + tLUDecomposition(a, n, &indx[0], d); + for (int i = 1; i <= n; ++i) d *= a[getEl(i, i, n)]; - return d; + return d; } //----------------------------------------------------------------------------- -void tsolveSistem(double *a, int n, double *res) -{ - double d; - std::vector indx(n); - - tLUDecomposition(a, n, &indx[0], d); - assert(tdet(a, n, d) != 0); - /* - if( isAlmostZero(tdet(a, n, d)) ) - throw TMathException("Singular matrix in routine tLUDecomposition\n"); - */ - tbackSubstitution(a, n, &indx[0], res); +void tsolveSistem(double *a, int n, double *res) { + double d; + std::vector indx(n); + + tLUDecomposition(a, n, &indx[0], d); + assert(tdet(a, n, d) != 0); + /* +if( isAlmostZero(tdet(a, n, d)) ) +throw TMathException("Singular matrix in routine tLUDecomposition\n"); +*/ + tbackSubstitution(a, n, &indx[0], res); } //----------------------------------------------------------------------------- -int rootFinding(const std::vector &in_poly, std::vector &sol) -{ - // per ora risolvo solo i polinomi di grado al piu' pari a 3 - assert((int)in_poly.size() <= MAX_ORDER); - if (in_poly.empty() || (int)in_poly.size() > MAX_ORDER) - return -1; - - std::vector p; - std::copy(in_poly.begin(), in_poly.end(), std::back_inserter(p)); - - // eat zero in poly - while (!p.empty() && isAlmostZero(p.back())) - p.pop_back(); - - sol.clear(); - - while (!p.empty() && p.front() == 0) { - sol.push_back(0.0); - p.erase(p.begin()); //se i coefficienti bassi sono zero, ci sono soluzioni pari a 0.0. le metto, - } //e abbasso il grado del polinomio(piu' veloce) - - switch (p.size()) { - case 0: - if (sol.empty()) - return INFINITE_SOLUTIONS; - break; - case 1: //no solutions - break; - case 2: - sol.push_back(-p[0] / p[1]); - break; - case 3: - rootForQuadraticEquation(p, sol); - break; - case 4: - rootForCubicEquation(p, sol); - break; - default: - rootForGreaterThanThreeEquation(p, sol); - } - return sol.size(); +int rootFinding(const std::vector &in_poly, std::vector &sol) { + // per ora risolvo solo i polinomi di grado al piu' pari a 3 + assert((int)in_poly.size() <= MAX_ORDER); + if (in_poly.empty() || (int)in_poly.size() > MAX_ORDER) return -1; + + std::vector p; + std::copy(in_poly.begin(), in_poly.end(), std::back_inserter(p)); + + // eat zero in poly + while (!p.empty() && isAlmostZero(p.back())) p.pop_back(); + + sol.clear(); + + while (!p.empty() && p.front() == 0) { + sol.push_back(0.0); + p.erase(p.begin()); // se i coefficienti bassi sono zero, ci sono soluzioni + // pari a 0.0. le metto, + } // e abbasso il grado del polinomio(piu' veloce) + + switch (p.size()) { + case 0: + if (sol.empty()) return INFINITE_SOLUTIONS; + break; + case 1: // no solutions + break; + case 2: + sol.push_back(-p[0] / p[1]); + break; + case 3: + rootForQuadraticEquation(p, sol); + break; + case 4: + rootForCubicEquation(p, sol); + break; + default: + rootForGreaterThanThreeEquation(p, sol); + } + return sol.size(); } //----------------------------------------------------------------------------- /* */ -int numberOfRootsInInterval(int order, const double *polyH, double min, double max) -{ - poly sseq[MAX_ORDER]; +int numberOfRootsInInterval(int order, const double *polyH, double min, + double max) { + poly sseq[MAX_ORDER]; - int - i, - nchanges_0, - nchanges_1, - np; + int i, nchanges_0, nchanges_1, np; - if (order > MAX_ORDER) - return -1; + if (order > MAX_ORDER) return -1; - while (polyH[order] == 0.0 && order > 0) - --order; + while (polyH[order] == 0.0 && order > 0) --order; - // init a sturm's sequence with our polynomious - for (i = order; i >= 0; --i) - sseq[0].coef[i] = polyH[i]; + // init a sturm's sequence with our polynomious + for (i = order; i >= 0; --i) sseq[0].coef[i] = polyH[i]; - // build the Sturm sequence - np = buildsturm(order, sseq); + // build the Sturm sequence + np = buildsturm(order, sseq); - //compute number of variation on 0.0 - nchanges_0 = numchanges(np, sseq, min); + // compute number of variation on 0.0 + nchanges_0 = numchanges(np, sseq, min); - nchanges_1 = numchanges(np, sseq, max); + nchanges_1 = numchanges(np, sseq, max); - return (nchanges_0 - nchanges_1); + return (nchanges_0 - nchanges_1); } //----------------------------------------------------------------------------- -double quadraticRoot(double a, double b, double c) -{ - double bb, q; - // caso lineare - if (fabs(a) < epsilon) { - if (fabs(b) >= epsilon) - return -c / b; - return 1; - } - bb = b * b; - q = bb - 4.0 * a * c; - if (q < 0.0) - return 1; - q = sqrt(q); - if (b < 0.0) - q = -q; - q = -0.5 * (b + q); - double root1 = -1; - double root2 = -1; - if (fabs(q) >= epsilon) - root1 = c / q; - if (fabs(a) >= epsilon) - root2 = q / a; - if (0.0 - epsilon <= root1 && root1 <= 1.0 + epsilon) - return root1; - if (0.0 - epsilon <= root2 && root2 <= 1.0 + epsilon) - return root2; - return 1; +double quadraticRoot(double a, double b, double c) { + double bb, q; + // caso lineare + if (fabs(a) < epsilon) { + if (fabs(b) >= epsilon) return -c / b; + return 1; + } + bb = b * b; + q = bb - 4.0 * a * c; + if (q < 0.0) return 1; + q = sqrt(q); + if (b < 0.0) q = -q; + q = -0.5 * (b + q); + double root1 = -1; + double root2 = -1; + if (fabs(q) >= epsilon) root1 = c / q; + if (fabs(a) >= epsilon) root2 = q / a; + if (0.0 - epsilon <= root1 && root1 <= 1.0 + epsilon) return root1; + if (0.0 - epsilon <= root2 && root2 <= 1.0 + epsilon) return root2; + return 1; } //----------------------------------------------------------------------------- -double cubicRoot(double a, double b, double c, double d) -{ - double A, Q, R, QQQ, RR; - double theta; - /* Test for a quadratic or linear degeneracy */ - if (fabs(a) < epsilon) - return quadraticRoot(b, c, d); - /* Normalize */ - b /= a; - c /= a; - d /= a; - a = 1.0; - /* Compute discriminants */ - Q = (b * b - 3.0 * c) / 9.0; - QQQ = Q * Q * Q; - R = (2.0 * b * b * b - 9.0 * b * c + 27.0 * d) / 54.0; - RR = R * R; - /* Three real roots */ - if (RR < QQQ) { - theta = acos(R / sqrt(QQQ)); - double root[3]; - root[0] = root[1] = root[2] = -2.0 * sqrt(Q); - root[0] *= cos(theta / 3.0); - root[1] *= cos((theta + 2 * TConsts::pi) / 3.0); - root[2] *= cos((theta - 2 * TConsts::pi) / 3.0); - root[0] -= b / 3.0; - root[1] -= b / 3.0; - root[2] -= b / 3.0; - if (0.0 - epsilon < root[0] && root[0] < 1.0 + epsilon) - return root[0]; - if (0.0 - epsilon < root[1] && root[1] < 1.0 + epsilon) - return root[1]; - if (0.0 - epsilon < root[2] && root[2] < 1.0 + epsilon) - return root[2]; - return 1; - } - /* One real root */ - else { - double root = 0; - A = -pow(fabs(R) + sqrt(RR - QQQ), 1.0 / 3.0); - if (A != 0.0) { - if (R < 0.0) - A = -A; - root = A + Q / A; - } - root -= b / 3.0; - if (0.0 - epsilon < root && root < 1.0 + epsilon) - return root; - return 1; - } +double cubicRoot(double a, double b, double c, double d) { + double A, Q, R, QQQ, RR; + double theta; + /* Test for a quadratic or linear degeneracy */ + if (fabs(a) < epsilon) return quadraticRoot(b, c, d); + /* Normalize */ + b /= a; + c /= a; + d /= a; + a = 1.0; + /* Compute discriminants */ + Q = (b * b - 3.0 * c) / 9.0; + QQQ = Q * Q * Q; + R = (2.0 * b * b * b - 9.0 * b * c + 27.0 * d) / 54.0; + RR = R * R; + /* Three real roots */ + if (RR < QQQ) { + theta = acos(R / sqrt(QQQ)); + double root[3]; + root[0] = root[1] = root[2] = -2.0 * sqrt(Q); + root[0] *= cos(theta / 3.0); + root[1] *= cos((theta + M_2PI) / 3.0); + root[2] *= cos((theta - M_2PI) / 3.0); + root[0] -= b / 3.0; + root[1] -= b / 3.0; + root[2] -= b / 3.0; + if (0.0 - epsilon < root[0] && root[0] < 1.0 + epsilon) return root[0]; + if (0.0 - epsilon < root[1] && root[1] < 1.0 + epsilon) return root[1]; + if (0.0 - epsilon < root[2] && root[2] < 1.0 + epsilon) return root[2]; + return 1; + } + /* One real root */ + else { + double root = 0; + A = -pow(fabs(R) + sqrt(RR - QQQ), 1.0 / 3.0); + if (A != 0.0) { + if (R < 0.0) A = -A; + root = A + Q / A; + } + root -= b / 3.0; + if (0.0 - epsilon < root && root < 1.0 + epsilon) return root; + return 1; + } } //----------------------------------------------------------------------------- diff --git a/toonz/sources/common/tcore/trandom.cpp b/toonz/sources/common/tcore/trandom.cpp index a408f88..d13e78c 100644 --- a/toonz/sources/common/tcore/trandom.cpp +++ b/toonz/sources/common/tcore/trandom.cpp @@ -2,173 +2,159 @@ #include "trandom.h" -TRandom::RANDOM_FLOAT_TYPE TRandom::RandomFloatType = TRandom::RANDOM_FLOAT_TYPE_NONE; +TRandom::RANDOM_FLOAT_TYPE TRandom::RandomFloatType = + TRandom::RANDOM_FLOAT_TYPE_NONE; -TRandom::TRandom(UINT _seed) - : seed(_seed) -{ - if (RandomFloatType == TRandom::RANDOM_FLOAT_TYPE_NONE) - setRandomFloatType(); - reset(); +TRandom::TRandom(UINT _seed) : seed(_seed) { + if (RandomFloatType == TRandom::RANDOM_FLOAT_TYPE_NONE) setRandomFloatType(); + reset(); } //-------------------------------------------------------------------------- -TRandom::~TRandom() -{ -} +TRandom::~TRandom() {} //-------------------------------------------------------------------------- -void TRandom::setSeed(UINT s) -{ - seed = s; - reset(); +void TRandom::setSeed(UINT s) { + seed = s; + reset(); } //-------------------------------------------------------------------------- -void TRandom::reset() -{ - UINT uj, uk; - int i, ii, k; - - assert(sizeof(UINT) == 32 / 8); - - uj = 161803398 - seed; - ran[55] = uj; - uk = 1; - for (i = 1; i <= 54; i++) { - ii = (21 * i) % 55; - ran[ii] = uk; - uk = uj - uk; - uj = ran[ii]; - } - for (k = 1; k <= 4; k++) - for (i = 1; i <= 55; i++) - ran[i] -= ran[1 + (i + 30) % 55]; - idx1 = 55; - idx2 = 31; +void TRandom::reset() { + UINT uj, uk; + int i, ii, k; + + assert(sizeof(UINT) == 32 / 8); + + uj = 161803398 - seed; + ran[55] = uj; + uk = 1; + for (i = 1; i <= 54; i++) { + ii = (21 * i) % 55; + ran[ii] = uk; + uk = uj - uk; + uj = ran[ii]; + } + for (k = 1; k <= 4; k++) + for (i = 1; i <= 55; i++) ran[i] -= ran[1 + (i + 30) % 55]; + idx1 = 55; + idx2 = 31; } //-------------------------------------------------------------------------- -inline void TRandom::setRandomFloatType() -{ - UINT u; - - assert(sizeof(float) == sizeof(UINT)); - u = 0x3f800000; - if ((*(float *)&u) == 1.0F) - RandomFloatType = RANDOM_FLOAT_TYPE_1; - else { - u = 0x0000803f; - if ((*(float *)&u) == 1.0F) - RandomFloatType = RANDOM_FLOAT_TYPE_2; - else - assert(0); - } +inline void TRandom::setRandomFloatType() { + UINT u; + + assert(sizeof(float) == sizeof(UINT)); + u = 0x3f800000; + if ((*(float *)&u) == 1.0F) + RandomFloatType = RANDOM_FLOAT_TYPE_1; + else { + u = 0x0000803f; + if ((*(float *)&u) == 1.0F) + RandomFloatType = RANDOM_FLOAT_TYPE_2; + else + assert(0); + } } //-------------------------------------------------------------------------- -inline UINT TRandom::getNextUINT() -{ - idx1++; - if (idx1 == 56) - idx1 = 1; - idx2++; - if (idx2 == 56) - idx2 = 1; - ran[idx1] = ran[idx1] - ran[idx2]; - return ran[idx1]; +inline UINT TRandom::getNextUINT() { + idx1++; + if (idx1 == 56) idx1 = 1; + idx2++; + if (idx2 == 56) idx2 = 1; + ran[idx1] = ran[idx1] - ran[idx2]; + return ran[idx1]; } //-------------------------------------------------------------------------- -UINT TRandom::getUInt(UINT end) // [0,end[ +UINT TRandom::getUInt(UINT end) // [0,end[ { - if (end == 0) - return 0; - UINT u = getNextUINT(); - if (end == c_maxuint) - return u; + if (end == 0) return 0; + UINT u = getNextUINT(); + if (end == c_maxuint) return u; - return u % end; + return u % end; } //-------------------------------------------------------------------------- -int TRandom::getInt(int begin, int end) // [begin, end[ +int TRandom::getInt(int begin, int end) // [begin, end[ { - assert(end >= begin); - int limit = end - begin; - if (limit == 0) // end == begin - return begin; - UINT u = getNextUINT(); - return u % limit + begin; + assert(end >= begin); + int limit = end - begin; + if (limit == 0) // end == begin + return begin; + UINT u = getNextUINT(); + return u % limit + begin; } //-------------------------------------------------------------------------- -float TRandom::getFloat() // [0,1[ +float TRandom::getFloat() // [0,1[ { - UINT u = getNextUINT(); - - switch (RandomFloatType) { - case RANDOM_FLOAT_TYPE_1: - u = (u >> 5) & 0x007fffff | 0x3f800000; - break; - case RANDOM_FLOAT_TYPE_2: - u = u & 0xffff7f00 | 0x0000803f; - break; - default: - assert(0); - u = 0; - break; - } - return (*(float *)&u) - 1.0F; + UINT u = getNextUINT(); + + switch (RandomFloatType) { + case RANDOM_FLOAT_TYPE_1: + u = (u >> 5) & 0x007fffff | 0x3f800000; + break; + case RANDOM_FLOAT_TYPE_2: + u = u & 0xffff7f00 | 0x0000803f; + break; + default: + assert(0); + u = 0; + break; + } + return (*(float *)&u) - 1.0F; } //-------------------------------------------------------------------------- -float TRandom::getFloat(float end) // [0, end[ +float TRandom::getFloat(float end) // [0, end[ { - return getFloat() * end; + return getFloat() * end; } //-------------------------------------------------------------------------- -float TRandom::getFloat(float begin, float end) // [begin, end[ +float TRandom::getFloat(float begin, float end) // [begin, end[ { - assert(end >= begin); - return (getFloat() * (end - begin)) + begin; + assert(end >= begin); + return (getFloat() * (end - begin)) + begin; } //-------------------------------------------------------------------------- -bool TRandom::getBool() -{ - UINT u = getNextUINT(); - return u & 1; +bool TRandom::getBool() { + UINT u = getNextUINT(); + return u & 1; } //-------------------------------------------------------------------------- -double TRandom::getDouble() // [0,1[ +double TRandom::getDouble() // [0,1[ { - return getFloat(); + return getFloat(); #ifdef DA_RIVEDERE_O_PROPRIO_IMPLEMENTARE - UINT low = getNextUINT(); - UINT high = getNextUINT(); - double value = 0; + UINT low = getNextUINT(); + UINT high = getNextUINT(); + double value = 0; - void *ptr = &value; - UINT *retL = (UINT *)ptr; - UINT *retH = retL + 1; + void *ptr = &value; + UINT *retL = (UINT *)ptr; + UINT *retH = retL + 1; /* // questa parte e' stata commentata perche' su tutte le piattaforme il tipo -//di float e' RANDOM_FLOAT_TYPE_1ma su irix c'e' bisogno di eseguire le +//di float e' RANDOM_FLOAT_TYPE_1ma su irix c'e' bisogno di eseguire le //istruzioni sotto RANDOM_FLOAT_TYPE_2 switch (RandomFloatType) { @@ -187,22 +173,22 @@ switch (RandomFloatType) case RANDOM_FLOAT_TYPE_2: *retH = low; *retL = (high >> 5) & 0x007fffff | 0x3ff00000; break; - //!!!!!occhio andrebbe sopra il break + //!!!!!occhio andrebbe sopra il break return value-1.0; - default: assert (0); + default: assert (0); } return -1; */ #ifndef __sgi - *retH = high; - *retH &= 0x007fffff; - *retH |= 0x3ff00000; - *retL = low; - return value - 1.0; + *retH = high; + *retH &= 0x007fffff; + *retH |= 0x3ff00000; + *retL = low; + return value - 1.0; #else - *retH = low; - *retL = (high >> 5) & 0x007fffff | 0x3ff00000; - return value - 1.0; + *retH = low; + *retL = (high >> 5) & 0x007fffff | 0x3ff00000; + return value - 1.0; #endif #endif diff --git a/toonz/sources/common/tcore/tsmartpointer.cpp b/toonz/sources/common/tcore/tsmartpointer.cpp index f3cab2a..27fd24a 100644 --- a/toonz/sources/common/tcore/tsmartpointer.cpp +++ b/toonz/sources/common/tcore/tsmartpointer.cpp @@ -5,8 +5,7 @@ //------------------------------------------------------------------- -namespace -{ +namespace { //------------------------------------------------------------------- @@ -17,23 +16,21 @@ TAtomicVarPtr instanceCounts[maxClassCode + 1]; //------------------------------------------------------------------- -inline TAtomicVar &getInstanceCounter(TINT32 classCode) -{ - assert(0 <= classCode && classCode <= maxClassCode); - TAtomicVarPtr &instanceCountPtr = instanceCounts[classCode]; - if (instanceCountPtr == 0) { - static TThread::Mutex mutex; - TThread::MutexLocker g(&mutex); - if (instanceCountPtr == 0) - instanceCountPtr = new TAtomicVar(); - } - assert(instanceCountPtr); - return *instanceCountPtr; +inline TAtomicVar &getInstanceCounter(TINT32 classCode) { + assert(0 <= classCode && classCode <= maxClassCode); + TAtomicVarPtr &instanceCountPtr = instanceCounts[classCode]; + if (instanceCountPtr == 0) { + static TThread::Mutex mutex; + TThread::MutexLocker g(&mutex); + if (instanceCountPtr == 0) instanceCountPtr = new TAtomicVar(); + } + assert(instanceCountPtr); + return *instanceCountPtr; } //------------------------------------------------------------------- -} // namespace +} // namespace //------------------------------------------------------------------- @@ -41,26 +38,24 @@ inline TAtomicVar &getInstanceCounter(TINT32 classCode) const TINT32 TSmartObject::m_unknownClassCode = 0; #endif -void TSmartObject::incrementInstanceCount() -{ +void TSmartObject::incrementInstanceCount() { #ifdef INSTANCE_COUNT_ENABLED - TAtomicVar &instanceCount = getInstanceCounter(m_classCodeRef); - ++instanceCount; + TAtomicVar &instanceCount = getInstanceCounter(m_classCodeRef); + ++instanceCount; #else - assert(0); + assert(0); #endif } //------------------------------------------------------------------- -void TSmartObject::decrementInstanceCount() -{ +void TSmartObject::decrementInstanceCount() { #ifdef INSTANCE_COUNT_ENABLED - TAtomicVar &instanceCount = getInstanceCounter(m_classCodeRef); - assert(instanceCount > 0); - --instanceCount; + TAtomicVar &instanceCount = getInstanceCounter(m_classCodeRef); + assert(instanceCount > 0); + --instanceCount; #else - assert(0); + assert(0); #endif } @@ -68,16 +63,15 @@ void TSmartObject::decrementInstanceCount() TINT32 TSmartObject::getInstanceCount(ClassCode #ifdef INSTANCE_COUNT_ENABLED - code + code #endif - ) -{ + ) { #ifdef INSTANCE_COUNT_ENABLED - TAtomicVar &instanceCount = getInstanceCounter(code); - return instanceCount; + TAtomicVar &instanceCount = getInstanceCounter(code); + return instanceCount; #else - assert(0); - return 0; + assert(0); + return 0; #endif } diff --git a/toonz/sources/common/tcore/tstopwatch.cpp b/toonz/sources/common/tcore/tstopwatch.cpp index 5d7601f..5a993a8 100644 --- a/toonz/sources/common/tcore/tstopwatch.cpp +++ b/toonz/sources/common/tcore/tstopwatch.cpp @@ -2,11 +2,11 @@ #include "tstopwatch.h" -#include +#include #ifdef _WIN32 #include -#else //_WIN32 +#else //_WIN32 #if defined(__APPLE_CC__) #include @@ -33,18 +33,16 @@ extern "C" long sysconf(int); TStopWatch TStopWatch::StopWatch[10]; -enum TimerType { TTUUnknown, - TTUHiRes, - TTUTickCount }; +enum TimerType { TTUUnknown, TTUHiRes, TTUTickCount }; static void determineTimer(); #ifdef _WIN32 static TimerType timerToUse = TTUUnknown; -static LARGE_INTEGER perfFreq; // ticks per second -static int perfFreqAdjust = 0; // in case Freq is too big -static int overheadTicks = 0; // overhead in calling timer +static LARGE_INTEGER perfFreq; // ticks per second +static int perfFreqAdjust = 0; // in case Freq is too big +static int overheadTicks = 0; // overhead in calling timer #else static TimerType timerToUse = TTUTickCount; @@ -55,130 +53,118 @@ using namespace std; //----------------------------------------------------------- TStopWatch::TStopWatch(std::string name) - : m_name(name), m_active(false), m_isRunning(false) -{ - if (timerToUse == TTUUnknown) - determineTimer(); + : m_name(name), m_active(false), m_isRunning(false) { + if (timerToUse == TTUUnknown) determineTimer(); - m_start = 0; + m_start = 0; #ifdef _WIN32 - m_startUser.dwHighDateTime = m_startUser.dwLowDateTime = 0; - m_startSystem.dwHighDateTime = m_startSystem.dwLowDateTime = 0; + m_startUser.dwHighDateTime = m_startUser.dwLowDateTime = 0; + m_startSystem.dwHighDateTime = m_startSystem.dwLowDateTime = 0; #else - m_startUser = 0; - m_startSystem = 0; -#endif //_WIN32 - m_tm = 0; - m_tmUser = 0; - m_tmSystem = 0; + m_startUser = 0; + m_startSystem = 0; +#endif //_WIN32 + m_tm = 0; + m_tmUser = 0; + m_tmSystem = 0; } //----------------------------------------------------------- -TStopWatch::~TStopWatch() -{ - m_active = false; -} +TStopWatch::~TStopWatch() { m_active = false; } //----------------------------------------------------------- -void TStopWatch::setStartToCurrentTime() -{ +void TStopWatch::setStartToCurrentTime() { #ifdef _WIN32 - FILETIME creationTime, exitTime; - BOOL ret = GetProcessTimes(GetCurrentProcess(), // specifies the process of interest - &creationTime, - &exitTime, - &m_startSystem, - &m_startUser); - - if (timerToUse == TTUTickCount) { - m_start = GetTickCount(); - } else { - QueryPerformanceCounter(&m_hrStart); - } + FILETIME creationTime, exitTime; + BOOL ret = + GetProcessTimes(GetCurrentProcess(), // specifies the process of interest + &creationTime, &exitTime, &m_startSystem, &m_startUser); + + if (timerToUse == TTUTickCount) { + m_start = GetTickCount(); + } else { + QueryPerformanceCounter(&m_hrStart); + } #else - struct tms clk; - m_start = times(&clk); - m_startUser = clk.tms_utime; - m_startSystem = clk.tms_stime; -#endif //_WIN32 + struct tms clk; + m_start = times(&clk); + m_startUser = clk.tms_utime; + m_startSystem = clk.tms_stime; +#endif //_WIN32 } //----------------------------------------------------------- -void TStopWatch::reset() -{ - m_tm = 0; - m_tmUser = 0; - m_tmSystem = 0; - setStartToCurrentTime(); +void TStopWatch::reset() { + m_tm = 0; + m_tmUser = 0; + m_tmSystem = 0; + setStartToCurrentTime(); } //----------------------------------------------------------- -void TStopWatch::start(bool resetFlag) -{ - if (resetFlag) - reset(); - if (m_isRunning) - return; - m_active = true; - m_isRunning = true; - setStartToCurrentTime(); +void TStopWatch::start(bool resetFlag) { + if (resetFlag) reset(); + if (m_isRunning) return; + m_active = true; + m_isRunning = true; + setStartToCurrentTime(); } //----------------------------------------------------------- #ifdef _WIN32 -inline __int64 FileTimeToInt64(LPFILETIME pFileTime) -{ - __int64 val; - val = pFileTime->dwHighDateTime; - val <<= 32; - val |= pFileTime->dwLowDateTime; - return val; +inline __int64 FileTimeToInt64(LPFILETIME pFileTime) { + __int64 val; + val = pFileTime->dwHighDateTime; + val <<= 32; + val |= pFileTime->dwLowDateTime; + return val; } -#endif //_WIN32 +#endif //_WIN32 //----------------------------------------------------------- // -// Aggiunge il tempo trascorso fra start(startUser, startSystem) e l'istante corrente +// Aggiunge il tempo trascorso fra start(startUser, startSystem) e l'istante +// corrente // a tm(tmUser, tmSystem) // -static void checkTime(START start, START_USER startUser, START_SYSTEM startSystem, - TM_TOTAL &tm, TM_USER &tmUser, TM_SYSTEM &tmSystem) -{ - assert(timerToUse == TTUTickCount); +static void checkTime(START start, START_USER startUser, + START_SYSTEM startSystem, TM_TOTAL &tm, TM_USER &tmUser, + TM_SYSTEM &tmSystem) { + assert(timerToUse == TTUTickCount); #ifdef _WIN32 - DWORD tm_stop; - FILETIME creationTime, exitTime, stopSystem, stopUser; - BOOL ret = GetProcessTimes(GetCurrentProcess(), // specifies the process of interest - &creationTime, - &exitTime, - &stopSystem, - &stopUser); - tm_stop = GetTickCount(); - assert(tm_stop >= start); - tm += tm_stop - start; //total elapsed time - - tmUser += FileTimeToInt64(&stopUser) - FileTimeToInt64(&startUser); //user elapsed time - tmSystem += FileTimeToInt64(&stopSystem) - FileTimeToInt64(&startSystem); //system elapsed time - -#else // _WIN32 - - struct tms clk; - clock_t tm_stop; - tm_stop = times(&clk); - assert(tm_stop >= start); - tm += tm_stop - start; - tmUser += clk.tms_utime - startUser; - tmSystem += clk.tms_stime - startSystem; - -#endif // _WIN32 + DWORD tm_stop; + FILETIME creationTime, exitTime, stopSystem, stopUser; + BOOL ret = + GetProcessTimes(GetCurrentProcess(), // specifies the process of interest + &creationTime, &exitTime, &stopSystem, &stopUser); + tm_stop = GetTickCount(); + assert(tm_stop >= start); + tm += tm_stop - start; // total elapsed time + + tmUser += FileTimeToInt64(&stopUser) - + FileTimeToInt64(&startUser); // user elapsed time + tmSystem += FileTimeToInt64(&stopSystem) - + FileTimeToInt64(&startSystem); // system elapsed time + +#else // _WIN32 + + struct tms clk; + clock_t tm_stop; + tm_stop = times(&clk); + assert(tm_stop >= start); + tm += tm_stop - start; + tmUser += clk.tms_utime - startUser; + tmSystem += clk.tms_stime - startSystem; + +#endif // _WIN32 } //----------------------------------------------------------- @@ -188,250 +174,233 @@ static void checkTime(START start, START_USER startUser, START_SYSTEM startSyste // // come checkTime, ma usa i timer ad alta risoluzione // -namespace -{ +namespace { //----------------------------------------------------------- -void hrCheckTime(LARGE_INTEGER start, START_USER startUser, START_SYSTEM startSystem, - TM_TOTAL &tm, TM_USER &tmUser, TM_SYSTEM &tmSystem) -{ - assert(timerToUse != TTUTickCount); - - LARGE_INTEGER hrTm_stop; - FILETIME creationTime, exitTime, stopSystem, stopUser; - BOOL ret = GetProcessTimes(GetCurrentProcess(), // specifies the process of interest - &creationTime, - &exitTime, - &stopSystem, - &stopUser); - - QueryPerformanceCounter(&hrTm_stop); - assert(hrTm_stop.HighPart > start.HighPart || - hrTm_stop.HighPart == start.HighPart && hrTm_stop.LowPart >= start.LowPart); - - LARGE_INTEGER Freq = perfFreq; - int Oht = overheadTicks; - - LARGE_INTEGER dtime; - //faccio "a mano" la differenza dtime = m_tStop - m_tStart - dtime.HighPart = hrTm_stop.HighPart - start.HighPart; - if (hrTm_stop.LowPart >= start.LowPart) - dtime.LowPart = hrTm_stop.LowPart - start.LowPart; - else { - assert(dtime.HighPart > 0); - dtime.HighPart--; - dtime.LowPart = hrTm_stop.LowPart + ~start.LowPart + 1; - } - - int shift = 0; - if (Freq.HighPart > 0) { - int h = Freq.HighPart; - while (h > 0) { - h >>= 1; - shift++; - } - } - if ((dtime.HighPart >> shift) > 0) { - int h = dtime.HighPart >> shift; - while (h > 0) { - h >>= 1; - shift++; - } - } - if (shift > 0) { - dtime.QuadPart = Int64ShrlMod32(dtime.QuadPart, shift); - Freq.QuadPart = Int64ShrlMod32(Freq.QuadPart, shift); - } - assert(Freq.HighPart == 0); - assert(dtime.HighPart == 0); - - double totalTime = 1000.0 * dtime.LowPart / Freq.LowPart; - tm += troundp(totalTime); - - tmUser += FileTimeToInt64(&stopUser) - FileTimeToInt64(&startUser); //user elapsed time - tmSystem += FileTimeToInt64(&stopSystem) - FileTimeToInt64(&startSystem); //system elapsed time +void hrCheckTime(LARGE_INTEGER start, START_USER startUser, + START_SYSTEM startSystem, TM_TOTAL &tm, TM_USER &tmUser, + TM_SYSTEM &tmSystem) { + assert(timerToUse != TTUTickCount); + + LARGE_INTEGER hrTm_stop; + FILETIME creationTime, exitTime, stopSystem, stopUser; + BOOL ret = + GetProcessTimes(GetCurrentProcess(), // specifies the process of interest + &creationTime, &exitTime, &stopSystem, &stopUser); + + QueryPerformanceCounter(&hrTm_stop); + assert(hrTm_stop.HighPart > start.HighPart || + hrTm_stop.HighPart == start.HighPart && + hrTm_stop.LowPart >= start.LowPart); + + LARGE_INTEGER Freq = perfFreq; + int Oht = overheadTicks; + + LARGE_INTEGER dtime; + // faccio "a mano" la differenza dtime = m_tStop - m_tStart + dtime.HighPart = hrTm_stop.HighPart - start.HighPart; + if (hrTm_stop.LowPart >= start.LowPart) + dtime.LowPart = hrTm_stop.LowPart - start.LowPart; + else { + assert(dtime.HighPart > 0); + dtime.HighPart--; + dtime.LowPart = hrTm_stop.LowPart + ~start.LowPart + 1; + } + + int shift = 0; + if (Freq.HighPart > 0) { + int h = Freq.HighPart; + while (h > 0) { + h >>= 1; + shift++; + } + } + if ((dtime.HighPart >> shift) > 0) { + int h = dtime.HighPart >> shift; + while (h > 0) { + h >>= 1; + shift++; + } + } + if (shift > 0) { + dtime.QuadPart = Int64ShrlMod32(dtime.QuadPart, shift); + Freq.QuadPart = Int64ShrlMod32(Freq.QuadPart, shift); + } + assert(Freq.HighPart == 0); + assert(dtime.HighPart == 0); + + double totalTime = 1000.0 * dtime.LowPart / Freq.LowPart; + tm += troundp(totalTime); + + tmUser += FileTimeToInt64(&stopUser) - + FileTimeToInt64(&startUser); // user elapsed time + tmSystem += FileTimeToInt64(&stopSystem) - + FileTimeToInt64(&startSystem); // system elapsed time } //----------------------------------------------------------- -} //namespace +} // namespace -#endif // _WIN32 +#endif // _WIN32 //----------------------------------------------------------- -void TStopWatch::stop() -{ - if (!m_isRunning) - return; - m_isRunning = false; +void TStopWatch::stop() { + if (!m_isRunning) return; + m_isRunning = false; #ifdef _WIN32 - if (timerToUse == TTUTickCount) - checkTime(m_start, m_startUser, m_startSystem, m_tm, m_tmUser, m_tmSystem); - else - hrCheckTime(m_hrStart, m_startUser, m_startSystem, m_tm, m_tmUser, m_tmSystem); + if (timerToUse == TTUTickCount) + checkTime(m_start, m_startUser, m_startSystem, m_tm, m_tmUser, m_tmSystem); + else + hrCheckTime(m_hrStart, m_startUser, m_startSystem, m_tm, m_tmUser, + m_tmSystem); #else - checkTime(m_start, m_startUser, m_startSystem, m_tm, m_tmUser, m_tmSystem); + checkTime(m_start, m_startUser, m_startSystem, m_tm, m_tmUser, m_tmSystem); #endif } //----------------------------------------------------------- -void TStopWatch::getElapsedTime(TM_TOTAL &tm, TM_USER &user, TM_SYSTEM &system) -{ - if (m_isRunning) { - TM_TOTAL cur_tm = 0; - TM_USER cur_tmUser = 0; - TM_SYSTEM cur_tmSystem = 0; +void TStopWatch::getElapsedTime(TM_TOTAL &tm, TM_USER &user, + TM_SYSTEM &system) { + if (m_isRunning) { + TM_TOTAL cur_tm = 0; + TM_USER cur_tmUser = 0; + TM_SYSTEM cur_tmSystem = 0; #ifdef _WIN32 - if (timerToUse == TTUTickCount) - checkTime(m_start, m_startUser, m_startSystem, cur_tm, cur_tmUser, cur_tmSystem); - else - hrCheckTime(m_hrStart, m_startUser, m_startSystem, cur_tm, cur_tmUser, cur_tmSystem); + if (timerToUse == TTUTickCount) + checkTime(m_start, m_startUser, m_startSystem, cur_tm, cur_tmUser, + cur_tmSystem); + else + hrCheckTime(m_hrStart, m_startUser, m_startSystem, cur_tm, cur_tmUser, + cur_tmSystem); #else - checkTime(m_start, m_startUser, m_startSystem, cur_tm, cur_tmUser, cur_tmSystem); + checkTime(m_start, m_startUser, m_startSystem, cur_tm, cur_tmUser, + cur_tmSystem); #endif - tm = m_tm + cur_tm; - user = m_tmUser + cur_tmUser; - system = m_tmSystem + cur_tmSystem; - } else { - tm = m_tm; - user = m_tmUser; - system = m_tmSystem; - } + tm = m_tm + cur_tm; + user = m_tmUser + cur_tmUser; + system = m_tmSystem + cur_tmSystem; + } else { + tm = m_tm; + user = m_tmUser; + system = m_tmSystem; + } } //----------------------------------------------------------- -TUINT32 TStopWatch::getTotalTime() -{ - TM_TOTAL tm; - TM_USER user; - TM_SYSTEM system; - getElapsedTime(tm, user, system); +TUINT32 TStopWatch::getTotalTime() { + TM_TOTAL tm; + TM_USER user; + TM_SYSTEM system; + getElapsedTime(tm, user, system); #ifdef _WIN32 - return tm; + return tm; #else - return (TINT32)(tm * 1000) / STW_TICKS_PER_SECOND; -#endif //_WIN32 + return (TINT32)(tm * 1000) / STW_TICKS_PER_SECOND; +#endif //_WIN32 } //----------------------------------------------------------- -TUINT32 TStopWatch::getUserTime() -{ - TM_TOTAL tm; - TM_USER user; - TM_SYSTEM system; - getElapsedTime(tm, user, system); +TUINT32 TStopWatch::getUserTime() { + TM_TOTAL tm; + TM_USER user; + TM_SYSTEM system; + getElapsedTime(tm, user, system); #ifdef _WIN32 - return (TINT32)(user / 10000); + return (TINT32)(user / 10000); #else - return (TINT32)(user * 1000) / STW_TICKS_PER_SECOND; -#endif //_WIN32 + return (TINT32)(user * 1000) / STW_TICKS_PER_SECOND; +#endif //_WIN32 } //----------------------------------------------------------- -TUINT32 TStopWatch::getSystemTime() -{ - TM_TOTAL tm; - TM_USER user; - TM_SYSTEM system; - getElapsedTime(tm, user, system); +TUINT32 TStopWatch::getSystemTime() { + TM_TOTAL tm; + TM_USER user; + TM_SYSTEM system; + getElapsedTime(tm, user, system); #ifdef _WIN32 - return (TINT32)(system / 10000); + return (TINT32)(system / 10000); #else - return (TINT32)(system * 1000) / STW_TICKS_PER_SECOND; -#endif //_WIN32 + return (TINT32)(system * 1000) / STW_TICKS_PER_SECOND; +#endif //_WIN32 } //----------------------------------------------------------- -TStopWatch::operator string() -{ - char buffer[256]; - ostrstream out(buffer, sizeof(buffer)); - out << m_name.c_str() << ": " << (int)getTotalTime() << " u" << (int)getUserTime() << " s" << (TINT32)getSystemTime(); - return string(buffer, out.pcount()); +TStopWatch::operator string() { + ostringstream out; + out << m_name.c_str() << ": " << (int)getTotalTime() << " u" + << (int)getUserTime() << " s" << (TINT32)getSystemTime(); + return out.str(); } //------------------------------------------------------------ -void TStopWatch::print() -{ - print(cout); -} +void TStopWatch::print() { print(cout); } //------------------------------------------------------------------------------------------- -void TStopWatch::print(ostream &out) -{ - string s(*this); - out << s.c_str() << endl; +void TStopWatch::print(ostream &out) { + string s(*this); + out << s.c_str() << endl; } //------------------------------------------------------------------------------------------- -void TStopWatch::printGlobals(ostream &out) -{ - const int n = sizeof(StopWatch) / sizeof(StopWatch[0]); - for (int i = 0; i < n; i++) - if (StopWatch[i].m_active) - StopWatch[i].print(out); +void TStopWatch::printGlobals(ostream &out) { + const int n = sizeof(StopWatch) / sizeof(StopWatch[0]); + for (int i = 0; i < n; i++) + if (StopWatch[i].m_active) StopWatch[i].print(out); } //------------------------------------------------------------------------------------------- -void TStopWatch::printGlobals() -{ - printGlobals(cout); -} +void TStopWatch::printGlobals() { printGlobals(cout); } //----------------------------------------------------------- #ifdef _WIN32 -void dummyFunction() -{ - // It's used just to calculate the overhead - return; +void dummyFunction() { + // It's used just to calculate the overhead + return; } -void determineTimer() -{ - - void (*pFunc)() = dummyFunction; - // cout << "DETERMINE TIMER" << endl; - // Assume the worst - timerToUse = TTUTickCount; - if (QueryPerformanceFrequency(&perfFreq)) { - // We can use hires timer, determine overhead - timerToUse = TTUHiRes; - overheadTicks = 200; - for (int i = 0; i < 20; i++) { - LARGE_INTEGER b, e; - int Ticks; - QueryPerformanceCounter(&b); - (*pFunc)(); - QueryPerformanceCounter(&e); - Ticks = e.LowPart - b.LowPart; - if (Ticks >= 0 && Ticks < overheadTicks) - overheadTicks = Ticks; - } - // See if Freq fits in 32 bits; if not lose some precision - perfFreqAdjust = 0; - int High32 = perfFreq.HighPart; - while (High32) { - High32 >>= 1; - perfFreqAdjust++; - } - } +void determineTimer() { + void (*pFunc)() = dummyFunction; + // cout << "DETERMINE TIMER" << endl; + // Assume the worst + timerToUse = TTUTickCount; + if (QueryPerformanceFrequency(&perfFreq)) { + // We can use hires timer, determine overhead + timerToUse = TTUHiRes; + overheadTicks = 200; + for (int i = 0; i < 20; i++) { + LARGE_INTEGER b, e; + int Ticks; + QueryPerformanceCounter(&b); + (*pFunc)(); + QueryPerformanceCounter(&e); + Ticks = e.LowPart - b.LowPart; + if (Ticks >= 0 && Ticks < overheadTicks) overheadTicks = Ticks; + } + // See if Freq fits in 32 bits; if not lose some precision + perfFreqAdjust = 0; + int High32 = perfFreq.HighPart; + while (High32) { + High32 >>= 1; + perfFreqAdjust++; + } + } } #else -void determineTimer() -{ -} +void determineTimer() {} #endif diff --git a/toonz/sources/common/tcore/tstring.cpp b/toonz/sources/common/tcore/tstring.cpp index fa123e6..8bbc83c 100644 --- a/toonz/sources/common/tcore/tstring.cpp +++ b/toonz/sources/common/tcore/tstring.cpp @@ -15,175 +15,153 @@ #include -class TStringConvertException : public TException -{ - std::string m_string; +class TStringConvertException : public TException { + std::string m_string; public: - TStringConvertException(const std::string str) : m_string(str) {} + TStringConvertException(const std::string str) : m_string(str) {} }; -std::wstring to_wstring(std::string s) -{ +std::wstring to_wstring(std::string s) { #ifdef TNZCORE_LIGHT - std::wstring ws; - ws.assign(s.begin(), s.end()); - return ws; + std::wstring ws; + ws.assign(s.begin(), s.end()); + return ws; #else - QString testString = QString::fromStdString(s); - QString qString = QString::fromUtf8(s.c_str()); + QString testString = QString::fromStdString(s); + QString qString = QString::fromUtf8(s.c_str()); - // To detect if 's' is UTF-8 encoded or not - if (qString != testString && std::string(qString.toUtf8()) == s) - return qString.toStdWString(); - else - return testString.toStdWString(); + // To detect if 's' is UTF-8 encoded or not + if (qString != testString && std::string(qString.toUtf8()) == s) + return qString.toStdWString(); + else + return testString.toStdWString(); #endif } -std::string to_string(std::wstring ws) -{ +std::string to_string(std::wstring ws) { #ifdef TNZCORE_LIGHT - std::string s; - s.assign(ws.begin(), ws.end()); - return s; + std::string s; + s.assign(ws.begin(), ws.end()); + return s; #else - QString const qString = QString::fromStdWString(ws); + QString const qString = QString::fromStdWString(ws); - // Test if 'ws' is not unicode (UTF-8) - if (qString.toLatin1() == qString) - return qString.toStdString(); + // Test if 'ws' is not unicode (UTF-8) + if (qString.toLatin1() == qString) return qString.toStdString(); - return std::string(qString.toUtf8()); + return std::string(qString.toUtf8()); #endif } -std::string to_string(const TFilePath &fp) -{ - return ::to_string(fp.getWideString()); +std::string to_string(const TFilePath &fp) { + return ::to_string(fp.getWideString()); } /*! - The default precision is six decimal places. If the + The default precision is six decimal places. If the precision is less than of the decimal places in the fractonal part, the remainder is not cut off but rounded. */ -std::string to_string(double value, int prec) -{ - if (prec < 0) { - return std::to_string(value); - } - - std::ostringstream out; - out.setf(std::ios_base::fixed, std::ios_base::floatfield); - out.precision(prec); - out << value; - return out.str(); +std::string to_string(double value, int prec) { + if (prec < 0) { + return std::to_string(value); + } + + std::ostringstream out; + out.setf(std::ios_base::fixed, std::ios_base::floatfield); + out.precision(prec); + out << value; + return out.str(); } -std::string to_string(void* p) -{ - std::ostringstream out; - out << p; - return out.str(); +std::string to_string(void *p) { + std::ostringstream out; + out << p; + return out.str(); } -bool isInt(std::string s) -{ - int i = 0, len = (int)s.size(); - if (len == 0) - return false; - if (s[0] == '-') { - if (len == 1) - return false; - else - i++; - } - - while (i < len) { - if (s[i] < '0' || s[i] > '9') - return false; - i++; - } - return true; +bool isInt(std::string s) { + int i = 0, len = (int)s.size(); + if (len == 0) return false; + if (s[0] == '-') { + if (len == 1) + return false; + else + i++; + } + + while (i < len) { + if (s[i] < '0' || s[i] > '9') return false; + i++; + } + return true; } -bool isDouble(std::string s) -{ - int i = 0, len = (int)s.size(); - if (len == 0) - return false; - if (i < len && s[i] == '-') - i++; - while (i < len && s[i] != '.') { - if (s[i] < '0' || s[i] > '9') - return false; - i++; - } - if (i >= len) - return true; - i++; - while (i < len) { - if (s[i] < '0' || s[i] > '9') - return false; - i++; - } - return true; +bool isDouble(std::string s) { + int i = 0, len = (int)s.size(); + if (len == 0) return false; + if (i < len && s[i] == '-') i++; + while (i < len && s[i] != '.') { + if (s[i] < '0' || s[i] > '9') return false; + i++; + } + if (i >= len) return true; + i++; + while (i < len) { + if (s[i] < '0' || s[i] > '9') return false; + i++; + } + return true; } bool isInt(std::wstring s) { return isInt(::to_string(s)); } bool isDouble(std::wstring s) { return isDouble(::to_string(s)); } -std::string toUpper(std::string a) -{ +std::string toUpper(std::string a) { #ifdef _WIN32 - return _strupr(const_cast(a.c_str())); + return _strupr(const_cast(a.c_str())); #else - std::string ret = a; - for (int i = 0; i < (int)ret.length(); i++) - ret[i] = toupper(ret[i]); - return ret; + std::string ret = a; + for (int i = 0; i < (int)ret.length(); i++) ret[i] = toupper(ret[i]); + return ret; #endif } -std::string toLower(std::string a) -{ +std::string toLower(std::string a) { #ifdef _WIN32 - return _strlwr(const_cast(a.c_str())); + return _strlwr(const_cast(a.c_str())); #else - std::string ret = a; - for (int i = 0; i < (int)ret.length(); i++) - ret[i] = tolower(ret[i]); - return ret; + std::string ret = a; + for (int i = 0; i < (int)ret.length(); i++) ret[i] = tolower(ret[i]); + return ret; #endif } -std::wstring toUpper(std::wstring a) -{ +std::wstring toUpper(std::wstring a) { #ifdef _WIN32 - return _wcsupr(const_cast(a.c_str())); + return _wcsupr(const_cast(a.c_str())); #else - std::wstring ret; - for (int i = 0; i < (int)a.length(); i++) { - wchar_t c = towupper(a[i]); - ret += c; - } - return ret; + std::wstring ret; + for (int i = 0; i < (int)a.length(); i++) { + wchar_t c = towupper(a[i]); + ret += c; + } + return ret; #endif } -std::wstring toLower(std::wstring a) -{ +std::wstring toLower(std::wstring a) { #ifdef _WIN32 - return _wcslwr(const_cast(a.c_str())); + return _wcslwr(const_cast(a.c_str())); #else - std::wstring ret; - for (int i = 0; i < (int)a.length(); i++) { - wchar_t c = towlower(a[i]); - ret += c; - } - return ret; + std::wstring ret; + for (int i = 0; i < (int)a.length(); i++) { + wchar_t c = towlower(a[i]); + ret += c; + } + return ret; #endif } diff --git a/toonz/sources/common/tcore/tthread.cpp b/toonz/sources/common/tcore/tthread.cpp index 3189b8c..3e99c35 100644 --- a/toonz/sources/common/tcore/tthread.cpp +++ b/toonz/sources/common/tcore/tthread.cpp @@ -19,7 +19,7 @@ // tcg includes #include "tcg/tcg_pool.h" -//Qt includes +// Qt includes #include #include #include @@ -33,7 +33,7 @@ // Paradigms of the Executor tasks management //-------------------------------------------------- -//Basics: +// Basics: // * Tasks added by Executors are always stored in a global QMultiMap first - // ordering primarily being the schedulingPriority(), and insertion instant // (implicit) when they have the same scheduling priority. @@ -43,58 +43,88 @@ // * Worker threads are stored in a global set. // * When a task is added or a task has been performed, the workers list is // refreshed, possibly adding new Workers for some executable tasks. -// * When a worker ends a task, it automatically takes a new one before refreshing +// * When a worker ends a task, it automatically takes a new one before +// refreshing // the workers list. If no task can be taken, by default the thread exits and // invokes its own destruction. // * The thread may instead be put to rest if explicitly told by the user with // the appropriate method. -//Default execution conditions: -// * A task is executable if, by default, its task load added to the sum of that of -// all other active tasks does not exceed the available resources of the system +// Default execution conditions: +// * A task is executable if, by default, its task load added to the sum of +// that of +// all other active tasks does not exceed the available resources of the +// system // (i.e.: 100 * # of cores of the machine). -// In other words, in every instant of execution, the sum of all active task's loads +// In other words, in every instant of execution, the sum of all active +// task's loads // never exceeds the available machine resources. -// * When such default execution condition is not met when attempting to take the -// task, no other task is taken instead - we wait until enough resources have been +// * When such default execution condition is not met when attempting to take +// the +// task, no other task is taken instead - we wait until enough resources have +// been // freed before attempting to take the same task again. // In other words, the default execution condition is *BLOCKING*. -//Custom execution conditions: -// * The user may decide to impose more tight conditions for tasks added by a certain +// Custom execution conditions: +// * The user may decide to impose more tight conditions for tasks added by a +// certain // Executor. Let's call such conditions 'custom' conditions. -// * Custom conditions are always tested *AFTER* the default ones (on the same task). +// * Custom conditions are always tested *AFTER* the default ones (on the same +// task). // This is necessary to enforce the global scheduling priorities mechanism. -// * When no task of a certain executor is active, custom conditions are always considered +// * When no task of a certain executor is active, custom conditions are always +// considered // satisfied. -// * If custom conditions are not met, we enqueue the task in an Executor-private queue -// for later execution and remove it from the global tasks queue - making it possible -// to perform other tasks before our custom-failed one (such operation will be called +// * If custom conditions are not met, we enqueue the task in an +// Executor-private queue +// for later execution and remove it from the global tasks queue - making it +// possible +// to perform other tasks before our custom-failed one (such operation will +// be called // "ACCUMULATION"). -// In other words, custom conditions are *NOT BLOCKING* among different Executors. -// * Tasks in the last task's Executor-private queue are always polled before those in -// the global queue by Workers which ended a task, and this is done in a *BLOCKING* way +// In other words, custom conditions are *NOT BLOCKING* among different +// Executors. +// * Tasks in the last task's Executor-private queue are always polled before +// those in +// the global queue by Workers which ended a task, and this is done in a +// *BLOCKING* way // inside the same Executor. -// * When an Executor-private tasks queue is not empty, all the other tasks added by the +// * When an Executor-private tasks queue is not empty, all the other tasks +// added by the // same executor are scheduled in the queue. -// In other words, the order of execution is always that of global insertion, *inside +// In other words, the order of execution is always that of global insertion, +// *inside // the same executor*. -// * Tasks polled from an Executor-private queue (which therefore satisfied custom conditions) -// may still fail with default execution conditions. If that happens, we put the task -// back into the global queue with highest possible priority (timedOut) and the worker dies. -// Tasks with this special priority are polled *before every other task*. So, again, default +// * Tasks polled from an Executor-private queue (which therefore satisfied +// custom conditions) +// may still fail with default execution conditions. If that happens, we put +// the task +// back into the global queue with highest possible priority (timedOut) and +// the worker dies. +// Tasks with this special priority are polled *before every other task*. So, +// again, default // conditions are *BLOCKING*. -//Thread-safety: -// * Most of the following code is mutex-protected, altough it might seem not - indeed, -// only *one* mutex is locked and unlocked all of the time. This 'transition mutex' is -// the key to thread-safety: we're considered to lie in a 'transition state' if we are -// operating outside the run() of some task - which covers almost the totality of the code. -// * The transition mutex is *not* recursive. The reason is that threads con not wait on -// QWaitConditions if the mutex is recursive. That makes it necessary (and welcome) to put -// mutex lockers in strategic points of the code - in many low-level functions no mutex -// is locked *because some caller already did it before*. If you're modifying the code -// always trace back the callers of a function before inserting misleading mutex lockers. +// Thread-safety: +// * Most of the following code is mutex-protected, altough it might seem not - +// indeed, +// only *one* mutex is locked and unlocked all of the time. This 'transition +// mutex' is +// the key to thread-safety: we're considered to lie in a 'transition state' +// if we are +// operating outside the run() of some task - which covers almost the +// totality of the code. +// * The transition mutex is *not* recursive. The reason is that threads con +// not wait on +// QWaitConditions if the mutex is recursive. That makes it necessary (and +// welcome) to put +// mutex lockers in strategic points of the code - in many low-level +// functions no mutex +// is locked *because some caller already did it before*. If you're modifying +// the code +// always trace back the callers of a function before inserting misleading +// mutex lockers. //============================================================================== @@ -102,16 +132,20 @@ // TODO list //------------------ -// * Improve dedicated threads support: make sure that tasks added to a dedicated -// executor are directly moved to the accumulation queue. The setDedicatedThreads() +// * Improve dedicated threads support: make sure that tasks added to a +// dedicated +// executor are directly moved to the accumulation queue. The +// setDedicatedThreads() // method must therefore react accordingly. // * It could be possible to implement a dependency-based mechanism... -// * Should the hosting thread wait for worker ones upon ExecutorImp destruction?? +// * Should the hosting thread wait for worker ones upon ExecutorImp +// destruction?? // It could be a problem on some forever-waiting tasks... -// * Ricontrolla che con le ultime modifiche gli ExecutorId rimangano quando si passano +// * Ricontrolla che con le ultime modifiche gli ExecutorId rimangano quando si +// passano // i puntatori in takeTask e refreshAss.. //============================================================================== @@ -126,23 +160,18 @@ DEFINE_CLASS_CODE(TThread::Runnable, 21) // Global init() initializer function //------------------------------------------ -void TThread::init() -{ - Executor::init(); - TThreadMessageDispatcher::init(); +void TThread::init() { + Executor::init(); + TThreadMessageDispatcher::init(); } //--------------------------------------------------------------------- -void TThread::shutdown() -{ - Executor::shutdown(); -} +void TThread::shutdown() { Executor::shutdown(); } //============================================================================== -namespace TThread -{ +namespace TThread { //============================================================================== @@ -152,31 +181,30 @@ namespace TThread //! A Worker is a specialized QThread that continuously polls Runnable //! tasks from a global execution queue to make them work. -class Worker : public QThread -{ +class Worker : public QThread { public: - RunnableP m_task; + RunnableP m_task; - TSmartPointerT m_master; + TSmartPointerT m_master; - bool m_exit; - QWaitCondition m_waitCondition; + bool m_exit; + QWaitCondition m_waitCondition; - Worker(); - ~Worker(); + Worker(); + ~Worker(); - void run(); + void run(); - inline void takeTask(); - inline bool canAdopt(const RunnableP &task); - inline void adoptTask(RunnableP &task); + inline void takeTask(); + inline bool canAdopt(const RunnableP &task); + inline void adoptTask(RunnableP &task); - inline void rest(); + inline void rest(); - inline void updateCountsOnTake(); - inline void updateCountsOnRelease(); + inline void updateCountsOnTake(); + inline void updateCountsOnRelease(); - inline void onFinish(); + inline void onFinish(); }; //===================================================================== @@ -192,28 +220,27 @@ public: //! tasks added through it - by copying the smart pointer to the id into each //! added task. //! \sa Executor and Runnable class. -class ExecutorId : public TSmartObject -{ +class ExecutorId : public TSmartObject { public: - size_t m_id; + size_t m_id; - int m_activeTasks; - int m_maxActiveTasks; + int m_activeTasks; + int m_maxActiveTasks; - int m_activeLoad; - int m_maxActiveLoad; + int m_activeLoad; + int m_maxActiveLoad; - bool m_dedicatedThreads; - bool m_persistentThreads; - std::deque m_sleepings; + bool m_dedicatedThreads; + bool m_persistentThreads; + std::deque m_sleepings; - ExecutorId(); - ~ExecutorId(); + ExecutorId(); + ~ExecutorId(); - inline void accumulate(const RunnableP &task); + inline void accumulate(const RunnableP &task); - void newWorker(RunnableP &task); - void refreshDedicatedList(); + void newWorker(RunnableP &task); + void refreshDedicatedList(); }; //===================================================================== @@ -227,33 +254,32 @@ public: //! One process only hosts one instance of the ExecutorImp class as a //! a global variable that needs to be allocated in an application-lasting //! and event-looped thread - typically the main thread in GUI applications. -class ExecutorImp -{ +class ExecutorImp { public: - QMultiMap m_tasks; - std::set m_workers; // Used just for debugging purposes + QMultiMap m_tasks; + std::set m_workers; // Used just for debugging purposes - tcg::indices_pool<> m_executorIdPool; - std::vector m_waitingFlagsPool; + tcg::indices_pool<> m_executorIdPool; + std::vector m_waitingFlagsPool; - int m_activeLoad; - int m_maxLoad; + int m_activeLoad; + int m_maxLoad; - QMutex m_transitionMutex; // Workers' transition mutex + QMutex m_transitionMutex; // Workers' transition mutex - ExecutorImp(); - ~ExecutorImp(); + ExecutorImp(); + ~ExecutorImp(); - inline void insertTask(int schedulingPriority, RunnableP &task); + inline void insertTask(int schedulingPriority, RunnableP &task); - void refreshAssignments(); + void refreshAssignments(); - inline bool isExecutable(RunnableP &task); + inline bool isExecutable(RunnableP &task); }; //===================================================================== -} // namespace TThread +} // namespace TThread //===================================================================== @@ -261,11 +287,10 @@ public: // Global variables //--------------------------- -namespace -{ -ExecutorImp *globalImp = 0; +namespace { +ExecutorImp *globalImp = 0; ExecutorImpSlots *globalImpSlots = 0; -bool shutdownVar = false; +bool shutdownVar = false; } //===================================================================== @@ -275,32 +300,30 @@ bool shutdownVar = false; //----------------------------- ExecutorImp::ExecutorImp() - : m_activeLoad(0), m_maxLoad(TSystem::getProcessorCount() * 100), m_transitionMutex() //NOTE: We'll wait on this mutex - so it can't be recursive -{ -} + : m_activeLoad(0) + , m_maxLoad(TSystem::getProcessorCount() * 100) + , m_transitionMutex() // NOTE: We'll wait on this mutex - so it can't be + // recursive +{} //--------------------------------------------------------------------- -ExecutorImp::~ExecutorImp() -{ -} +ExecutorImp::~ExecutorImp() {} //--------------------------------------------------------------------- -//A task is executable <==> its load allows it. The task load is considered -//fixed until another isExecutable() call is made again - in case it may -//change in time. -inline bool ExecutorImp::isExecutable(RunnableP &task) -{ - return m_activeLoad + task->m_load <= m_maxLoad; +// A task is executable <==> its load allows it. The task load is considered +// fixed until another isExecutable() call is made again - in case it may +// change in time. +inline bool ExecutorImp::isExecutable(RunnableP &task) { + return m_activeLoad + task->m_load <= m_maxLoad; } //--------------------------------------------------------------------- -inline void ExecutorImp::insertTask(int schedulingPriority, RunnableP &task) -{ - task->m_schedulingPriority = schedulingPriority; - m_tasks.insert(schedulingPriority, task); +inline void ExecutorImp::insertTask(int schedulingPriority, RunnableP &task) { + task->m_schedulingPriority = schedulingPriority; + m_tasks.insert(schedulingPriority, task); } //===================================================================== @@ -309,50 +332,58 @@ inline void ExecutorImp::insertTask(int schedulingPriority, RunnableP &task) // Runnable methods //------------------------ -Runnable::Runnable() - : TSmartObject(m_classCode), m_id(0) -{ -} +Runnable::Runnable() : TSmartObject(m_classCode), m_id(0) {} //--------------------------------------------------------------------- -Runnable::~Runnable() -{ - if (m_id) - m_id->release(); //see Executor::addTask() +Runnable::~Runnable() { + if (m_id) m_id->release(); // see Executor::addTask() } //--------------------------------------------------------------------- -//! Returns the predicted CPU load generated by the task, expressed in percentage -//! of core usage (that is, 100 is intended to fully occupy one processing core). -//! Appropriate task load calibration is an important step to take when implementing +//! Returns the predicted CPU load generated by the task, expressed in +//! percentage +//! of core usage (that is, 100 is intended to fully occupy one processing +//! core). +//! Appropriate task load calibration is an important step to take when +//! implementing //! a new task; for this purpose, remember some rules to follow: //!
    -//!
  • In every moment, the task manager ensures that the overall sum of the active -//! task's load does not exceed the number of machine's processing cores multiplied -//! by 100. This condition is \a blocking with respect to the execution of any other -//! task - meaning that when a task is about to be executed the task manager \a waits +//!
  • In every moment, the task manager ensures that the overall sum of the +//! active +//! task's load does not exceed the number of machine's processing cores +//! multiplied +//! by 100. This condition is \a blocking with respect to the execution of +//! any other +//! task - meaning that when a task is about to be executed the task manager +//! \a waits //! until enough CPU resources are available to make it run. -//! In particular, observe that a task's load \b never has to exceed the total CPU -//! resources - doing so would surely result in a block of your application. The number -//! of available cores can be accessed via the \b TSystem::getProcessorCount() or +//! In particular, observe that a task's load \b never has to exceed the +//! total CPU +//! resources - doing so would surely result in a block of your application. +//! The number +//! of available cores can be accessed via the \b +//! TSystem::getProcessorCount() or //! \b QThread::idealThreadCount(). -//!
  • The task load is considered constant for the duration of the task. Changing its -//! value does not affect the task manager in any way once the task has been started. - -//!
  • The default task load is 0, representing a very light task. If the task load -//! is 0 the condition at point 1 always succeeds - so the task is always executed when -//! encountered. Observe that a long succession of 0 task loads leads to the creation of -//! a proportional number of threads simultaneously running to dispatch it; if this is +//!
  • The task load is considered constant for the duration of the task. +//! Changing its +//! value does not affect the task manager in any way once the task has been +//! started. + +//!
  • The default task load is 0, representing a very light task. If the task +//! load +//! is 0 the condition at point 1 always succeeds - so the task is always +//! executed when +//! encountered. Observe that a long succession of 0 task loads leads to the +//! creation of +//! a proportional number of threads simultaneously running to dispatch it; +//! if this is //! a problem, consider the use of \b Executor::setMaxActiveTasks() //! to make only a certain number of tasks being executed at the same time. //!
-int Runnable::taskLoad() -{ - return 0; -} +int Runnable::taskLoad() { return 0; } //--------------------------------------------------------------------- @@ -360,26 +391,21 @@ int Runnable::taskLoad() //! with higher priority start before tasks with lower priority. The default //! value returned is 5 (halfway from 0 to 10) - but any value other than //! (std::numeric_limits::max)() is acceptable. -int Runnable::schedulingPriority() -{ - return 5; -} +int Runnable::schedulingPriority() { return 5; } //--------------------------------------------------------------------- //! Returns the QThread::Priority used by worker threads when they adopt //! the task. The default value returned is QThread::Normal. -QThread::Priority Runnable::runningPriority() -{ - return QThread::NormalPriority; +QThread::Priority Runnable::runningPriority() { + return QThread::NormalPriority; } //--------------------------------------------------------------------- -inline bool Runnable::customConditions() -{ - return (m_id->m_activeTasks < m_id->m_maxActiveTasks) && - (m_id->m_activeLoad + m_load <= m_id->m_maxActiveLoad); +inline bool Runnable::customConditions() { + return (m_id->m_activeTasks < m_id->m_maxActiveTasks) && + (m_id->m_activeLoad + m_load <= m_id->m_maxActiveLoad); } /*! @@ -394,11 +420,13 @@ inline bool Runnable::customConditions() emissions (i.e. so that canceled() and terminated() controller-emitted signals are either delivered after started() and before finished() or exception(), or \a instead of them). - \warning Thus, setting up blocking connections or \a direct slots that contain a + \warning Thus, setting up blocking connections or \a direct slots that contain + a blocking instruction or even calls to the Executor API (which would definitely try to relock the aforementioned mutex) is dangerous and could result in an application freeze. - \warning In case it's necessary to use blocking features, they should be enforced + \warning In case it's necessary to use blocking features, they should be + enforced through custom signals to be invoked manually in the run() method, outside the mutex. @@ -456,37 +484,27 @@ inline bool Runnable::customConditions() //! Convenience slot for the started() signal - so it's not necessary to declare //! the task in a header file for moc'ing each time. You must both reimplement //! \b and connect it to the started() signal to make it work. -void Runnable::onStarted(RunnableP) -{ -} +void Runnable::onStarted(RunnableP) {} //--------------------------------------------------------------------- //! The analogous of onStarted() for the finished() signal. -void Runnable::onFinished(RunnableP) -{ -} +void Runnable::onFinished(RunnableP) {} //--------------------------------------------------------------------- //! The analogous of onStarted() for the exception() signal. -void Runnable::onException(RunnableP) -{ -} +void Runnable::onException(RunnableP) {} //--------------------------------------------------------------------- //! The analogous of onStarted() for the canceled() signal. -void Runnable::onCanceled(RunnableP) -{ -} +void Runnable::onCanceled(RunnableP) {} //--------------------------------------------------------------------- //! The analogous of onStarted() for the terminated() signal. -void Runnable::onTerminated(RunnableP) -{ -} +void Runnable::onTerminated(RunnableP) {} //===================================================================== @@ -495,48 +513,51 @@ void Runnable::onTerminated(RunnableP) //-------------------------- ExecutorId::ExecutorId() - : m_activeTasks(0), m_maxActiveTasks(1), m_activeLoad(0), m_maxActiveLoad((std::numeric_limits::max)()), m_dedicatedThreads(false), m_persistentThreads(false) -{ - QMutexLocker transitionLocker(&globalImp->m_transitionMutex); - - m_id = globalImp->m_executorIdPool.acquire(); - globalImp->m_waitingFlagsPool.resize(globalImp->m_executorIdPool.size()); + : m_activeTasks(0) + , m_maxActiveTasks(1) + , m_activeLoad(0) + , m_maxActiveLoad((std::numeric_limits::max)()) + , m_dedicatedThreads(false) + , m_persistentThreads(false) { + QMutexLocker transitionLocker(&globalImp->m_transitionMutex); + + m_id = globalImp->m_executorIdPool.acquire(); + globalImp->m_waitingFlagsPool.resize(globalImp->m_executorIdPool.size()); } //--------------------------------------------------------------------- -ExecutorId::~ExecutorId() -{ - QMutexLocker transitionLocker(&globalImp->m_transitionMutex); +ExecutorId::~ExecutorId() { + QMutexLocker transitionLocker(&globalImp->m_transitionMutex); - if (m_dedicatedThreads) { - m_persistentThreads = 0; - refreshDedicatedList(); - } + if (m_dedicatedThreads) { + m_persistentThreads = 0; + refreshDedicatedList(); + } - globalImp->m_executorIdPool.release(m_id); + globalImp->m_executorIdPool.release(m_id); } //--------------------------------------------------------------------- -//Make sure that sleeping workers are eliminated properly if the permanent -//workers count decreases. -void ExecutorId::refreshDedicatedList() -{ - //QMutexLocker transitionLocker(&globalImp->m_transitionMutex); //Already covered +// Make sure that sleeping workers are eliminated properly if the permanent +// workers count decreases. +void ExecutorId::refreshDedicatedList() { + // QMutexLocker transitionLocker(&globalImp->m_transitionMutex); //Already + // covered - if (!m_dedicatedThreads || !m_persistentThreads) { - //Release all sleeping workers - //Wake them - they will exit on their own + if (!m_dedicatedThreads || !m_persistentThreads) { + // Release all sleeping workers + // Wake them - they will exit on their own - unsigned int i, size = m_sleepings.size(); - for (i = 0; i < size; ++i) { - m_sleepings[i]->m_exit = true; - m_sleepings[i]->m_waitCondition.wakeOne(); - } + unsigned int i, size = m_sleepings.size(); + for (i = 0; i < size; ++i) { + m_sleepings[i]->m_exit = true; + m_sleepings[i]->m_waitCondition.wakeOne(); + } - m_sleepings.clear(); - } + m_sleepings.clear(); + } } //===================================================================== @@ -545,106 +566,96 @@ void ExecutorId::refreshDedicatedList() // Worker methods //--------------------------- -Worker::Worker() - : QThread(), m_task(0), m_master(0), m_exit(true) -{ -} +Worker::Worker() : QThread(), m_task(0), m_master(0), m_exit(true) {} //--------------------------------------------------------------------- -Worker::~Worker() -{ -} +Worker::~Worker() {} //--------------------------------------------------------------------- -void Worker::run() -{ - //Ensure atomicity of worker's state transitions - QMutexLocker sl(&globalImp->m_transitionMutex); +void Worker::run() { + // Ensure atomicity of worker's state transitions + QMutexLocker sl(&globalImp->m_transitionMutex); - if (shutdownVar) - return; + if (shutdownVar) return; - for (;;) { - //Run the taken task - setPriority(m_task->runningPriority()); + for (;;) { + // Run the taken task + setPriority(m_task->runningPriority()); - try { - Q_EMIT m_task->started(m_task); - sl.unlock(); + try { + Q_EMIT m_task->started(m_task); + sl.unlock(); - m_task->run(); + m_task->run(); - sl.relock(); - Q_EMIT m_task->finished(m_task); - } catch (...) { - sl.relock(); //throw must be in the run() block - Q_EMIT m_task->exception(m_task); - } + sl.relock(); + Q_EMIT m_task->finished(m_task); + } catch (...) { + sl.relock(); // throw must be in the run() block + Q_EMIT m_task->exception(m_task); + } - updateCountsOnRelease(); + updateCountsOnRelease(); - if (shutdownVar) - return; + if (shutdownVar) return; - //Get the next task - takeTask(); + // Get the next task + takeTask(); - if (!m_task) { - onFinish(); + if (!m_task) { + onFinish(); - if (!m_exit && !shutdownVar) { - //Put the worker to sleep - m_waitCondition.wait(sl.mutex()); + if (!m_exit && !shutdownVar) { + // Put the worker to sleep + m_waitCondition.wait(sl.mutex()); - //Upon thread destruction the wait condition is implicitly woken up. - //If this is the case, m_task == 0 and we return. - if (!m_task || shutdownVar) - return; - } else - return; - } - } + // Upon thread destruction the wait condition is implicitly woken up. + // If this is the case, m_task == 0 and we return. + if (!m_task || shutdownVar) return; + } else + return; + } + } } //--------------------------------------------------------------------- -inline void Worker::updateCountsOnTake() -{ - globalImp->m_activeLoad += m_task->m_load; - m_task->m_id->m_activeLoad += m_task->m_load; - ++m_task->m_id->m_activeTasks; +inline void Worker::updateCountsOnTake() { + globalImp->m_activeLoad += m_task->m_load; + m_task->m_id->m_activeLoad += m_task->m_load; + ++m_task->m_id->m_activeTasks; } //--------------------------------------------------------------------- -inline void Worker::updateCountsOnRelease() -{ - globalImp->m_activeLoad -= m_task->m_load; - m_task->m_id->m_activeLoad -= m_task->m_load; - --m_task->m_id->m_activeTasks; +inline void Worker::updateCountsOnRelease() { + globalImp->m_activeLoad -= m_task->m_load; + m_task->m_id->m_activeLoad -= m_task->m_load; + --m_task->m_id->m_activeTasks; } //--------------------------------------------------------------------- -inline void Worker::onFinish() -{ - if (m_master && m_master->m_dedicatedThreads && m_master->m_persistentThreads) { - m_exit = false; - m_master->m_sleepings.push_back(this); +inline void Worker::onFinish() { + if (m_master && m_master->m_dedicatedThreads && + m_master->m_persistentThreads) { + m_exit = false; + m_master->m_sleepings.push_back(this); - // Unlock the mutex - since eventually invoked ~ExecutorId will relock it... - globalImp->m_transitionMutex.unlock(); + // Unlock the mutex - since eventually invoked ~ExecutorId will relock it... + globalImp->m_transitionMutex.unlock(); - m_master = 0; //Master may be destroyed here - and m_exit= true for all sleepings - //in that case + m_master = + 0; // Master may be destroyed here - and m_exit= true for all sleepings + // in that case - globalImp->m_transitionMutex.lock(); - } else { - m_exit = true; - globalImp->m_workers.erase(this); - } + globalImp->m_transitionMutex.lock(); + } else { + m_exit = true; + globalImp->m_workers.erase(this); + } } //===================================================================== @@ -653,18 +664,11 @@ inline void Worker::onFinish() // Executor methods //--------------------------- -Executor::Executor() - : m_id(new ExecutorId) -{ - m_id->addRef(); -} +Executor::Executor() : m_id(new ExecutorId) { m_id->addRef(); } //--------------------------------------------------------------------- -Executor::~Executor() -{ - m_id->release(); -} +Executor::~Executor() { m_id->release(); } //--------------------------------------------------------------------- @@ -672,76 +676,89 @@ Executor::~Executor() //! the application code. Be sure to use it according to the following rules: //!
    //!
  • Only QCoreApplications or QApplications may use Executors. -//!
  • This method must be invoked in a thread which performs constant Qt event +//!
  • This method must be invoked in a thread which performs constant Qt +//! event //! processing - like the main loop of interactive GUI applications. //!
  • No task processing is allowed after event processing stops. //!
-void Executor::init() -{ - //If no global ExecutorImp exists, allocate it now. You may not move this - //to a static declaration, since ExecutorImpSlots's connections must be - //made once the QCoreApplication has been constructed. - if (!globalImp) { - globalImp = new ExecutorImp; - globalImpSlots = new ExecutorImpSlots; - } - - qRegisterMetaType("TThread::RunnableP"); +void Executor::init() { + // If no global ExecutorImp exists, allocate it now. You may not move this + // to a static declaration, since ExecutorImpSlots's connections must be + // made once the QCoreApplication has been constructed. + if (!globalImp) { + globalImp = new ExecutorImp; + globalImpSlots = new ExecutorImpSlots; + } + + qRegisterMetaType("TThread::RunnableP"); } //--------------------------------------------------------------------- -//! This static method, which \b must be invoked in the controller thread, declares -//! termination of all Executor-based components, forcing the execution of tasks submitted +//! This static method, which \b must be invoked in the controller thread, +//! declares +//! termination of all Executor-based components, forcing the execution of tasks +//! submitted //! by any Executor to quit as soon as possible in a safe way. -//! When the shutdown method is invoked, the task manager first emits a canceled() -//! signal for all the tasks that were submitted to it, independently from the Executor that -//! performed the submission; then, tasks that are still active once all the cancellation signals -//! were delivered further receive a terminated() signal informing them that they must provide -//! code termination (or at least remain silent in a safe state until the application quits). - -//! \b NOTE: Observe that this method does not explicitly wait for all the tasks to terminate - this depends -//! on the code connected to the terminated() signal and is under the user's responsibility (see the -//! remarks specified in started() signal descritpion); if this is the intent and the terminated slot -//! is invoked in the controller thread, you should remember to implement a local event loop in it (so that -//! event processing is still performed) and wait there until the first finished() or catched() +//! When the shutdown method is invoked, the task manager first emits a +//! canceled() +//! signal for all the tasks that were submitted to it, independently from the +//! Executor that +//! performed the submission; then, tasks that are still active once all the +//! cancellation signals +//! were delivered further receive a terminated() signal informing them that +//! they must provide +//! code termination (or at least remain silent in a safe state until the +//! application quits). + +//! \b NOTE: Observe that this method does not explicitly wait for all the tasks +//! to terminate - this depends +//! on the code connected to the terminated() signal and is under the user's +//! responsibility (see the +//! remarks specified in started() signal descritpion); if this is the intent +//! and the terminated slot +//! is invoked in the controller thread, you should remember to implement a +//! local event loop in it (so that +//! event processing is still performed) and wait there until the first +//! finished() or catched() //! slot make it quit. -void Executor::shutdown() -{ - { - //Updating tasks list - lock against state transitions - QMutexLocker transitionLocker(&globalImp->m_transitionMutex); - - shutdownVar = true; - - //Cancel all tasks - first the active ones - std::set::iterator it; - for (it = globalImp->m_workers.begin(); it != globalImp->m_workers.end(); ++it) { - RunnableP task = (*it)->m_task; - if (task) - Q_EMIT task->canceled(task); - } - - //Finally, deal with the global queue tasks - QMutableMapIterator jt(globalImp->m_tasks); - while (jt.hasNext()) { - jt.next(); - RunnableP task = jt.value(); - Q_EMIT task->canceled(task); - jt.remove(); - } - - //Now, send the terminate() signal to all active tasks - for (it = globalImp->m_workers.begin(); it != globalImp->m_workers.end(); ++it) { - RunnableP task = (*it)->m_task; - if (task) - Q_EMIT task->terminated(task); - } - } - - //Just placing a convenience processEvents() to make sure that queued slots invoked by the - //signals above are effectively invoked in this method - without having to return to an event loop. - QCoreApplication::processEvents(); +void Executor::shutdown() { + { + // Updating tasks list - lock against state transitions + QMutexLocker transitionLocker(&globalImp->m_transitionMutex); + + shutdownVar = true; + + // Cancel all tasks - first the active ones + std::set::iterator it; + for (it = globalImp->m_workers.begin(); it != globalImp->m_workers.end(); + ++it) { + RunnableP task = (*it)->m_task; + if (task) Q_EMIT task->canceled(task); + } + + // Finally, deal with the global queue tasks + QMutableMapIterator jt(globalImp->m_tasks); + while (jt.hasNext()) { + jt.next(); + RunnableP task = jt.value(); + Q_EMIT task->canceled(task); + jt.remove(); + } + + // Now, send the terminate() signal to all active tasks + for (it = globalImp->m_workers.begin(); it != globalImp->m_workers.end(); + ++it) { + RunnableP task = (*it)->m_task; + if (task) Q_EMIT task->terminated(task); + } + } + + // Just placing a convenience processEvents() to make sure that queued slots + // invoked by the + // signals above are effectively invoked in this method - without having to + // return to an event loop. + QCoreApplication::processEvents(); } //--------------------------------------------------------------------- @@ -766,42 +783,41 @@ void Executor::shutdown() //!
    //!
  • The Executor's tasks use thread-specific data such as QThreadStorages, //! which may be recycled among different tasks. -//!
  • The Executor receives tasks at a frequent rate, but mostly ends each one before +//!
  • The Executor receives tasks at a frequent rate, but mostly ends each +//! one before //! another one is submitted - resulting in a continuous thread turnover. //!
-void Executor::setDedicatedThreads(bool dedicated, bool persistent) -{ - QMutexLocker transitionLocker(&globalImp->m_transitionMutex); +void Executor::setDedicatedThreads(bool dedicated, bool persistent) { + QMutexLocker transitionLocker(&globalImp->m_transitionMutex); - m_id->m_dedicatedThreads = dedicated; - m_id->m_persistentThreads = persistent; + m_id->m_dedicatedThreads = dedicated; + m_id->m_persistentThreads = persistent; - m_id->refreshDedicatedList(); + m_id->refreshDedicatedList(); } //--------------------------------------------------------------------- //! Submits a task for execution. The task is executed according to //! its task load, insertion time and scheduling priority. -void Executor::addTask(RunnableP task) -{ - { - if (task->m_id) // Must be done outside transition lock, since eventually - task->m_id->release(); // invoked ~ExecutorId will lock it +void Executor::addTask(RunnableP task) { + { + if (task->m_id) // Must be done outside transition lock, since eventually + task->m_id->release(); // invoked ~ExecutorId will lock it - //Updating tasks and workers list - lock against state transitions - QMutexLocker transitionLocker(&globalImp->m_transitionMutex); + // Updating tasks and workers list - lock against state transitions + QMutexLocker transitionLocker(&globalImp->m_transitionMutex); - task->m_id = m_id; - m_id->addRef(); + task->m_id = m_id; + m_id->addRef(); - globalImp->insertTask(task->schedulingPriority(), task); - } + globalImp->insertTask(task->schedulingPriority(), task); + } - //If addTask is called in the main thread, the emit works directly - - //so it is necessary to unlock the mutex *before* emitting the refresh. - globalImpSlots->emitRefreshAssignments(); + // If addTask is called in the main thread, the emit works directly - + // so it is necessary to unlock the mutex *before* emitting the refresh. + globalImpSlots->emitRefreshAssignments(); } //--------------------------------------------------------------------- @@ -809,32 +825,30 @@ void Executor::addTask(RunnableP task) //! Removes the given task from scheduled execution and emits its //! Runnable::canceled signal. Tasks already under execution are not //! stopped by this method - although the canceled signal is still emitted. -//! It has no effect if the task is not currently under the task manager's control. +//! It has no effect if the task is not currently under the task manager's +//! control. //! \sa \b Runnable::canceled signal and the \b cancelAll method. -void Executor::removeTask(RunnableP task) -{ - //If the task does not belong to this Executor, quit. - if (task->m_id != m_id) - return; - - //Updating tasks list - lock against state transitions - QMutexLocker transitionLocker(&globalImp->m_transitionMutex); - - //Then, look in the global queue - if it is found, emiminate the task and - //send the canceled signal. - if (globalImp->m_tasks.remove(task->m_schedulingPriority, task)) { - Q_EMIT task->canceled(task); - return; - } - - //Finally, the task may be running - look in workers. - std::set &workers = globalImp->m_workers; - std::set::iterator it; - for (it = workers.begin(); it != workers.end(); ++it) - if (task && (*it)->m_task == task) - Q_EMIT task->canceled(task); - - //No need to refresh - tasks were eventually decremented... +void Executor::removeTask(RunnableP task) { + // If the task does not belong to this Executor, quit. + if (task->m_id != m_id) return; + + // Updating tasks list - lock against state transitions + QMutexLocker transitionLocker(&globalImp->m_transitionMutex); + + // Then, look in the global queue - if it is found, emiminate the task and + // send the canceled signal. + if (globalImp->m_tasks.remove(task->m_schedulingPriority, task)) { + Q_EMIT task->canceled(task); + return; + } + + // Finally, the task may be running - look in workers. + std::set &workers = globalImp->m_workers; + std::set::iterator it; + for (it = workers.begin(); it != workers.end(); ++it) + if (task && (*it)->m_task == task) Q_EMIT task->canceled(task); + + // No need to refresh - tasks were eventually decremented... } //--------------------------------------------------------------------- @@ -843,31 +857,31 @@ void Executor::removeTask(RunnableP task) //! the Runnable::canceled signal for each of them. The same specifications //! described in the \b removeTask method apply here. //! \sa \b Runnable::canceled signal and the \b removeTask method. -void Executor::cancelAll() -{ - //Updating tasks list - lock against state transitions - QMutexLocker transitionLocker(&globalImp->m_transitionMutex); - - //Clear the tasks chronologically. So, first check currently working - //tasks. - std::set::iterator it; - for (it = globalImp->m_workers.begin(); it != globalImp->m_workers.end(); ++it) { - RunnableP task = (*it)->m_task; - if (task && task->m_id == m_id) - Q_EMIT task->canceled(task); - } - - //Finally, clear the global tasks list from all tasks inserted by this executor - //NOTE: An easier way here? - QMutableMapIterator jt(globalImp->m_tasks); - while (jt.hasNext()) { - jt.next(); - if (jt.value()->m_id == m_id) { - RunnableP task = jt.value(); - Q_EMIT task->canceled(task); - jt.remove(); - } - } +void Executor::cancelAll() { + // Updating tasks list - lock against state transitions + QMutexLocker transitionLocker(&globalImp->m_transitionMutex); + + // Clear the tasks chronologically. So, first check currently working + // tasks. + std::set::iterator it; + for (it = globalImp->m_workers.begin(); it != globalImp->m_workers.end(); + ++it) { + RunnableP task = (*it)->m_task; + if (task && task->m_id == m_id) Q_EMIT task->canceled(task); + } + + // Finally, clear the global tasks list from all tasks inserted by this + // executor + // NOTE: An easier way here? + QMutableMapIterator jt(globalImp->m_tasks); + while (jt.hasNext()) { + jt.next(); + if (jt.value()->m_id == m_id) { + RunnableP task = jt.value(); + Q_EMIT task->canceled(task); + jt.remove(); + } + } } //--------------------------------------------------------------------- @@ -880,41 +894,37 @@ void Executor::cancelAll() //! satisfy this condition avoid blocking execution of tasks not //! added by the same Executor - even if they were scheduled for later //! execution. -void Executor::setMaxActiveTasks(int maxActiveTasks) -{ - QMutexLocker transitionLocker(&globalImp->m_transitionMutex); - - if (maxActiveTasks <= 0) - m_id->m_maxActiveTasks = (std::numeric_limits::max)(); - else - m_id->m_maxActiveTasks = maxActiveTasks; +void Executor::setMaxActiveTasks(int maxActiveTasks) { + QMutexLocker transitionLocker(&globalImp->m_transitionMutex); + + if (maxActiveTasks <= 0) + m_id->m_maxActiveTasks = (std::numeric_limits::max)(); + else + m_id->m_maxActiveTasks = maxActiveTasks; } //--------------------------------------------------------------------- -int Executor::maxActiveTasks() const -{ - QMutexLocker transitionLocker(&globalImp->m_transitionMutex); - return m_id->m_maxActiveTasks; +int Executor::maxActiveTasks() const { + QMutexLocker transitionLocker(&globalImp->m_transitionMutex); + return m_id->m_maxActiveTasks; } //--------------------------------------------------------------------- //! Declares a maximum overall task load for the tasks added by this Executor. //! \b NOTE: The same remark for setMaxActiveTasks() holds here. -void Executor::setMaxActiveLoad(int maxActiveLoad) -{ - QMutexLocker transitionLocker(&globalImp->m_transitionMutex); +void Executor::setMaxActiveLoad(int maxActiveLoad) { + QMutexLocker transitionLocker(&globalImp->m_transitionMutex); - m_id->m_maxActiveLoad = maxActiveLoad; + m_id->m_maxActiveLoad = maxActiveLoad; } //--------------------------------------------------------------------- -int Executor::maxActiveLoad() const -{ - QMutexLocker transitionLocker(&globalImp->m_transitionMutex); - return m_id->m_maxActiveLoad; +int Executor::maxActiveLoad() const { + QMutexLocker transitionLocker(&globalImp->m_transitionMutex); + return m_id->m_maxActiveLoad; } //===================================================================== @@ -923,70 +933,60 @@ int Executor::maxActiveLoad() const // ExecutorImpSlots methods //---------------------------------- -ExecutorImpSlots::ExecutorImpSlots() -{ - connect(this, SIGNAL(refreshAssignments()), this, SLOT(onRefreshAssignments())); +ExecutorImpSlots::ExecutorImpSlots() { + connect(this, SIGNAL(refreshAssignments()), this, + SLOT(onRefreshAssignments())); } //--------------------------------------------------------------------- -ExecutorImpSlots::~ExecutorImpSlots() -{ -} +ExecutorImpSlots::~ExecutorImpSlots() {} //--------------------------------------------------------------------- -void ExecutorImpSlots::emitRefreshAssignments() -{ - Q_EMIT refreshAssignments(); -} +void ExecutorImpSlots::emitRefreshAssignments() { Q_EMIT refreshAssignments(); } //--------------------------------------------------------------------- -void ExecutorImpSlots::onRefreshAssignments() -{ - QMutexLocker transitionLocker(&globalImp->m_transitionMutex); +void ExecutorImpSlots::onRefreshAssignments() { + QMutexLocker transitionLocker(&globalImp->m_transitionMutex); - globalImp->refreshAssignments(); + globalImp->refreshAssignments(); } //--------------------------------------------------------------------- -void ExecutorImpSlots::onTerminated() -{ - delete QObject::sender(); -} +void ExecutorImpSlots::onTerminated() { delete QObject::sender(); } //===================================================================== // Task adoption methods //--------------------------------------------------------------------- -inline void ExecutorId::newWorker(RunnableP &task) -{ - Worker *worker; - - if (m_sleepings.size()) { - worker = m_sleepings.front(); - m_sleepings.pop_front(); - worker->m_task = task; - worker->updateCountsOnTake(); - worker->m_waitCondition.wakeOne(); - } else { - worker = new Worker; - globalImp->m_workers.insert(worker); - QObject::connect(worker, SIGNAL(finished()), globalImpSlots, SLOT(onTerminated())); - worker->m_task = task; - worker->updateCountsOnTake(); - worker->start(); - } +inline void ExecutorId::newWorker(RunnableP &task) { + Worker *worker; + + if (m_sleepings.size()) { + worker = m_sleepings.front(); + m_sleepings.pop_front(); + worker->m_task = task; + worker->updateCountsOnTake(); + worker->m_waitCondition.wakeOne(); + } else { + worker = new Worker; + globalImp->m_workers.insert(worker); + QObject::connect(worker, SIGNAL(finished()), globalImpSlots, + SLOT(onTerminated())); + worker->m_task = task; + worker->updateCountsOnTake(); + worker->start(); + } } //--------------------------------------------------------------------- -inline void Worker::adoptTask(RunnableP &task) -{ - m_task = task; - updateCountsOnTake(); +inline void Worker::adoptTask(RunnableP &task) { + m_task = task; + updateCountsOnTake(); } //--------------------------------------------------------------------- @@ -1008,126 +1008,130 @@ inline void Worker::adoptTask(RunnableP &task) //--------------------------------------------------------------------- -//Assigns tasks polled from the id's accumulation queue (if id is given) and -//the global tasks queue. -//It works like: +// Assigns tasks polled from the id's accumulation queue (if id is given) and +// the global tasks queue. +// It works like: // a) First look if there exist tasks with timedOut priority and if so // try to take them out // b) Then look for tasks in the id's accumulation queue // c) Finally search in the remaining global tasks queue -void ExecutorImp::refreshAssignments() -{ - //QMutexLocker transitionLocker(&globalImp->m_transitionMutex); //Already covered - - if (m_tasks.isEmpty()) - return; - - // Erase the id vector data - assert(m_executorIdPool.size() == m_waitingFlagsPool.size()); - memset(&m_waitingFlagsPool.front(), 0, m_waitingFlagsPool.size()); - - //c) Try with the global queue - int e, executorsCount = m_executorIdPool.acquiredSize(); - - int i, tasksCount = m_tasks.size(); - QMultiMap::iterator it; - for (i = 0, e = 0, it = m_tasks.end() - 1; i < tasksCount && e < executorsCount; ++i, --it) { - //std::cout<< "global tasks-refreshAss" << std::endl; - //Take the task - RunnableP task = it.value(); - task->m_load = task->taskLoad(); - - UCHAR &idWaitingForAnotherTask = m_waitingFlagsPool[task->m_id->m_id]; - if (idWaitingForAnotherTask) - continue; - - if (!isExecutable(task)) - break; - - if (!task->customConditions()) { - ++e; - idWaitingForAnotherTask = 1; - } else { - task->m_id->newWorker(task); - it = m_tasks.erase(it); - } - } +void ExecutorImp::refreshAssignments() { + // QMutexLocker transitionLocker(&globalImp->m_transitionMutex); //Already + // covered + + if (m_tasks.isEmpty()) return; + + // Erase the id vector data + assert(m_executorIdPool.size() == m_waitingFlagsPool.size()); + memset(&m_waitingFlagsPool.front(), 0, m_waitingFlagsPool.size()); + + // c) Try with the global queue + int e, executorsCount = m_executorIdPool.acquiredSize(); + + int i, tasksCount = m_tasks.size(); + QMultiMap::iterator it; + for (i = 0, e = 0, it = m_tasks.end() - 1; + i < tasksCount && e < executorsCount; ++i, --it) { + // std::cout<< "global tasks-refreshAss" << std::endl; + // Take the task + RunnableP task = it.value(); + task->m_load = task->taskLoad(); + + UCHAR &idWaitingForAnotherTask = m_waitingFlagsPool[task->m_id->m_id]; + if (idWaitingForAnotherTask) continue; + + if (!isExecutable(task)) break; + + if (!task->customConditions()) { + ++e; + idWaitingForAnotherTask = 1; + } else { + task->m_id->newWorker(task); + it = m_tasks.erase(it); + } + } } //--------------------------------------------------------------------- -inline bool Worker::canAdopt(const RunnableP &task) -{ - return task->m_id->m_sleepings.size() == 0 && //Always prefer sleeping dedicateds if present - (!m_master || (m_master.getPointer() == task->m_id)); //If was seized by an Executor, ensure task compatibility +inline bool Worker::canAdopt(const RunnableP &task) { + return task->m_id->m_sleepings.size() == + 0 && // Always prefer sleeping dedicateds if present + (!m_master || (m_master.getPointer() == task->m_id)); // If was seized + // by an + // Executor, + // ensure task + // compatibility } //--------------------------------------------------------------------- -//Takes a task and assigns it to the worker in a way similar to the one above. -inline void Worker::takeTask() -{ - TSmartPointerT oldId = m_task->m_id; +// Takes a task and assigns it to the worker in a way similar to the one above. +inline void Worker::takeTask() { + TSmartPointerT oldId = m_task->m_id; - //When a new task is taken, the old one's Executor may seize the worker - m_master = oldId->m_dedicatedThreads ? oldId : (TSmartPointerT)0; + // When a new task is taken, the old one's Executor may seize the worker + m_master = oldId->m_dedicatedThreads ? oldId : (TSmartPointerT)0; - //c) No accumulated task can be taken - look for a task in the global tasks queue. - // If the active load admits it, take the earliest task. + // c) No accumulated task can be taken - look for a task in the global tasks + // queue. + // If the active load admits it, take the earliest task. - //Free the old task. NOTE: This instruction MUST be performed OUTSIDE the mutex-protected environment - - //since user code may be executed upon task destruction - including the mutex relock!! + // Free the old task. NOTE: This instruction MUST be performed OUTSIDE the + // mutex-protected environment - + // since user code may be executed upon task destruction - including the mutex + // relock!! - globalImp->m_transitionMutex.unlock(); + globalImp->m_transitionMutex.unlock(); - m_task = 0; - oldId = TSmartPointerT(); + m_task = 0; + oldId = TSmartPointerT(); - globalImp->m_transitionMutex.lock(); + globalImp->m_transitionMutex.lock(); - // Erase the executor id status pool - tcg::indices_pool<> &executorIdPool = globalImp->m_executorIdPool; - std::vector &waitingFlagsPool = globalImp->m_waitingFlagsPool; + // Erase the executor id status pool + tcg::indices_pool<> &executorIdPool = globalImp->m_executorIdPool; + std::vector &waitingFlagsPool = globalImp->m_waitingFlagsPool; - assert(waitingFlagsPool.size() == globalImp->m_executorIdPool.size()); - memset(&waitingFlagsPool.front(), 0, waitingFlagsPool.size()); + assert(waitingFlagsPool.size() == globalImp->m_executorIdPool.size()); + memset(&waitingFlagsPool.front(), 0, waitingFlagsPool.size()); - int e, executorsCount = executorIdPool.acquiredSize(); + int e, executorsCount = executorIdPool.acquiredSize(); - int i, tasksCount = globalImp->m_tasks.size(); - QMultiMap::iterator it; - for (i = 0, e = 0, it = globalImp->m_tasks.end() - 1; i < tasksCount && e < executorsCount; ++i, --it) { - //std::cout<< "global tasks-takeTask" << std::endl; - //Take the first task - RunnableP task = it.value(); - task->m_load = task->taskLoad(); + int i, tasksCount = globalImp->m_tasks.size(); + QMultiMap::iterator it; + for (i = 0, e = 0, it = globalImp->m_tasks.end() - 1; + i < tasksCount && e < executorsCount; ++i, --it) { + // std::cout<< "global tasks-takeTask" << std::endl; + // Take the first task + RunnableP task = it.value(); + task->m_load = task->taskLoad(); - UCHAR &idWaitingForAnotherTask = waitingFlagsPool[task->m_id->m_id]; - if (idWaitingForAnotherTask) - continue; + UCHAR &idWaitingForAnotherTask = waitingFlagsPool[task->m_id->m_id]; + if (idWaitingForAnotherTask) continue; - if (!globalImp->isExecutable(task)) - break; + if (!globalImp->isExecutable(task)) break; - //In case the worker was captured for dedication, check the task compatibility. - if (!canAdopt(task)) { - //some other worker may still take the task... - globalImpSlots->emitRefreshAssignments(); - break; - } + // In case the worker was captured for dedication, check the task + // compatibility. + if (!canAdopt(task)) { + // some other worker may still take the task... + globalImpSlots->emitRefreshAssignments(); + break; + } - //Test its custom conditions - if (!task->customConditions()) { - ++e; - idWaitingForAnotherTask = 1; - } else { - adoptTask(task); - it = globalImp->m_tasks.erase(it); + // Test its custom conditions + if (!task->customConditions()) { + ++e; + idWaitingForAnotherTask = 1; + } else { + adoptTask(task); + it = globalImp->m_tasks.erase(it); - globalImpSlots->emitRefreshAssignments(); - break; - } - } + globalImpSlots->emitRefreshAssignments(); + break; + } + } } diff --git a/toonz/sources/common/tcore/tthread_nt.cpp b/toonz/sources/common/tcore/tthread_nt.cpp index 3739a3f..23d895f 100644 --- a/toonz/sources/common/tcore/tthread_nt.cpp +++ b/toonz/sources/common/tcore/tthread_nt.cpp @@ -11,287 +11,238 @@ class TThreadGroupImp; // TMutex & TMutexImp //--------------------------------------------------------------------------- -class TMutexImp -{ - HANDLE id; +class TMutexImp { + HANDLE id; public: - TMutexImp(); - ~TMutexImp(); - void lock(); - void unlock(); + TMutexImp(); + ~TMutexImp(); + void lock(); + void unlock(); }; //--------------------------------------------------------------------------- -class TThreadGroupImp -{ - list threads; +class TThreadGroupImp { + list threads; public: - TThreadGroupImp(); - ~TThreadGroupImp(); - void add(TThread *); - void remove(TThread *); - void wait(); + TThreadGroupImp(); + ~TThreadGroupImp(); + void add(TThread *); + void remove(TThread *); + void wait(); }; //--------------------------------------------------------------------------- -TMutexImp::TMutexImp() -{ - id = CreateMutex(NULL, FALSE, NULL); -} +TMutexImp::TMutexImp() { id = CreateMutex(NULL, FALSE, NULL); } //--------------------------------------------------------------------------- -TMutexImp::~TMutexImp() -{ - BOOL rc = CloseHandle(id); -} +TMutexImp::~TMutexImp() { BOOL rc = CloseHandle(id); } //--------------------------------------------------------------------------- -void TMutexImp::lock() -{ - DWORD rc = WaitForSingleObject(id, INFINITE); -} +void TMutexImp::lock() { DWORD rc = WaitForSingleObject(id, INFINITE); } //--------------------------------------------------------------------------- -void TMutexImp::unlock() -{ - BOOL rc = ReleaseMutex(id); -} +void TMutexImp::unlock() { BOOL rc = ReleaseMutex(id); } //--------------------------------------------------------------------------- -TMutex::TMutex() - : m_imp(new TMutexImp()) -{ -} +TMutex::TMutex() : m_imp(new TMutexImp()) {} //--------------------------------------------------------------------------- -TMutex::~TMutex() -{ - delete m_imp; -} +TMutex::~TMutex() { delete m_imp; } //--------------------------------------------------------------------------- -void TMutex::lock() -{ - m_imp->lock(); -} +void TMutex::lock() { m_imp->lock(); } //--------------------------------------------------------------------------- -void TMutex::unlock() -{ - m_imp->unlock(); -} +void TMutex::unlock() { m_imp->unlock(); } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // TThread & TThreadImp //--------------------------------------------------------------------------- -class TThreadImp -{ +class TThreadImp { public: - friend class TThreadGroupImp; - - HANDLE threadId; - HANDLE mainThread; - int m_refCount; - TMutex secureLock; - bool isRunning; - TThreadGroupImp *owner; - TThread *thread; - - //some static stuff - static TUINT32 nThreads; - static TMutex mutex; - - TThreadImp(); - ~TThreadImp(); - - void start(); - - bool setThreadPriority(TThread::TThreadPriority p); - bool setPreferredProcessor(int processorId); - - static void incNThreads() - { - mutex.lock(); - nThreads++; - mutex.unlock(); - } - static void decNThreads() - { - mutex.lock(); - nThreads--; - mutex.unlock(); - } - - void setOwner(TThreadGroupImp *_owner) { owner = _owner; } + friend class TThreadGroupImp; + + HANDLE threadId; + HANDLE mainThread; + int m_refCount; + TMutex secureLock; + bool isRunning; + TThreadGroupImp *owner; + TThread *thread; + + // some static stuff + static TUINT32 nThreads; + static TMutex mutex; + + TThreadImp(); + ~TThreadImp(); + + void start(); + + bool setThreadPriority(TThread::TThreadPriority p); + bool setPreferredProcessor(int processorId); + + static void incNThreads() { + mutex.lock(); + nThreads++; + mutex.unlock(); + } + static void decNThreads() { + mutex.lock(); + nThreads--; + mutex.unlock(); + } + + void setOwner(TThreadGroupImp *_owner) { owner = _owner; } }; TUINT32 TThreadImp::nThreads = 0; -TMutex TThreadImp::mutex = TMutex(); +TMutex TThreadImp::mutex = TMutex(); //--------------------------------------------------------------------------- TThreadImp::TThreadImp() - : isRunning(false), threadId(0), owner(0), mainThread(0), thread(0), secureLock(), m_refCount(0) -{ -} + : isRunning(false) + , threadId(0) + , owner(0) + , mainThread(0) + , thread(0) + , secureLock() + , m_refCount(0) {} //--------------------------------------------------------------------------- -TThreadImp::~TThreadImp() -{ - if (threadId) - CloseHandle(threadId); +TThreadImp::~TThreadImp() { + if (threadId) CloseHandle(threadId); } //--------------------------------------------------------------------------- -static TUINT32 __stdcall fun(void *data) -{ - TThreadImp *t = (TThreadImp *)data; +static TUINT32 __stdcall fun(void *data) { + TThreadImp *t = (TThreadImp *)data; - t->secureLock.lock(); - if (t->isRunning) { - t->secureLock.unlock(); - assert(!"thread is already running"); - return 0; - } - t->isRunning = true; + t->secureLock.lock(); + if (t->isRunning) { + t->secureLock.unlock(); + assert(!"thread is already running"); + return 0; + } + t->isRunning = true; - t->secureLock.unlock(); + t->secureLock.unlock(); - t->thread->run(); + t->thread->run(); - t->decNThreads(); - if (t->owner) - t->owner->remove(t->thread); - t->thread->release(); - return 0; + t->decNThreads(); + if (t->owner) t->owner->remove(t->thread); + t->thread->release(); + return 0; } //--------------------------------------------------------------------------- -void TThreadImp::start() -{ - TThreadImp::incNThreads(); - threadId = CreateThread(0, 0, fun, this, 0, 0); +void TThreadImp::start() { + TThreadImp::incNThreads(); + threadId = CreateThread(0, 0, fun, this, 0, 0); } //--------------------------------------------------------------------------- -bool TThreadImp::setThreadPriority(TThread::TThreadPriority p) -{ - int priority; - switch (p) { - case TThread::TIME_CRITICAL: - priority = THREAD_PRIORITY_TIME_CRITICAL; - break; - case TThread::HIGHEST: - priority = THREAD_PRIORITY_HIGHEST; - break; - case TThread::ABOVE_NORMAL: - priority = THREAD_PRIORITY_ABOVE_NORMAL; - break; - case TThread::NORMAL: - priority = THREAD_PRIORITY_NORMAL; - break; - case TThread::BELOW_NORMAL: - priority = THREAD_PRIORITY_BELOW_NORMAL; - break; - case TThread::LOWEST: - priority = THREAD_PRIORITY_LOWEST; - break; - case TThread::IDLE: - priority = THREAD_PRIORITY_IDLE; - break; - default: - priority = THREAD_PRIORITY_NORMAL; - break; - } - return !!SetThreadPriority(threadId, priority); +bool TThreadImp::setThreadPriority(TThread::TThreadPriority p) { + int priority; + switch (p) { + case TThread::TIME_CRITICAL: + priority = THREAD_PRIORITY_TIME_CRITICAL; + break; + case TThread::HIGHEST: + priority = THREAD_PRIORITY_HIGHEST; + break; + case TThread::ABOVE_NORMAL: + priority = THREAD_PRIORITY_ABOVE_NORMAL; + break; + case TThread::NORMAL: + priority = THREAD_PRIORITY_NORMAL; + break; + case TThread::BELOW_NORMAL: + priority = THREAD_PRIORITY_BELOW_NORMAL; + break; + case TThread::LOWEST: + priority = THREAD_PRIORITY_LOWEST; + break; + case TThread::IDLE: + priority = THREAD_PRIORITY_IDLE; + break; + default: + priority = THREAD_PRIORITY_NORMAL; + break; + } + return !!SetThreadPriority(threadId, priority); } //--------------------------------------------------------------------------- -bool TThreadImp::setPreferredProcessor(int processorId) -{ - DWORD rc = SetThreadIdealProcessor(threadId, processorId); - return (rc != -1); +bool TThreadImp::setPreferredProcessor(int processorId) { + DWORD rc = SetThreadIdealProcessor(threadId, processorId); + return (rc != -1); } //--------------------------------------------------------------------------- -TThread::TThread() - : m_imp(new TThreadImp()) -{ - m_imp->thread = this; -} +TThread::TThread() : m_imp(new TThreadImp()) { m_imp->thread = this; } //--------------------------------------------------------------------------- -TThread::~TThread() -{ - delete m_imp; -} +TThread::~TThread() { delete m_imp; } //--------------------------------------------------------------------------- -void TThread::start() -{ - addRef(); - m_imp->start(); +void TThread::start() { + addRef(); + m_imp->start(); } //--------------------------------------------------------------------------- -void TThread::addRef() -{ - m_imp->mutex.lock(); - m_imp->m_refCount++; - m_imp->mutex.unlock(); +void TThread::addRef() { + m_imp->mutex.lock(); + m_imp->m_refCount++; + m_imp->mutex.unlock(); } //--------------------------------------------------------------------------- -void TThread::release() -{ - bool kill = false; - m_imp->mutex.lock(); - m_imp->m_refCount--; - if (m_imp->m_refCount <= 0) - kill = true; - m_imp->mutex.unlock(); - if (kill) - delete this; +void TThread::release() { + bool kill = false; + m_imp->mutex.lock(); + m_imp->m_refCount--; + if (m_imp->m_refCount <= 0) kill = true; + m_imp->mutex.unlock(); + if (kill) delete this; } //--------------------------------------------------------------------------- -int TThread::getRefCount() -{ - return m_imp->m_refCount; -} +int TThread::getRefCount() { return m_imp->m_refCount; } //--------------------------------------------------------------------------- -bool TThread::setPreferredProcessor(int processorId) -{ - return m_imp->setPreferredProcessor(processorId); +bool TThread::setPreferredProcessor(int processorId) { + return m_imp->setPreferredProcessor(processorId); } //--------------------------------------------------------------------------- -bool TThread::setThreadPriority(TThread::TThreadPriority p) -{ - return m_imp->setThreadPriority(p); +bool TThread::setThreadPriority(TThread::TThreadPriority p) { + return m_imp->setThreadPriority(p); } //======================= @@ -299,89 +250,71 @@ bool TThread::setThreadPriority(TThread::TThreadPriority p) //--------------------------------------------------------------------------- -TThreadGroupImp::TThreadGroupImp() -{ -} +TThreadGroupImp::TThreadGroupImp() {} //--------------------------------------------------------------------------- -TThreadGroupImp::~TThreadGroupImp() -{ -} +TThreadGroupImp::~TThreadGroupImp() {} //--------------------------------------------------------------------------- -void TThreadGroupImp::add(TThread *t) -{ - threads.push_back(t); - t->m_imp->setOwner(this); +void TThreadGroupImp::add(TThread *t) { + threads.push_back(t); + t->m_imp->setOwner(this); } //--------------------------------------------------------------------------- -void TThreadGroupImp::remove(TThread *t) -{ - threads.remove(t); - t->m_imp->setOwner(0); +void TThreadGroupImp::remove(TThread *t) { + threads.remove(t); + t->m_imp->setOwner(0); } //--------------------------------------------------------------------------- -void TThreadGroupImp::wait() -{ - DWORD count = threads.size(); - if (count == 0) - return; - HANDLE *hThreads = new HANDLE[count]; - int id = 0; - for (list::iterator it = threads.begin(); it != threads.end(); it++, id++) { - TThread *t = *it; - if (t->m_imp->threadId == 0) - t->start(); - hThreads[id] = t->m_imp->threadId; - } - - DWORD rc = WaitForMultipleObjects(count, hThreads, FALSE, INFINITE); - if (rc >= WAIT_OBJECT_0 && rc <= (WAIT_OBJECT_0 + count - 1)) { - // cout << "obj #" << rc << endl; - } - if (rc >= WAIT_ABANDONED_0 && rc <= (WAIT_ABANDONED_0 + count - 1)) { - // cout << "obj #" << rc << " abandoned" << endl; - } - if (rc == WAIT_TIMEOUT) { - // cout << "timeout" << endl; - } - - if (rc == WAIT_FAILED) { - // cout << "failed" << endl; - } - - delete[] hThreads; - wait(); +void TThreadGroupImp::wait() { + DWORD count = threads.size(); + if (count == 0) return; + HANDLE *hThreads = new HANDLE[count]; + int id = 0; + for (list::iterator it = threads.begin(); it != threads.end(); + it++, id++) { + TThread *t = *it; + if (t->m_imp->threadId == 0) t->start(); + hThreads[id] = t->m_imp->threadId; + } + + DWORD rc = WaitForMultipleObjects(count, hThreads, FALSE, INFINITE); + if (rc >= WAIT_OBJECT_0 && rc <= (WAIT_OBJECT_0 + count - 1)) { + // cout << "obj #" << rc << endl; + } + if (rc >= WAIT_ABANDONED_0 && rc <= (WAIT_ABANDONED_0 + count - 1)) { + // cout << "obj #" << rc << " abandoned" << endl; + } + if (rc == WAIT_TIMEOUT) { + // cout << "timeout" << endl; + } + + if (rc == WAIT_FAILED) { + // cout << "failed" << endl; + } + + delete[] hThreads; + wait(); } //--------------------------------------------------------------------------- TThreadGroup::TThreadGroup() - : m_imp(new TThreadGroupImp()) + : m_imp(new TThreadGroupImp()) -{ -} +{} //--------------------------------------------------------------------------- -TThreadGroup::~TThreadGroup() -{ - delete m_imp; -} +TThreadGroup::~TThreadGroup() { delete m_imp; } //--------------------------------------------------------------------------- -void TThreadGroup::add(TThread *t) -{ - m_imp->add(t); -} +void TThreadGroup::add(TThread *t) { m_imp->add(t); } //--------------------------------------------------------------------------- -void TThreadGroup::wait() -{ - m_imp->wait(); -} +void TThreadGroup::wait() { m_imp->wait(); } diff --git a/toonz/sources/common/tcore/tthread_x.cpp b/toonz/sources/common/tcore/tthread_x.cpp index 87adb19..316fa9d 100644 --- a/toonz/sources/common/tcore/tthread_x.cpp +++ b/toonz/sources/common/tcore/tthread_x.cpp @@ -7,341 +7,273 @@ // TMutex & TMutexImp //--------------------------------------------------------------------------- -class TMutexImp -{ - pthread_mutex_t id; +class TMutexImp { + pthread_mutex_t id; public: - TMutexImp(); - ~TMutexImp(); - void lock(); - void unlock(); + TMutexImp(); + ~TMutexImp(); + void lock(); + void unlock(); }; //--------------------------------------------------------------------------- TMutex lockForTheList; -class TThreadGroupImp -{ - list threads; +class TThreadGroupImp { + list threads; public: - TThreadGroupImp(); - ~TThreadGroupImp(); - void add(TThread *); - void remove(TThread *); - void wait(); + TThreadGroupImp(); + ~TThreadGroupImp(); + void add(TThread *); + void remove(TThread *); + void wait(); }; //--------------------------------------------------------------------------- -TMutexImp::TMutexImp() -{ - pthread_mutex_init(&id, 0); -} +TMutexImp::TMutexImp() { pthread_mutex_init(&id, 0); } //--------------------------------------------------------------------------- -TMutexImp::~TMutexImp() -{ - pthread_mutex_destroy(&id); -} +TMutexImp::~TMutexImp() { pthread_mutex_destroy(&id); } //--------------------------------------------------------------------------- -void TMutexImp::lock() -{ - pthread_mutex_lock(&id); -} +void TMutexImp::lock() { pthread_mutex_lock(&id); } //--------------------------------------------------------------------------- -void TMutexImp::unlock() -{ - pthread_mutex_unlock(&id); -} +void TMutexImp::unlock() { pthread_mutex_unlock(&id); } //--------------------------------------------------------------------------- -TMutex::TMutex() - : m_imp(new TMutexImp) -{ -} +TMutex::TMutex() : m_imp(new TMutexImp) {} //--------------------------------------------------------------------------- -TMutex::~TMutex() -{ - delete m_imp; -} +TMutex::~TMutex() { delete m_imp; } //--------------------------------------------------------------------------- -void TMutex::lock() -{ - m_imp->lock(); -} +void TMutex::lock() { m_imp->lock(); } //--------------------------------------------------------------------------- -void TMutex::unlock() -{ - m_imp->unlock(); -} +void TMutex::unlock() { m_imp->unlock(); } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // TThread & TThreadImp //--------------------------------------------------------------------------- -class TThreadImp -{ - pthread_t threadId; +class TThreadImp { + pthread_t threadId; public: - TThreadImp(); - ~TThreadImp(); - - TThread *thread; - - void start(); - - bool setThreadPriority(TThread::TThreadPriority p); - bool setPreferredProcessor(int processorId); - - TMutex secureLock; - bool isRunning; - - static void incNThreads() - { - mutex.lock(); - nThreads++; - mutex.unlock(); - } - static void decNThreads() - { - mutex.lock(); - nThreads--; - mutex.unlock(); - } - - //some static stuff - static TUINT32 nThreads; - static TMutex mutex; - - friend class TThreadGroupImp; - void setOwner(TThreadGroupImp *_owner) { owner = _owner; } - TThreadGroupImp *owner; + TThreadImp(); + ~TThreadImp(); + + TThread *thread; + + void start(); + + bool setThreadPriority(TThread::TThreadPriority p); + bool setPreferredProcessor(int processorId); + + TMutex secureLock; + bool isRunning; + + static void incNThreads() { + mutex.lock(); + nThreads++; + mutex.unlock(); + } + static void decNThreads() { + mutex.lock(); + nThreads--; + mutex.unlock(); + } + + // some static stuff + static TUINT32 nThreads; + static TMutex mutex; + + friend class TThreadGroupImp; + void setOwner(TThreadGroupImp *_owner) { owner = _owner; } + TThreadGroupImp *owner; }; TUINT32 TThreadImp::nThreads = 0; -TMutex TThreadImp::mutex = TMutex(); +TMutex TThreadImp::mutex = TMutex(); //--------------------------------------------------------------------------- -TThreadImp::TThreadImp() - : isRunning(false), owner(0), thread(0) -{ -} +TThreadImp::TThreadImp() : isRunning(false), owner(0), thread(0) {} //--------------------------------------------------------------------------- -TThreadImp::~TThreadImp() -{ - //CloseHandle(threadId); +TThreadImp::~TThreadImp() { + // CloseHandle(threadId); } //--------------------------------------------------------------------------- -static void * /*__stdcall*/ fun(void *data) -{ - TThreadImp *t = (TThreadImp *)data; +static void * /*__stdcall*/ fun(void *data) { + TThreadImp *t = (TThreadImp *)data; - t->secureLock.lock(); - if (t->isRunning) { - t->secureLock.unlock(); - assert(!"thread is already running"); - return 0; - } - t->isRunning = true; + t->secureLock.lock(); + if (t->isRunning) { + t->secureLock.unlock(); + assert(!"thread is already running"); + return 0; + } + t->isRunning = true; - t->secureLock.unlock(); + t->secureLock.unlock(); - t->thread->run(); + t->thread->run(); - t->decNThreads(); - if (t->owner) - t->owner->remove(t->thread); + t->decNThreads(); + if (t->owner) t->owner->remove(t->thread); - return 0; + return 0; } //--------------------------------------------------------------------------- -void TThreadImp::start() -{ - incNThreads(); - pthread_create(&threadId, 0, fun, (void *)this); +void TThreadImp::start() { + incNThreads(); + pthread_create(&threadId, 0, fun, (void *)this); } //--------------------------------------------------------------------------- -bool TThreadImp::setThreadPriority(TThread::TThreadPriority) -{ - assert(!"not implemented"); - return false; +bool TThreadImp::setThreadPriority(TThread::TThreadPriority) { + assert(!"not implemented"); + return false; } //--------------------------------------------------------------------------- -bool TThreadImp::setPreferredProcessor(int processorId) -{ +bool TThreadImp::setPreferredProcessor(int processorId) { #ifdef __sgi #if (OP_RELEASE == rel_2) - assert(!"Not implemented"); - return false; + assert(!"Not implemented"); + return false; #else - int rc = pthread_setrunon_np(processorId); - return (rc != -1); + int rc = pthread_setrunon_np(processorId); + return (rc != -1); #endif #else - assert(0); - return false; + assert(0); + return false; #endif } //--------------------------------------------------------------------------- -TThread::TThread() - : m_imp(new TThreadImp()) -{ - m_imp->thread = this; -} +TThread::TThread() : m_imp(new TThreadImp()) { m_imp->thread = this; } //--------------------------------------------------------------------------- -TThread::~TThread() -{ - delete m_imp; -} +TThread::~TThread() { delete m_imp; } //--------------------------------------------------------------------------- -void TThread::start() -{ - m_imp->start(); -} +void TThread::start() { m_imp->start(); } //--------------------------------------------------------------------------- -bool TThread::setPreferredProcessor(int processorId) -{ - return m_imp->setPreferredProcessor(processorId); +bool TThread::setPreferredProcessor(int processorId) { + return m_imp->setPreferredProcessor(processorId); } //--------------------------------------------------------------------------- -bool TThread::setThreadPriority(TThread::TThreadPriority p) -{ - return m_imp->setThreadPriority(p); +bool TThread::setThreadPriority(TThread::TThreadPriority p) { + return m_imp->setThreadPriority(p); } //======================= // TThreadGroupImp -TThreadGroupImp::TThreadGroupImp() -{ -} +TThreadGroupImp::TThreadGroupImp() {} //--------------------------------------------------------------------------- -TThreadGroupImp::~TThreadGroupImp() -{ -} +TThreadGroupImp::~TThreadGroupImp() {} //--------------------------------------------------------------------------- -void TThreadGroupImp::add(TThread *t) -{ - lockForTheList.lock(); - threads.push_back(t); - lockForTheList.unlock(); - t->m_imp->setOwner(this); +void TThreadGroupImp::add(TThread *t) { + lockForTheList.lock(); + threads.push_back(t); + lockForTheList.unlock(); + t->m_imp->setOwner(this); } //--------------------------------------------------------------------------- -void TThreadGroupImp::remove(TThread *t) -{ - lockForTheList.lock(); - threads.remove(t); - lockForTheList.unlock(); - t->m_imp->setOwner(0); +void TThreadGroupImp::remove(TThread *t) { + lockForTheList.lock(); + threads.remove(t); + lockForTheList.unlock(); + t->m_imp->setOwner(0); } //--------------------------------------------------------------------------- -static void * /*__stdcall*/ mainFun(void *data) -{ - //cout << "mainfun" << endl; - list *threads = (list *)data; - //lockForTheList.lock(); - ULONG s = threads->size(); - //lockForTheList.unlock(); - //cout <<"ci sono " << s << "thread in ballo..." << endl; - - while (s != 0) { - lockForTheList.lock(); - s = threads->size(); - lockForTheList.unlock(); - } - return 0; +static void * /*__stdcall*/ mainFun(void *data) { + // cout << "mainfun" << endl; + list *threads = (list *)data; + // lockForTheList.lock(); + ULONG s = threads->size(); + // lockForTheList.unlock(); + // cout <<"ci sono " << s << "thread in ballo..." << endl; + + while (s != 0) { + lockForTheList.lock(); + s = threads->size(); + lockForTheList.unlock(); + } + return 0; } //--------------------------------------------------------------------------- -void TThreadGroupImp::wait() -{ - //cout << "wait()" << endl; - lockForTheList.lock(); - ULONG count = threads.size(); - - for (list::iterator it = threads.begin(); it != threads.end(); it++) { - TThread *t = *it; - t->start(); - } - lockForTheList.unlock(); - - if (count == 0) - return; - void *mainRet = 0; - pthread_t mainThread; - //cout << "creo il main" << endl; - pthread_create(&mainThread, 0, mainFun, &threads); - //cout << mainThread << endl; - pthread_join(mainThread, &mainRet); +void TThreadGroupImp::wait() { + // cout << "wait()" << endl; + lockForTheList.lock(); + ULONG count = threads.size(); + + for (list::iterator it = threads.begin(); it != threads.end(); + it++) { + TThread *t = *it; + t->start(); + } + lockForTheList.unlock(); + + if (count == 0) return; + void *mainRet = 0; + pthread_t mainThread; + // cout << "creo il main" << endl; + pthread_create(&mainThread, 0, mainFun, &threads); + // cout << mainThread << endl; + pthread_join(mainThread, &mainRet); } //--------------------------------------------------------------------------- TThreadGroup::TThreadGroup() - : m_imp(new TThreadGroupImp()) + : m_imp(new TThreadGroupImp()) -{ -} +{} //--------------------------------------------------------------------------- -TThreadGroup::~TThreadGroup() -{ - delete m_imp; -} +TThreadGroup::~TThreadGroup() { delete m_imp; } //--------------------------------------------------------------------------- -void TThreadGroup::add(TThread *t) -{ - m_imp->add(t); -} +void TThreadGroup::add(TThread *t) { m_imp->add(t); } //--------------------------------------------------------------------------- -void TThreadGroup::wait() -{ - m_imp->wait(); -} +void TThreadGroup::wait() { m_imp->wait(); } diff --git a/toonz/sources/common/tcore/tthreadp.h b/toonz/sources/common/tcore/tthreadp.h index da63f1c..d6319b0 100644 --- a/toonz/sources/common/tcore/tthreadp.h +++ b/toonz/sources/common/tcore/tthreadp.h @@ -13,30 +13,30 @@ // TThreadMessageDispatcher class //-------------------------------------- -//NOTE: This class should eventually be moved to tthreadmessagep.h... -class TThreadMessageDispatcher : public QObject //singleton +// NOTE: This class should eventually be moved to tthreadmessagep.h... +class TThreadMessageDispatcher : public QObject // singleton { - Q_OBJECT + Q_OBJECT public: - TThreadMessageDispatcher(); - Q_SIGNALS : void signaled(TThread::Message *msg); - void blockingSignaled(TThread::Message *msg); + TThreadMessageDispatcher(); +Q_SIGNALS: + void signaled(TThread::Message *msg); + void blockingSignaled(TThread::Message *msg); protected Q_SLOTS: - void onSignal(TThread::Message *msg); + void onSignal(TThread::Message *msg); public: - void emitSignaled(TThread::Message *msg); - void emitBlockingSignaled(TThread::Message *msg); - static void init(); - static TThreadMessageDispatcher *instance(); + void emitSignaled(TThread::Message *msg); + void emitBlockingSignaled(TThread::Message *msg); + static void init(); + static TThreadMessageDispatcher *instance(); }; //===================================================================== -namespace TThread -{ -//Forward declarations +namespace TThread { +// Forward declarations class ExecutorId; class ExecutorImpSlots; } @@ -47,28 +47,30 @@ class ExecutorImpSlots; // ExecutorImpSlots class //------------------------------ -class TThread::ExecutorImpSlots : public QObject -{ - Q_OBJECT +class TThread::ExecutorImpSlots : public QObject { + Q_OBJECT public: - ExecutorImpSlots(); - ~ExecutorImpSlots(); + ExecutorImpSlots(); + ~ExecutorImpSlots(); - //The following is provided to ensure that point #3 in Qt reference in page "Thread support in Qt" - //is satisfied: + // The following is provided to ensure that point #3 in Qt reference in page + // "Thread support in Qt" + // is satisfied: - // "You must ensure that all objects created in - // a thread are deleted before you delete the QThread." + // "You must ensure that all objects created in + // a thread are deleted before you delete the QThread." - //So, specifically, thread creation should happen only in the main thread, not in worker threads. - void emitRefreshAssignments(); + // So, specifically, thread creation should happen only in the main thread, + // not in worker threads. + void emitRefreshAssignments(); - Q_SIGNALS : void refreshAssignments(); +Q_SIGNALS: + void refreshAssignments(); public Q_SLOTS: - void onTerminated(); - void onRefreshAssignments(); + void onTerminated(); + void onRefreshAssignments(); }; #endif diff --git a/toonz/sources/common/tcore/tundo.cpp b/toonz/sources/common/tcore/tundo.cpp index b1c8a85..dba65f6 100644 --- a/toonz/sources/common/tcore/tundo.cpp +++ b/toonz/sources/common/tcore/tundo.cpp @@ -7,113 +7,97 @@ using std::for_each; -namespace -{ +namespace { void deleteUndo(const TUndo *undo) { delete undo; } void callUndo(const TUndo *undo) { undo->undo(); } void callRedo(const TUndo *undo) { undo->redo(); } // void callRepeat(const TUndo* undo) {undo->repeat(); } -class TUndoBlock : public TUndo -{ - std::vector m_undos; - typedef std::vector::const_iterator Iterator; - typedef std::vector::const_reverse_iterator ReverseIterator; - mutable bool m_deleted, m_undoing; +class TUndoBlock : public TUndo { + std::vector m_undos; + typedef std::vector::const_iterator Iterator; + typedef std::vector::const_reverse_iterator ReverseIterator; + mutable bool m_deleted, m_undoing; public: - TUndoBlock() : m_deleted(false), m_undoing(false) {} - ~TUndoBlock() - { - assert(m_undoing == false); - assert(m_deleted == false); - m_deleted = true; - for_each(m_undos.begin(), m_undos.end(), deleteUndo); - m_undos.clear(); - } - - int getSize() const - { - int size = sizeof(*this); - for (Iterator cit = m_undos.begin(); cit != m_undos.end(); ++cit) - size += (*cit)->getSize(); - size += (m_undos.capacity() - m_undos.size()) * sizeof(TUndo *); - return size; - } - int getUndoCount() const - { - return (int)m_undos.size(); - } - void setLast() - { - for (UINT i = 1; i < m_undos.size(); i++) - m_undos[i]->m_isLastInBlock = false; - m_undos[0]->m_isLastInBlock = true; - } - - void undo() const - { - assert(!m_deleted); - assert(!m_undoing); - m_undoing = true; - //VERSIONE CORRETTA - for_each(m_undos.rbegin(), m_undos.rend(), callUndo); - //VERSIONE SBAGLIATA - //for_each(m_undos.begin(), m_undos.end(), callUndo); - m_undoing = false; - } - void redo() const - { - assert(!m_deleted); - //VERSIONE CORRETTA - for_each(m_undos.begin(), m_undos.end(), callRedo); - //VERSIONE SBAGLIATA - //for_each(m_undos.rbegin(), m_undos.rend(), callRedo); - } - - //void repeat() const { - // for_each(m_undos.begin(), m_undos.end(), callRepeat); - //} - void onAdd() {} - void add(TUndo *undo) - { - undo->m_isLastInBlock = true; - m_undos.push_back(undo); - } - - void popUndo(int n) - { - if (n == -1) - n = m_undos.size(); - if (m_undos.empty() || n <= 0) - return; - while (n > 0 && !m_undos.empty()) { - TUndo *undo = m_undos.back(); - m_undos.pop_back(); - delete undo; - n--; - } - } - - virtual QString getHistoryString() - { - if (m_undos.empty()) - return TUndo::getHistoryString(); - else if ((int)m_undos.size() == 1) - return m_undos.back()->getHistoryString(); - else { - return QString("%1 etc..").arg(m_undos.back()->getHistoryString()); - } - } - - virtual int getHistoryType() - { - if (m_undos.empty()) - return TUndo::getHistoryType(); - else - return m_undos.back()->getHistoryType(); - } + TUndoBlock() : m_deleted(false), m_undoing(false) {} + ~TUndoBlock() { + assert(m_undoing == false); + assert(m_deleted == false); + m_deleted = true; + for_each(m_undos.begin(), m_undos.end(), deleteUndo); + m_undos.clear(); + } + + int getSize() const { + int size = sizeof(*this); + for (Iterator cit = m_undos.begin(); cit != m_undos.end(); ++cit) + size += (*cit)->getSize(); + size += (m_undos.capacity() - m_undos.size()) * sizeof(TUndo *); + return size; + } + int getUndoCount() const { return (int)m_undos.size(); } + void setLast() { + for (UINT i = 1; i < m_undos.size(); i++) + m_undos[i]->m_isLastInBlock = false; + m_undos[0]->m_isLastInBlock = true; + } + + void undo() const { + assert(!m_deleted); + assert(!m_undoing); + m_undoing = true; + // VERSIONE CORRETTA + for_each(m_undos.rbegin(), m_undos.rend(), callUndo); + // VERSIONE SBAGLIATA + // for_each(m_undos.begin(), m_undos.end(), callUndo); + m_undoing = false; + } + void redo() const { + assert(!m_deleted); + // VERSIONE CORRETTA + for_each(m_undos.begin(), m_undos.end(), callRedo); + // VERSIONE SBAGLIATA + // for_each(m_undos.rbegin(), m_undos.rend(), callRedo); + } + + // void repeat() const { + // for_each(m_undos.begin(), m_undos.end(), callRepeat); + //} + void onAdd() {} + void add(TUndo *undo) { + undo->m_isLastInBlock = true; + m_undos.push_back(undo); + } + + void popUndo(int n) { + if (n == -1) n = m_undos.size(); + if (m_undos.empty() || n <= 0) return; + while (n > 0 && !m_undos.empty()) { + TUndo *undo = m_undos.back(); + m_undos.pop_back(); + delete undo; + n--; + } + } + + virtual QString getHistoryString() { + if (m_undos.empty()) + return TUndo::getHistoryString(); + else if ((int)m_undos.size() == 1) + return m_undos.back()->getHistoryString(); + else { + return QString("%1 etc..").arg(m_undos.back()->getHistoryString()); + } + } + + virtual int getHistoryType() { + if (m_undos.empty()) + return TUndo::getHistoryType(); + else + return m_undos.back()->getHistoryType(); + } }; } @@ -124,181 +108,172 @@ typedef UndoList::const_iterator UndoListConstIterator; //----------------------------------------------------------------------------- struct TUndoManager::TUndoManagerImp { - UndoList m_undoList; - UndoListIterator m_current; - bool m_skipped; - int m_undoMemorySize; // in bytes + UndoList m_undoList; + UndoListIterator m_current; + bool m_skipped; + int m_undoMemorySize; // in bytes - std::vector m_blockStack; + std::vector m_blockStack; public: - TUndoManagerImp() : m_skipped(false), m_undoMemorySize(0) { m_current = m_undoList.end(); } - ~TUndoManagerImp() {} + TUndoManagerImp() : m_skipped(false), m_undoMemorySize(0) { + m_current = m_undoList.end(); + } + ~TUndoManagerImp() {} - void add(TUndo *undo); + void add(TUndo *undo); public: - static struct ManagerPtr { - TUndoManager *m_ptr; + static struct ManagerPtr { + TUndoManager *m_ptr; - public: - ManagerPtr() : m_ptr(0) {} - ~ManagerPtr() - { - if (m_ptr) - delete m_ptr; - m_ptr = 0; - } + public: + ManagerPtr() : m_ptr(0) {} + ~ManagerPtr() { + if (m_ptr) delete m_ptr; + m_ptr = 0; + } - } theManager; + } theManager; private: - void doAdd(TUndo *undo); + void doAdd(TUndo *undo); }; //============================================================================= -TUndoManager::TUndoManagerImp::ManagerPtr TUndoManager::TUndoManagerImp::theManager; +TUndoManager::TUndoManagerImp::ManagerPtr + TUndoManager::TUndoManagerImp::theManager; //----------------------------------------------------------------------------- -TUndoManager *TUndoManager::manager() -{ - if (!TUndoManagerImp::theManager.m_ptr) - TUndoManagerImp::theManager.m_ptr = new TUndoManager; - return TUndoManagerImp::theManager.m_ptr; +TUndoManager *TUndoManager::manager() { + if (!TUndoManagerImp::theManager.m_ptr) + TUndoManagerImp::theManager.m_ptr = new TUndoManager; + return TUndoManagerImp::theManager.m_ptr; } //============================================================================= -TUndoManager::TUndoManager() - : m_imp(new TUndoManagerImp) -{ -} +TUndoManager::TUndoManager() : m_imp(new TUndoManagerImp) {} //----------------------------------------------------------------------------- -TUndoManager::~TUndoManager() -{ - //cout << "Distrutto undo manager" << endl; - assert(m_imp->m_blockStack.empty()); - reset(); +TUndoManager::~TUndoManager() { + // cout << "Distrutto undo manager" << endl; + assert(m_imp->m_blockStack.empty()); + reset(); } //----------------------------------------------------------------------------- -void TUndoManager::TUndoManagerImp::add(TUndo *undo) -{ - assert(undo); +void TUndoManager::TUndoManagerImp::add(TUndo *undo) { + assert(undo); - if (!m_blockStack.empty()) { - assert(m_current == m_undoList.end()); - m_blockStack.back()->add(undo); - } else - doAdd(undo); + if (!m_blockStack.empty()) { + assert(m_current == m_undoList.end()); + m_blockStack.back()->add(undo); + } else + doAdd(undo); } //----------------------------------------------------------------------------- -void TUndoManager::TUndoManagerImp::doAdd(TUndo *undo) -{ - if (m_current != m_undoList.end()) { - for_each(m_current, m_undoList.end(), deleteUndo); - m_undoList.erase(m_current, m_undoList.end()); - } - - int i, memorySize = 0, count = m_undoList.size(); - for (i = 0; i < count; i++) - memorySize += m_undoList[i]->getSize(); - - while (count > 100 || (count != 0 && memorySize + undo->getSize() > m_undoMemorySize)) //20MB - { - --count; - TUndo *undo = m_undoList.front(); - m_undoList.pop_front(); - memorySize -= undo->getSize(); - delete undo; - } - - undo->m_isLastInBlock = true; - m_undoList.push_back(undo); - m_current = m_undoList.end(); +void TUndoManager::TUndoManagerImp::doAdd(TUndo *undo) { + if (m_current != m_undoList.end()) { + for_each(m_current, m_undoList.end(), deleteUndo); + m_undoList.erase(m_current, m_undoList.end()); + } + + int i, memorySize = 0, count = m_undoList.size(); + for (i = 0; i < count; i++) memorySize += m_undoList[i]->getSize(); + + while ( + count > 100 || + (count != 0 && memorySize + undo->getSize() > m_undoMemorySize)) // 20MB + { + --count; + TUndo *undo = m_undoList.front(); + m_undoList.pop_front(); + memorySize -= undo->getSize(); + delete undo; + } + + undo->m_isLastInBlock = true; + m_undoList.push_back(undo); + m_current = m_undoList.end(); } //----------------------------------------------------------------------------- -void TUndoManager::beginBlock() -{ - if (m_imp->m_current != m_imp->m_undoList.end()) { - for_each(m_imp->m_current, m_imp->m_undoList.end(), deleteUndo); - m_imp->m_undoList.erase(m_imp->m_current, m_imp->m_undoList.end()); - } - - TUndoBlock *undoBlock = new TUndoBlock; - m_imp->m_blockStack.push_back(undoBlock); - m_imp->m_current = m_imp->m_undoList.end(); +void TUndoManager::beginBlock() { + if (m_imp->m_current != m_imp->m_undoList.end()) { + for_each(m_imp->m_current, m_imp->m_undoList.end(), deleteUndo); + m_imp->m_undoList.erase(m_imp->m_current, m_imp->m_undoList.end()); + } + + TUndoBlock *undoBlock = new TUndoBlock; + m_imp->m_blockStack.push_back(undoBlock); + m_imp->m_current = m_imp->m_undoList.end(); } //----------------------------------------------------------------------------- -void TUndoManager::endBlock() -{ - //vogliamo fare anche resize del vector ??? - assert(m_imp->m_blockStack.empty() == false); - TUndoBlock *undoBlock = m_imp->m_blockStack.back(); - m_imp->m_blockStack.pop_back(); - if (undoBlock->getUndoCount() > 0) { - undoBlock->setLast(); - m_imp->add(undoBlock); - emit historyChanged(); - } else { - delete undoBlock; - m_imp->m_current = m_imp->m_undoList.end(); - } +void TUndoManager::endBlock() { + // vogliamo fare anche resize del vector ??? + assert(m_imp->m_blockStack.empty() == false); + TUndoBlock *undoBlock = m_imp->m_blockStack.back(); + m_imp->m_blockStack.pop_back(); + if (undoBlock->getUndoCount() > 0) { + undoBlock->setLast(); + m_imp->add(undoBlock); + emit historyChanged(); + } else { + delete undoBlock; + m_imp->m_current = m_imp->m_undoList.end(); + } } //----------------------------------------------------------------------------- -bool TUndoManager::undo() -{ - assert(m_imp->m_blockStack.empty()); - UndoListIterator &it = m_imp->m_current; - if (it != m_imp->m_undoList.begin()) { - m_imp->m_skipped = false; - --it; - (*it)->undo(); - emit historyChanged(); - if (m_imp->m_skipped) { - m_imp->m_skipped = false; - return undo(); - } - return true; - } else - return false; +bool TUndoManager::undo() { + assert(m_imp->m_blockStack.empty()); + UndoListIterator &it = m_imp->m_current; + if (it != m_imp->m_undoList.begin()) { + m_imp->m_skipped = false; + --it; + (*it)->undo(); + emit historyChanged(); + if (m_imp->m_skipped) { + m_imp->m_skipped = false; + return undo(); + } + return true; + } else + return false; } //----------------------------------------------------------------------------- -bool TUndoManager::redo() -{ - assert(m_imp->m_blockStack.empty()); - UndoListIterator &it = m_imp->m_current; - if (it != m_imp->m_undoList.end()) { - m_imp->m_skipped = false; - (*it)->redo(); - ++it; - emit historyChanged(); - if (m_imp->m_skipped) { - m_imp->m_skipped = false; - return redo(); - } - return true; - } else - return false; +bool TUndoManager::redo() { + assert(m_imp->m_blockStack.empty()); + UndoListIterator &it = m_imp->m_current; + if (it != m_imp->m_undoList.end()) { + m_imp->m_skipped = false; + (*it)->redo(); + ++it; + emit historyChanged(); + if (m_imp->m_skipped) { + m_imp->m_skipped = false; + return redo(); + } + return true; + } else + return false; } //----------------------------------------------------------------------------- -//repeat e' come redo ma non sposta il puntatore al corrente +// repeat e' come redo ma non sposta il puntatore al corrente /* void TUndoManager::repeat() { @@ -313,149 +288,129 @@ void TUndoManager::repeat() //----------------------------------------------------------------------------- -void TUndoManager::skip() -{ - m_imp->m_skipped = true; -} +void TUndoManager::skip() { m_imp->m_skipped = true; } //----------------------------------------------------------------------------- -void TUndoManager::setUndoMemorySize(int memorySyze) -{ - m_imp->m_undoMemorySize = 1048576 * memorySyze; +void TUndoManager::setUndoMemorySize(int memorySyze) { + m_imp->m_undoMemorySize = 1048576 * memorySyze; } //----------------------------------------------------------------------------- -void TUndoManager::add(TUndo *undo) -{ - assert(undo); - if (!undo) - return; +void TUndoManager::add(TUndo *undo) { + assert(undo); + if (!undo) return; - m_imp->add(undo); - Q_EMIT historyChanged(); + m_imp->add(undo); + Q_EMIT historyChanged(); - undo->onAdd(); - Q_EMIT somethingChanged(); + undo->onAdd(); + Q_EMIT somethingChanged(); } //----------------------------------------------------------------------------- -void TUndoManager::reset() -{ - assert(m_imp->m_blockStack.empty()); - m_imp->m_blockStack.clear(); - UndoList &lst = m_imp->m_undoList; - for_each(lst.begin(), lst.end(), deleteUndo); - lst.clear(); - m_imp->m_current = m_imp->m_undoList.end(); - Q_EMIT historyChanged(); +void TUndoManager::reset() { + assert(m_imp->m_blockStack.empty()); + m_imp->m_blockStack.clear(); + UndoList &lst = m_imp->m_undoList; + for_each(lst.begin(), lst.end(), deleteUndo); + lst.clear(); + m_imp->m_current = m_imp->m_undoList.end(); + Q_EMIT historyChanged(); } //----------------------------------------------------------------------------- -void TUndoManager::popUndo(int n, bool forward) -{ - if (!forward) { - if (m_imp->m_blockStack.empty()) { - if (n == -1) { - UndoListIterator start = m_imp->m_undoList.begin(); - n = 0; - while (start != m_imp->m_current) - ++n; - } - if (m_imp->m_undoList.empty() || n <= 0) - return; - if (m_imp->m_current == m_imp->m_undoList.end()) { - int i; - for (i = 0; i < n && m_imp->m_current != m_imp->m_undoList.begin(); i++) { - m_imp->m_current--; - delete (*m_imp->m_current); - m_imp->m_undoList.erase(m_imp->m_current); - m_imp->m_current = m_imp->m_undoList.end(); - } - } else { - TUndo *undo = *m_imp->m_current; - UndoListIterator start, end = m_imp->m_current; - if (end == m_imp->m_undoList.begin()) - return; - - int i; - for (i = 0; i < n && m_imp->m_current != m_imp->m_undoList.begin(); i++) - m_imp->m_current--; - - start = m_imp->m_current; - UndoListIterator _end = end; - while (_end != start) { - _end--; - delete (*_end); - } - m_imp->m_undoList.erase(start, end); - - m_imp->m_current = m_imp->m_undoList.begin(); - while (*m_imp->m_current != undo) - m_imp->m_current++; - } - } else - m_imp->m_blockStack.back()->popUndo(n); - return; - } - - if (m_imp->m_current == m_imp->m_undoList.end()) - return; - if (m_imp->m_blockStack.empty()) { - UndoListIterator end, start = m_imp->m_current++; - if (n == -1) - end = m_imp->m_undoList.end(); - else { - UndoListIterator it = start; - end = it; - int i = 0; - while (i != n && end != m_imp->m_undoList.end()) { - ++end; - i++; - } - } - for_each(start, end, deleteUndo); - m_imp->m_undoList.erase(start, end); - m_imp->m_current = m_imp->m_undoList.end(); - } else - m_imp->m_blockStack.back()->popUndo(n); +void TUndoManager::popUndo(int n, bool forward) { + if (!forward) { + if (m_imp->m_blockStack.empty()) { + if (n == -1) { + UndoListIterator start = m_imp->m_undoList.begin(); + n = 0; + while (start != m_imp->m_current) ++n; + } + if (m_imp->m_undoList.empty() || n <= 0) return; + if (m_imp->m_current == m_imp->m_undoList.end()) { + int i; + for (i = 0; i < n && m_imp->m_current != m_imp->m_undoList.begin(); + i++) { + m_imp->m_current--; + delete (*m_imp->m_current); + m_imp->m_undoList.erase(m_imp->m_current); + m_imp->m_current = m_imp->m_undoList.end(); + } + } else { + TUndo *undo = *m_imp->m_current; + UndoListIterator start, end = m_imp->m_current; + if (end == m_imp->m_undoList.begin()) return; + + int i; + for (i = 0; i < n && m_imp->m_current != m_imp->m_undoList.begin(); i++) + m_imp->m_current--; + + start = m_imp->m_current; + UndoListIterator _end = end; + while (_end != start) { + _end--; + delete (*_end); + } + m_imp->m_undoList.erase(start, end); + + m_imp->m_current = m_imp->m_undoList.begin(); + while (*m_imp->m_current != undo) m_imp->m_current++; + } + } else + m_imp->m_blockStack.back()->popUndo(n); + return; + } + + if (m_imp->m_current == m_imp->m_undoList.end()) return; + if (m_imp->m_blockStack.empty()) { + UndoListIterator end, start = m_imp->m_current++; + if (n == -1) + end = m_imp->m_undoList.end(); + else { + UndoListIterator it = start; + end = it; + int i = 0; + while (i != n && end != m_imp->m_undoList.end()) { + ++end; + i++; + } + } + for_each(start, end, deleteUndo); + m_imp->m_undoList.erase(start, end); + m_imp->m_current = m_imp->m_undoList.end(); + } else + m_imp->m_blockStack.back()->popUndo(n); } //----------------------------------------------------------------------------- -int TUndoManager::getHistoryCount() -{ - return (int)m_imp->m_undoList.size(); -} +int TUndoManager::getHistoryCount() { return (int)m_imp->m_undoList.size(); } //----------------------------------------------------------------------------- -int TUndoManager::getCurrentHistoryIndex() -{ - int index = 0; - UndoListIterator it = m_imp->m_undoList.begin(); - while (1) { - if (it == m_imp->m_current) - return index; - - if (it == m_imp->m_undoList.end()) - break; - - index++; - it++; - } - return 0; +int TUndoManager::getCurrentHistoryIndex() { + int index = 0; + UndoListIterator it = m_imp->m_undoList.begin(); + while (1) { + if (it == m_imp->m_current) return index; + + if (it == m_imp->m_undoList.end()) break; + + index++; + it++; + } + return 0; } //----------------------------------------------------------------------------- -TUndo *TUndoManager::getUndoItem(int index) -{ - if (index > (int)m_imp->m_undoList.size() || index <= 0) - return 0; +TUndo *TUndoManager::getUndoItem(int index) { + if (index > (int)m_imp->m_undoList.size() || index <= 0) return 0; - return m_imp->m_undoList.at(index - 1); + return m_imp->m_undoList.at(index - 1); } diff --git a/toonz/sources/common/tfx/binaryFx.cpp b/toonz/sources/common/tfx/binaryFx.cpp index e24e380..fe58a8e 100644 --- a/toonz/sources/common/tfx/binaryFx.cpp +++ b/toonz/sources/common/tfx/binaryFx.cpp @@ -16,16 +16,14 @@ // Local namespace //****************************************************************************************** -namespace -{ -void makeRectCoherent(TRectD &rect, const TPointD &pos) -{ - rect -= pos; - rect.x0 = tfloor(rect.x0); - rect.y0 = tfloor(rect.y0); - rect.x1 = tceil(rect.x1); - rect.y1 = tceil(rect.y1); - rect += pos; +namespace { +void makeRectCoherent(TRectD &rect, const TPointD &pos) { + rect -= pos; + rect.x0 = tfloor(rect.x0); + rect.y0 = tfloor(rect.y0); + rect.x1 = tceil(rect.x1); + rect.y1 = tceil(rect.y1); + rect += pos; } } @@ -33,721 +31,635 @@ void makeRectCoherent(TRectD &rect, const TPointD &pos) // TImageCombinationFx declaration //****************************************************************************************** -class TImageCombinationFx : public TBaseRasterFx -{ - TFxPortDG m_group; +class TImageCombinationFx : public TBaseRasterFx { + TFxPortDG m_group; public: - TImageCombinationFx(); - virtual ~TImageCombinationFx() {} + TImageCombinationFx(); + virtual ~TImageCombinationFx() {} public: - // Virtual interface for heirs + // Virtual interface for heirs - //! The raster processing function that must be reimplemented to perform the fx - virtual void process(const TRasterP &up, const TRasterP &down, double frame) = 0; + //! The raster processing function that must be reimplemented to perform the + //! fx + virtual void process(const TRasterP &up, const TRasterP &down, + double frame) = 0; - //! Whether the 'up' rasters of process() invocations must be allocated to - //! entirely cover the 'down' counterpart. Should be enabled if the process() - //! function affects 'down' pixels when the 'up's are fully transparent. - virtual bool requiresFullRect() { return false; } + //! Whether the 'up' rasters of process() invocations must be allocated to + //! entirely cover the 'down' counterpart. Should be enabled if the process() + //! function affects 'down' pixels when the 'up's are fully transparent. + virtual bool requiresFullRect() { return false; } public: - // Low-level TRasterFx-related functions + // Low-level TRasterFx-related functions - int dynamicPortGroupsCount() const { return 1; } - const TFxPortDG *dynamicPortGroup(int g) const { return (g == 0) ? &m_group : 0; } + int dynamicPortGroupsCount() const { return 1; } + const TFxPortDG *dynamicPortGroup(int g) const { + return (g == 0) ? &m_group : 0; + } - bool canHandle(const TRenderSettings &info, double frame) { return true; } + bool canHandle(const TRenderSettings &info, double frame) { return true; } - int getMemoryRequirement(const TRectD &rect, double frame, const TRenderSettings &info) - { - // At max the memory of another tile with the same infos may be allocated apart from - // the externally supplied one. - return TRasterFx::memorySize(rect, info.m_bpp); - } + int getMemoryRequirement(const TRectD &rect, double frame, + const TRenderSettings &info) { + // At max the memory of another tile with the same infos may be allocated + // apart from + // the externally supplied one. + return TRasterFx::memorySize(rect, info.m_bpp); + } - bool doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info); + bool doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info); - void doDryCompute(TRectD &rect, double frame, const TRenderSettings &info); - void doCompute(TTile &tile, double frame, const TRenderSettings &info); + void doDryCompute(TRectD &rect, double frame, const TRenderSettings &info); + void doCompute(TTile &tile, double frame, const TRenderSettings &info); - void compatibilityTranslatePort(int majorVersion, int minorVersion, std::string &portName); + void compatibilityTranslatePort(int majorVersion, int minorVersion, + std::string &portName); - int getPreferredInputPort() { return 1; } + int getPreferredInputPort() { return 1; } }; //****************************************************************************************** // TImageCombinationFx implementation //****************************************************************************************** -TImageCombinationFx::TImageCombinationFx() - : m_group("Source", 2) -{ - addInputPort("Source1", new TRasterFxPort, 0); - addInputPort("Source2", new TRasterFxPort, 0); - setName(L"ImageCombinationFx"); +TImageCombinationFx::TImageCombinationFx() : m_group("Source", 2) { + addInputPort("Source1", new TRasterFxPort, 0); + addInputPort("Source2", new TRasterFxPort, 0); + setName(L"ImageCombinationFx"); } //--------------------------------------------------------------------------- -bool TImageCombinationFx::doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info) -{ - bBox = TRectD(); +bool TImageCombinationFx::doGetBBox(double frame, TRectD &bBox, + const TRenderSettings &info) { + bBox = TRectD(); - int p, pCount = getInputPortCount(); - for (p = 0; p != pCount; ++p) { - TRasterFxPort *port = static_cast(getInputPort(p)); - TRectD inputBBox; + int p, pCount = getInputPortCount(); + for (p = 0; p != pCount; ++p) { + TRasterFxPort *port = static_cast(getInputPort(p)); + TRectD inputBBox; - bool hasInput = (port && port->isConnected()) ? (*port)->doGetBBox(frame, inputBBox, info) : false; + bool hasInput = (port && port->isConnected()) + ? (*port)->doGetBBox(frame, inputBBox, info) + : false; - if (hasInput) - bBox += inputBBox; - } + if (hasInput) bBox += inputBBox; + } - return (bBox.getLx() >= 0) && (bBox.getLy() >= 0); + return (bBox.getLx() >= 0) && (bBox.getLy() >= 0); } //--------------------------------------------------------------------------- -void TImageCombinationFx::doCompute(TTile &tile, double frame, const TRenderSettings &info) -{ - int p, pCount = getInputPortCount(); - TRasterFxPort *port = 0; - - // Skip empty ports - for (p = pCount - 1; p >= 0; --p) // Reverse iteration - bottom ports have high indices - { - port = static_cast(getInputPort(p)); - if (port && port->getFx()) - break; - } - - // If there is no input, clear and return - if (p < 0) { - tile.getRaster()->clear(); // Probably not necessary unless externally invocation - return; // deliberately soiled tile - however, should be rare anyway. - } - - // Calculate the tiles' geometries - const TRect &tileRect(tile.getRaster()->getBounds()); - const TDimension &tileSize(tileRect.getSize()); - TRectD tileRectD(tile.m_pos, TDimensionD(tileSize.lx, tileSize.ly)); - - // Render the first viable port directly on tile - (*port)->compute(tile, frame, info); // Should we do it only if the bbox is not empty? - - // Then, render each subsequent port and process() it on top of tile - bool canRestrict = !requiresFullRect(); - - for (--p; p >= 0; --p) { - port = static_cast(getInputPort(p)); - if (!(port && port->getFx())) // Skip empty ports - continue; - - // Will allocate a new tile to calculate the input contribution - so, if possible - // we'll restrict allocation to the input port's bbox - TRectD computeRect(tileRectD); - - if (canRestrict) { - TRectD inBBox; - (*port)->getBBox(frame, inBBox, info); - - computeRect *= inBBox; - - makeRectCoherent(computeRect, tile.m_pos); // Make it coherent with tile's pixel geometry - } - - // Calculate the input port and perform processing - TDimension computeSize(tround(computeRect.getLx()), tround(computeRect.getLy())); - if ((computeSize.lx > 0) && (computeSize.ly > 0)) { - TTile inTile; // Observe its locality - not incidental - (*port)->allocateAndCompute(inTile, computeRect.getP00(), computeSize, - tile.getRaster(), frame, info); - - // Invoke process() to deal with the actual fx processing - TRasterP up(inTile.getRaster()), down(tile.getRaster()); - - if (canRestrict) { - // Extract from tile the part corresponding to inTile - TRect downRect(convert(computeRect.getP00() - tile.m_pos), computeSize); - down = down->extract(downRect); - } - - assert(up->getSize() == down->getSize()); - process(up, down, frame); // This is the point with the max concentration - // of allocated resources - } - } +void TImageCombinationFx::doCompute(TTile &tile, double frame, + const TRenderSettings &info) { + int p, pCount = getInputPortCount(); + TRasterFxPort *port = 0; + + // Skip empty ports + for (p = pCount - 1; p >= 0; + --p) // Reverse iteration - bottom ports have high indices + { + port = static_cast(getInputPort(p)); + if (port && port->getFx()) break; + } + + // If there is no input, clear and return + if (p < 0) { + tile.getRaster() + ->clear(); // Probably not necessary unless externally invocation + return; // deliberately soiled tile - however, should be rare anyway. + } + + // Calculate the tiles' geometries + const TRect &tileRect(tile.getRaster()->getBounds()); + const TDimension &tileSize(tileRect.getSize()); + TRectD tileRectD(tile.m_pos, TDimensionD(tileSize.lx, tileSize.ly)); + + // Render the first viable port directly on tile + (*port)->compute(tile, frame, + info); // Should we do it only if the bbox is not empty? + + // Then, render each subsequent port and process() it on top of tile + bool canRestrict = !requiresFullRect(); + + for (--p; p >= 0; --p) { + port = static_cast(getInputPort(p)); + if (!(port && port->getFx())) // Skip empty ports + continue; + + // Will allocate a new tile to calculate the input contribution - so, if + // possible + // we'll restrict allocation to the input port's bbox + TRectD computeRect(tileRectD); + + if (canRestrict) { + TRectD inBBox; + (*port)->getBBox(frame, inBBox, info); + + computeRect *= inBBox; + + makeRectCoherent( + computeRect, + tile.m_pos); // Make it coherent with tile's pixel geometry + } + + // Calculate the input port and perform processing + TDimension computeSize(tround(computeRect.getLx()), + tround(computeRect.getLy())); + if ((computeSize.lx > 0) && (computeSize.ly > 0)) { + TTile inTile; // Observe its locality - not incidental + (*port)->allocateAndCompute(inTile, computeRect.getP00(), computeSize, + tile.getRaster(), frame, info); + + // Invoke process() to deal with the actual fx processing + TRasterP up(inTile.getRaster()), down(tile.getRaster()); + + if (canRestrict) { + // Extract from tile the part corresponding to inTile + TRect downRect(convert(computeRect.getP00() - tile.m_pos), computeSize); + down = down->extract(downRect); + } + + assert(up->getSize() == down->getSize()); + process(up, down, frame); // This is the point with the max concentration + // of allocated resources + } + } } //------------------------------------------------------------------------------------- -void TImageCombinationFx::doDryCompute( - TRectD &rect, double frame, const TRenderSettings &info) -{ - // Mere copy of doCompute(), stripped of the actual computations +void TImageCombinationFx::doDryCompute(TRectD &rect, double frame, + const TRenderSettings &info) { + // Mere copy of doCompute(), stripped of the actual computations - int p, pCount = getInputPortCount(); - TRasterFxPort *port = 0; + int p, pCount = getInputPortCount(); + TRasterFxPort *port = 0; - for (p = pCount - 1; p >= 0; --p) { - port = static_cast(getInputPort(p)); - if (port && port->getFx()) - break; - } + for (p = pCount - 1; p >= 0; --p) { + port = static_cast(getInputPort(p)); + if (port && port->getFx()) break; + } - if (p < 0) - return; + if (p < 0) return; - (*port)->dryCompute(rect, frame, info); + (*port)->dryCompute(rect, frame, info); - bool canRestrict = !requiresFullRect(); + bool canRestrict = !requiresFullRect(); - for (--p; p >= 0; --p) { - port = static_cast(getInputPort(p)); - if (!(port && port->getFx())) - continue; + for (--p; p >= 0; --p) { + port = static_cast(getInputPort(p)); + if (!(port && port->getFx())) continue; - TRectD computeRect(rect); + TRectD computeRect(rect); - if (canRestrict) { - TRectD inBBox; - (*port)->getBBox(frame, inBBox, info); + if (canRestrict) { + TRectD inBBox; + (*port)->getBBox(frame, inBBox, info); - computeRect *= inBBox; - makeRectCoherent(computeRect, rect.getP00()); - } + computeRect *= inBBox; + makeRectCoherent(computeRect, rect.getP00()); + } - TDimension computeSize(tround(computeRect.getLx()), tround(computeRect.getLy())); - if ((computeSize.lx > 0) && (computeSize.ly > 0)) - (*port)->dryCompute(computeRect, frame, info); - } + TDimension computeSize(tround(computeRect.getLx()), + tround(computeRect.getLy())); + if ((computeSize.lx > 0) && (computeSize.ly > 0)) + (*port)->dryCompute(computeRect, frame, info); + } } //------------------------------------------------------------------------------------- -void TImageCombinationFx::compatibilityTranslatePort(int major, int minor, std::string &portName) -{ - if (VersionNumber(major, minor) < VersionNumber(1, 20)) { - if (portName == "Up") - portName = "Source1"; - else if (portName == "Down") - portName = "Source2"; - } +void TImageCombinationFx::compatibilityTranslatePort(int major, int minor, + std::string &portName) { + if (VersionNumber(major, minor) < VersionNumber(1, 20)) { + if (portName == "Up") + portName = "Source1"; + else if (portName == "Down") + portName = "Source2"; + } } //****************************************************************************************** // TImageCombinationFx heir classes //****************************************************************************************** -class OverFx : public TImageCombinationFx -{ - - FX_DECLARATION(OverFx) +class OverFx : public TImageCombinationFx { + FX_DECLARATION(OverFx) public: - OverFx() - { - setName(L"OverFx"); - } - - void process(const TRasterP &up, const TRasterP &down, double frame) - { - TRop::over(down, up); - } + OverFx() { setName(L"OverFx"); } + + void process(const TRasterP &up, const TRasterP &down, double frame) { + TRop::over(down, up); + } }; //================================================================== -class AddFx : public TImageCombinationFx -{ - FX_DECLARATION(AddFx) +class AddFx : public TImageCombinationFx { + FX_DECLARATION(AddFx) - TDoubleParamP m_value; + TDoubleParamP m_value; public: - AddFx() : m_value(100.0) - { - bindParam(this, "value", m_value); - } - - void process(const TRasterP &up, const TRasterP &down, double frame) - { - double value = m_value->getValue(frame) / 100.0; - - if (value != 1.0) - TRop::add(up, down, down, value); - else - TRop::add(up, down, down); - } - - TFxPort *getXsheetPort() const - { - return getInputPort(1); - } + AddFx() : m_value(100.0) { bindParam(this, "value", m_value); } + + void process(const TRasterP &up, const TRasterP &down, double frame) { + double value = m_value->getValue(frame) / 100.0; + + if (value != 1.0) + TRop::add(up, down, down, value); + else + TRop::add(up, down, down); + } + + TFxPort *getXsheetPort() const { return getInputPort(1); } }; //================================================================== -class ColorDodgeFx : public TImageCombinationFx -{ - FX_DECLARATION(AddFx) +class ColorDodgeFx : public TImageCombinationFx { + FX_DECLARATION(AddFx) public: - void process(const TRasterP &up, const TRasterP &down, double frame) - { - TRop::colordodge(up, down, down); - } - - TFxPort *getXsheetPort() const - { - return getInputPort(1); - } + void process(const TRasterP &up, const TRasterP &down, double frame) { + TRop::colordodge(up, down, down); + } + + TFxPort *getXsheetPort() const { return getInputPort(1); } }; //================================================================== -class ColorBurnFx : public TImageCombinationFx -{ - FX_DECLARATION(AddFx) +class ColorBurnFx : public TImageCombinationFx { + FX_DECLARATION(AddFx) public: - void process(const TRasterP &up, const TRasterP &down, double frame) - { - TRop::colorburn(up, down, down); - } - - TFxPort *getXsheetPort() const - { - return getInputPort(1); - } + void process(const TRasterP &up, const TRasterP &down, double frame) { + TRop::colorburn(up, down, down); + } + + TFxPort *getXsheetPort() const { return getInputPort(1); } }; //================================================================== -class ScreenFx : public TImageCombinationFx -{ - FX_DECLARATION(AddFx) +class ScreenFx : public TImageCombinationFx { + FX_DECLARATION(AddFx) public: - bool requiresFullRect() { return true; } + bool requiresFullRect() { return true; } - void process(const TRasterP &up, const TRasterP &down, double frame) - { - TRop::screen(up, down, down); - } + void process(const TRasterP &up, const TRasterP &down, double frame) { + TRop::screen(up, down, down); + } - TFxPort *getXsheetPort() const - { - return getInputPort(1); - } + TFxPort *getXsheetPort() const { return getInputPort(1); } }; //================================================================== -class SubFx : public TImageCombinationFx -{ - FX_DECLARATION(SubFx) +class SubFx : public TImageCombinationFx { + FX_DECLARATION(SubFx) - TBoolParamP m_matte; + TBoolParamP m_matte; public: - SubFx() : m_matte(false) - { - bindParam(this, "matte", m_matte); - } - - void process(const TRasterP &up, const TRasterP &down, double frame) - { - TRop::sub(up, down, down, m_matte->getValue()); - } - - TFxPort *getXsheetPort() const - { - return getInputPort(1); - } + SubFx() : m_matte(false) { bindParam(this, "matte", m_matte); } + + void process(const TRasterP &up, const TRasterP &down, double frame) { + TRop::sub(up, down, down, m_matte->getValue()); + } + + TFxPort *getXsheetPort() const { return getInputPort(1); } }; //================================================================== -class MultFx : public TImageCombinationFx -{ - FX_DECLARATION(MultFx) +class MultFx : public TImageCombinationFx { + FX_DECLARATION(MultFx) - TDoubleParamP m_value; - TBoolParamP m_matte; + TDoubleParamP m_value; + TBoolParamP m_matte; public: - MultFx() : m_value(0.0), m_matte(false) - { - bindParam(this, "value", m_value); - bindParam(this, "matte", m_matte); - } - - bool requiresFullRect() { return m_matte->getValue(); } - - void process(const TRasterP &up, const TRasterP &down, double frame) - { - TRop::mult(up, down, down, m_value->getValue(frame), m_matte->getValue()); - } - - TFxPort *getXsheetPort() const - { - return getInputPort(1); - } + MultFx() : m_value(0.0), m_matte(false) { + bindParam(this, "value", m_value); + bindParam(this, "matte", m_matte); + } + + bool requiresFullRect() { return m_matte->getValue(); } + + void process(const TRasterP &up, const TRasterP &down, double frame) { + TRop::mult(up, down, down, m_value->getValue(frame), m_matte->getValue()); + } + + TFxPort *getXsheetPort() const { return getInputPort(1); } }; //================================================================== -class MinFx : public TImageCombinationFx -{ - FX_DECLARATION(MinFx) +class MinFx : public TImageCombinationFx { + FX_DECLARATION(MinFx) - TBoolParamP m_matte; + TBoolParamP m_matte; public: - MinFx() : m_matte(true) - { - bindParam(this, "matte", m_matte); - } - - bool requiresFullRect() { return true; } - - void process(const TRasterP &up, const TRasterP &down, double frame) - { - TRop::ropmin(up, down, down, m_matte->getValue()); - } - - TFxPort *getXsheetPort() const - { - return getInputPort(1); - } + MinFx() : m_matte(true) { bindParam(this, "matte", m_matte); } + + bool requiresFullRect() { return true; } + + void process(const TRasterP &up, const TRasterP &down, double frame) { + TRop::ropmin(up, down, down, m_matte->getValue()); + } + + TFxPort *getXsheetPort() const { return getInputPort(1); } }; //================================================================== -class MaxFx : public TImageCombinationFx -{ - FX_DECLARATION(MaxFx) +class MaxFx : public TImageCombinationFx { + FX_DECLARATION(MaxFx) public: - void process(const TRasterP &up, const TRasterP &down, double frame) - { - TRop::ropmax(up, down, down); - } - - TFxPort *getXsheetPort() const - { - return getInputPort(1); - } + void process(const TRasterP &up, const TRasterP &down, double frame) { + TRop::ropmax(up, down, down); + } + + TFxPort *getXsheetPort() const { return getInputPort(1); } }; //================================================================== -class LinearBurnFx : public TImageCombinationFx -{ - FX_DECLARATION(LinearBurnFx) +class LinearBurnFx : public TImageCombinationFx { + FX_DECLARATION(LinearBurnFx) public: - void process(const TRasterP &up, const TRasterP &down, double frame) - { - TRop::linearburn(up, down, down); - } - - TFxPort *getXsheetPort() const - { - return getInputPort(1); - } + void process(const TRasterP &up, const TRasterP &down, double frame) { + TRop::linearburn(up, down, down); + } + + TFxPort *getXsheetPort() const { return getInputPort(1); } }; //================================================================== -//This Fx is probably unused...! -class OverlayFx : public TImageCombinationFx -{ - FX_DECLARATION(OverlayFx) +// This Fx is probably unused...! +class OverlayFx : public TImageCombinationFx { + FX_DECLARATION(OverlayFx) public: - OverlayFx() {} - ~OverlayFx() {} + OverlayFx() {} + ~OverlayFx() {} - void process(const TRasterP &up, const TRasterP &down, double frame) - { - TRop::overlay(up, down, down); - } + void process(const TRasterP &up, const TRasterP &down, double frame) { + TRop::overlay(up, down, down); + } }; //================================================================== -class BlendFx : public TImageCombinationFx -{ - FX_DECLARATION(BlendFx) +class BlendFx : public TImageCombinationFx { + FX_DECLARATION(BlendFx) - TDoubleParamP m_value; + TDoubleParamP m_value; public: - BlendFx() : m_value(0.0) - { - bindParam(this, "value", m_value); - m_value->setValueRange(0.0, 100.0); - } - - bool requiresFullRect() { return true; } - - void process(const TRasterP &up, const TRasterP &down, double frame) - { - double value = 0.01 * m_value->getValue(frame); - UCHAR matteValue = (UCHAR)(value * 255.0 + 0.5); - - TRop::crossDissolve(up, down, down, matteValue); - } - - TFxPort *getXsheetPort() const - { - return getInputPort(1); - } + BlendFx() : m_value(0.0) { + bindParam(this, "value", m_value); + m_value->setValueRange(0.0, 100.0); + } + + bool requiresFullRect() { return true; } + + void process(const TRasterP &up, const TRasterP &down, double frame) { + double value = 0.01 * m_value->getValue(frame); + UCHAR matteValue = (UCHAR)(value * 255.0 + 0.5); + + TRop::crossDissolve(up, down, down, matteValue); + } + + TFxPort *getXsheetPort() const { return getInputPort(1); } }; //****************************************************************************************** // Matte Fxs definition //****************************************************************************************** -class InFx : public TBaseRasterFx -{ - FX_DECLARATION(InFx) +class InFx : public TBaseRasterFx { + FX_DECLARATION(InFx) - TRasterFxPort m_source, m_matte; + TRasterFxPort m_source, m_matte; public: - InFx() - { - addInputPort("Source", m_source); - addInputPort("Matte", m_matte); - setName(L"InFx"); - } - - ~InFx() {} - - bool doGetBBox(double frame, TRectD &bbox, const TRenderSettings &info) - { - if (m_matte.isConnected() && m_source.isConnected()) { - bool ret = m_matte->doGetBBox(frame, bbox, info); - - if (bbox == TConsts::infiniteRectD) - return m_source->doGetBBox(frame, bbox, info); - else - return ret; - } - bbox = TRectD(); - return false; - } - - bool canHandle(const TRenderSettings &info, double frame) { return true; } - - void doCompute(TTile &tile, double frame, const TRenderSettings &ri) - { - //This fx is not visible if either the source or the matte tiles are empty. - //It's because only source is visible, and only where matte is opaque. - if (!(m_source.isConnected() && m_matte.isConnected())) - return; - - TTile srcTile; - m_source->allocateAndCompute(srcTile, tile.m_pos, tile.getRaster()->getSize(), tile.getRaster(), frame, ri); - - m_matte->compute(tile, frame, ri); - - TRop::ropin(srcTile.getRaster(), tile.getRaster(), tile.getRaster()); - } - - void doDryCompute(TRectD &rect, - double frame, - const TRenderSettings &info) - { - if (!(m_source.isConnected() && m_matte.isConnected())) - return; - - m_source->dryCompute(rect, frame, info); - m_matte->dryCompute(rect, frame, info); - } - - int getMemoryRequirement(const TRectD &rect, double frame, const TRenderSettings &info) - { - return TRasterFx::memorySize(rect, info.m_bpp); - } - - void compute(TFlash &flash, int frame) - { - if (m_matte.isConnected()) { - flash.pushMatrix(); - flash.beginMask(); - ((TRasterFxP)(m_matte.getFx()))->compute(flash, frame); - flash.endMask(); - flash.popMatrix(); - } - - if (m_source.isConnected()) { - flash.pushMatrix(); - flash.enableMask(); - ((TRasterFxP)(m_source.getFx()))->compute(flash, frame); - flash.disableMask(); - flash.popMatrix(); - } - } + InFx() { + addInputPort("Source", m_source); + addInputPort("Matte", m_matte); + setName(L"InFx"); + } + + ~InFx() {} + + bool doGetBBox(double frame, TRectD &bbox, const TRenderSettings &info) { + if (m_matte.isConnected() && m_source.isConnected()) { + bool ret = m_matte->doGetBBox(frame, bbox, info); + + if (bbox == TConsts::infiniteRectD) + return m_source->doGetBBox(frame, bbox, info); + else + return ret; + } + bbox = TRectD(); + return false; + } + + bool canHandle(const TRenderSettings &info, double frame) { return true; } + + void doCompute(TTile &tile, double frame, const TRenderSettings &ri) { + // This fx is not visible if either the source or the matte tiles are empty. + // It's because only source is visible, and only where matte is opaque. + if (!(m_source.isConnected() && m_matte.isConnected())) return; + + TTile srcTile; + m_source->allocateAndCompute(srcTile, tile.m_pos, + tile.getRaster()->getSize(), tile.getRaster(), + frame, ri); + + m_matte->compute(tile, frame, ri); + + TRop::ropin(srcTile.getRaster(), tile.getRaster(), tile.getRaster()); + } + + void doDryCompute(TRectD &rect, double frame, const TRenderSettings &info) { + if (!(m_source.isConnected() && m_matte.isConnected())) return; + + m_source->dryCompute(rect, frame, info); + m_matte->dryCompute(rect, frame, info); + } + + int getMemoryRequirement(const TRectD &rect, double frame, + const TRenderSettings &info) { + return TRasterFx::memorySize(rect, info.m_bpp); + } + + void compute(TFlash &flash, int frame) { + if (m_matte.isConnected()) { + flash.pushMatrix(); + flash.beginMask(); + ((TRasterFxP)(m_matte.getFx()))->compute(flash, frame); + flash.endMask(); + flash.popMatrix(); + } + + if (m_source.isConnected()) { + flash.pushMatrix(); + flash.enableMask(); + ((TRasterFxP)(m_source.getFx()))->compute(flash, frame); + flash.disableMask(); + flash.popMatrix(); + } + } }; //================================================================== -class OutFx : public TBaseRasterFx -{ - FX_DECLARATION(OutFx) +class OutFx : public TBaseRasterFx { + FX_DECLARATION(OutFx) - TRasterFxPort m_source, m_matte; + TRasterFxPort m_source, m_matte; public: - OutFx() - { - addInputPort("Source", m_source); - addInputPort("Matte", m_matte); - setName(L"OutFx"); - } - - ~OutFx() {} - - bool doGetBBox(double frame, TRectD &bbox, const TRenderSettings &info) - { - if (m_source.isConnected()) - return m_source->doGetBBox(frame, bbox, info); - - return false; - } - - bool canHandle(const TRenderSettings &info, double frame) { return true; } - - void doCompute(TTile &tile, double frame, const TRenderSettings &ri) - { - // If there is no source, do nothing - if (!m_source.isConnected()) - return; - - // Here, source is visible where matte is transparent. So if there is - // no matte, just build source. - if (!m_matte.isConnected()) { - m_source->compute(tile, frame, ri); - return; - } - - TTile srcTile; - m_source->allocateAndCompute(srcTile, tile.m_pos, tile.getRaster()->getSize(), tile.getRaster(), frame, ri); - - m_matte->compute(tile, frame, ri); - - TRop::ropout(srcTile.getRaster(), tile.getRaster(), tile.getRaster()); - } - - void doDryCompute(TRectD &rect, - double frame, - const TRenderSettings &info) - { - if (!m_source.isConnected()) - return; - - if (!m_matte.isConnected()) { - m_source->dryCompute(rect, frame, info); - return; - } - - m_source->dryCompute(rect, frame, info); - m_matte->dryCompute(rect, frame, info); - } - - int getMemoryRequirement(const TRectD &rect, double frame, const TRenderSettings &info) - { - return TRasterFx::memorySize(rect, info.m_bpp); - } + OutFx() { + addInputPort("Source", m_source); + addInputPort("Matte", m_matte); + setName(L"OutFx"); + } + + ~OutFx() {} + + bool doGetBBox(double frame, TRectD &bbox, const TRenderSettings &info) { + if (m_source.isConnected()) return m_source->doGetBBox(frame, bbox, info); + + return false; + } + + bool canHandle(const TRenderSettings &info, double frame) { return true; } + + void doCompute(TTile &tile, double frame, const TRenderSettings &ri) { + // If there is no source, do nothing + if (!m_source.isConnected()) return; + + // Here, source is visible where matte is transparent. So if there is + // no matte, just build source. + if (!m_matte.isConnected()) { + m_source->compute(tile, frame, ri); + return; + } + + TTile srcTile; + m_source->allocateAndCompute(srcTile, tile.m_pos, + tile.getRaster()->getSize(), tile.getRaster(), + frame, ri); + + m_matte->compute(tile, frame, ri); + + TRop::ropout(srcTile.getRaster(), tile.getRaster(), tile.getRaster()); + } + + void doDryCompute(TRectD &rect, double frame, const TRenderSettings &info) { + if (!m_source.isConnected()) return; + + if (!m_matte.isConnected()) { + m_source->dryCompute(rect, frame, info); + return; + } + + m_source->dryCompute(rect, frame, info); + m_matte->dryCompute(rect, frame, info); + } + + int getMemoryRequirement(const TRectD &rect, double frame, + const TRenderSettings &info) { + return TRasterFx::memorySize(rect, info.m_bpp); + } }; //================================================================== -class AtopFx : public TBaseRasterFx -{ - FX_DECLARATION(AtopFx) +class AtopFx : public TBaseRasterFx { + FX_DECLARATION(AtopFx) - TRasterFxPort m_up, m_dn; + TRasterFxPort m_up, m_dn; public: - AtopFx() - { - addInputPort("Up", m_up); - addInputPort("Down", m_dn); - } + AtopFx() { + addInputPort("Up", m_up); + addInputPort("Down", m_dn); + } - bool canHandle(const TRenderSettings &info, double frame) { return true; } + bool canHandle(const TRenderSettings &info, double frame) { return true; } - bool doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info) - { - bBox = TRectD(); + bool doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info) { + bBox = TRectD(); - { - TRectD inputBBox; + { + TRectD inputBBox; - bool hasInput = m_up.isConnected() ? m_up->doGetBBox(frame, inputBBox, info) : false; - if (hasInput) - bBox += inputBBox; - } + bool hasInput = + m_up.isConnected() ? m_up->doGetBBox(frame, inputBBox, info) : false; + if (hasInput) bBox += inputBBox; + } - { - TRectD inputBBox; + { + TRectD inputBBox; - bool hasInput = m_dn.isConnected() ? m_dn->doGetBBox(frame, inputBBox, info) : false; - if (hasInput) - bBox += inputBBox; - } + bool hasInput = + m_dn.isConnected() ? m_dn->doGetBBox(frame, inputBBox, info) : false; + if (hasInput) bBox += inputBBox; + } - return (bBox.getLx() >= 0) && (bBox.getLy() >= 0); - } + return (bBox.getLx() >= 0) && (bBox.getLy() >= 0); + } - void doCompute(TTile &tile, double frame, const TRenderSettings &ri) - { - // Here it's just like matte in, but the matte is visible under up. + void doCompute(TTile &tile, double frame, const TRenderSettings &ri) { + // Here it's just like matte in, but the matte is visible under up. - if (!m_dn.isConnected()) - return; + if (!m_dn.isConnected()) return; - if (!m_up.isConnected()) { - m_dn->compute(tile, frame, ri); - return; - } + if (!m_up.isConnected()) { + m_dn->compute(tile, frame, ri); + return; + } - TTile upTile; - m_up->allocateAndCompute(upTile, tile.m_pos, tile.getRaster()->getSize(), tile.getRaster(), frame, ri); + TTile upTile; + m_up->allocateAndCompute(upTile, tile.m_pos, tile.getRaster()->getSize(), + tile.getRaster(), frame, ri); - m_dn->compute(tile, frame, ri); + m_dn->compute(tile, frame, ri); - TRop::atop(upTile.getRaster(), tile.getRaster(), tile.getRaster()); - } + TRop::atop(upTile.getRaster(), tile.getRaster(), tile.getRaster()); + } - void doDryCompute(TRectD &rect, - double frame, - const TRenderSettings &info) - { - if (!m_dn.isConnected()) - return; + void doDryCompute(TRectD &rect, double frame, const TRenderSettings &info) { + if (!m_dn.isConnected()) return; - if (!m_up.isConnected()) { - m_dn->dryCompute(rect, frame, info); - return; - } + if (!m_up.isConnected()) { + m_dn->dryCompute(rect, frame, info); + return; + } - m_up->dryCompute(rect, frame, info); - m_dn->dryCompute(rect, frame, info); - } + m_up->dryCompute(rect, frame, info); + m_dn->dryCompute(rect, frame, info); + } - int getMemoryRequirement(const TRectD &rect, double frame, const TRenderSettings &info) - { - return TRasterFx::memorySize(rect, info.m_bpp); - } + int getMemoryRequirement(const TRectD &rect, double frame, + const TRenderSettings &info) { + return TRasterFx::memorySize(rect, info.m_bpp); + } }; //================================================================== @@ -763,7 +675,7 @@ FX_IDENTIFIER(MultFx, "multFx") FX_IDENTIFIER(InFx, "inFx") FX_IDENTIFIER(OutFx, "outFx") FX_IDENTIFIER(AtopFx, "atopFx") -//FX_IDENTIFIER(XorFx, "xorFx") +// FX_IDENTIFIER(XorFx, "xorFx") FX_IDENTIFIER(MinFx, "minFx") FX_IDENTIFIER(MaxFx, "maxFx") FX_IDENTIFIER(LinearBurnFx, "linearBurnFx") diff --git a/toonz/sources/common/tfx/tcacheresource.cpp b/toonz/sources/common/tfx/tcacheresource.cpp index 1996bcf..653f239 100644 --- a/toonz/sources/common/tfx/tcacheresource.cpp +++ b/toonz/sources/common/tfx/tcacheresource.cpp @@ -1,28 +1,28 @@ -//String includes +// String includes #include "tconvert.h" -//Image includes +// Image includes #include "timage_io.h" -//Toonz Image cache +// Toonz Image cache #include "timagecache.h" -//TTile class +// TTile class #include "ttile.h" -//Trop include +// Trop include #include "trop.h" -//File I/O includes +// File I/O includes //#include "tstream.h" -//Qt classes +// Qt classes #include #include -//Resources pool manager +// Resources pool manager #include "tcacheresourcepool.h" #include "tcacheresource.h" @@ -41,13 +41,15 @@ namespace QString traduce(const TRectD& rect) { return "[" + QString::number(rect.x0) + " " + QString::number(rect.y0) + " " - + QString::number(rect.x1) + " " + QString::number(rect.y1) + "]"; + + QString::number(rect.x1) + " " + QString::number(rect.y1) + +"]"; } QString traduce(const TRect& rect) { return "[" + QString::number(rect.x0) + " " + QString::number(rect.y0) + " " - + QString::number(rect.x1+1) + " " + QString::number(rect.y1+1) + "]"; + + QString::number(rect.x1+1) + " " + QString::number(rect.y1+1) + +"]"; } QString traduce(const TTile& tile) @@ -63,23 +65,30 @@ namespace /* The TCacheResource class models the idea of sparsely defined tile objects. -Whereas common TTile instances can be used to represent images bounded on a specific +Whereas common TTile instances can be used to represent images bounded on a +specific rect of the plane, this model does not suit well in case the image object is sparse across the image plane. \n \n -The TCacheResource internal representation assumes that the image plane is split -in a fixed-length integer lattice, each cell of which may host an image object in +The TCacheResource internal representation assumes that the image plane is +split +in a fixed-length integer lattice, each cell of which may host an image object +in case some part of the complex inside the cell has been defined. The plane outside the complex is assumed to be transparent. \n The lattice origin must be specified in the complex's contructor, and all tiles -uploaded into and downloaded from it must have an integer displacement with respect -to it - in other words, it is required that the complex has a well-defined pixel geometry. +uploaded into and downloaded from it must have an integer displacement with +respect +to it - in other words, it is required that the complex has a well-defined pixel +geometry. \n \n -Specific regions of the complex can be cleared through the apposite clear() method. +Specific regions of the complex can be cleared through the apposite clear() +method. \warning -This class does not ensure thread-safety. Concurrent accesses must be dealt by users. +This class does not ensure thread-safety. Concurrent accesses must be dealt by +users. */ //==================================================================================================== @@ -95,7 +104,8 @@ the complex's origin. /*! \fn int TCacheResource::getRasterType() const Returns the type of raster currently present in the tile complex. Only images -providing a raster representation coherent with the complex's one may be exchanged +providing a raster representation coherent with the complex's one may be +exchanged with it. */ @@ -110,114 +120,112 @@ clear(getAvailableRegion()), supplied for convience. // Preliminaries //**************************************************************************************************** -namespace -{ -//Store tile textures of 512 x 512 pixels. Their memory usage ranges around 1-2 MB each. +namespace { +// Store tile textures of 512 x 512 pixels. Their memory usage ranges around 1-2 +// MB each. const int latticeStep = 512; static unsigned long cacheId = 0; //----------------------------------------------------------------- -inline int getRasterType(const TRasterP &ras) -{ - if ((TRaster32P)ras) - return TCacheResource::RGBM32; - else if ((TRaster64P)ras) - return TCacheResource::RGBM64; - else if ((TRasterCM32P)ras) - return TCacheResource::CM32; +inline int getRasterType(const TRasterP &ras) { + if ((TRaster32P)ras) + return TCacheResource::RGBM32; + else if ((TRaster64P)ras) + return TCacheResource::RGBM64; + else if ((TRasterCM32P)ras) + return TCacheResource::CM32; - return TCacheResource::NONE; + return TCacheResource::NONE; } //----------------------------------------------------------------- -inline TRasterP getRaster(const TImageP &img) -{ - TRasterImageP rimg(img); - if (rimg) - return rimg->getRaster(); - TToonzImageP timg(img); - if (timg) - return timg->getRaster(); +inline TRasterP getRaster(const TImageP &img) { + TRasterImageP rimg(img); + if (rimg) return rimg->getRaster(); + TToonzImageP timg(img); + if (timg) return timg->getRaster(); - assert(!"Wrong image type!"); - return 0; + assert(!"Wrong image type!"); + return 0; } //----------------------------------------------------------------- -inline bool isEmpty(const TRect &rect) { return rect.x0 > rect.x1 || rect.y0 > rect.y1; } +inline bool isEmpty(const TRect &rect) { + return rect.x0 > rect.x1 || rect.y0 > rect.y1; +} //----------------------------------------------------------------- -inline QRect toQRect(const TRect &r) { return QRect(r.x0, r.y0, r.getLx(), r.getLy()); } -inline TRect toTRect(const QRect &r) { return TRect(r.left(), r.top(), r.right(), r.bottom()); } +inline QRect toQRect(const TRect &r) { + return QRect(r.x0, r.y0, r.getLx(), r.getLy()); +} +inline TRect toTRect(const QRect &r) { + return TRect(r.left(), r.top(), r.right(), r.bottom()); +} inline QPoint toQPoint(const TPoint &p) { return QPoint(p.x, p.y); } //---------------------------------------------------------------------------- -inline TRect getTileRect(const TTile &tile) -{ - return TRect( - TPoint(tfloor(tile.m_pos.x), tfloor(tile.m_pos.y)), - tile.getRaster()->getSize()); +inline TRect getTileRect(const TTile &tile) { + return TRect(TPoint(tfloor(tile.m_pos.x), tfloor(tile.m_pos.y)), + tile.getRaster()->getSize()); } //---------------------------------------------------------------------------- -//Qt's contains actually returns QRegion::intersected... I wonder why... -inline bool contains(const QRegion ®ion, const TRect &rect) -{ - return QRegion(toQRect(rect)).subtracted(region).isEmpty(); +// Qt's contains actually returns QRegion::intersected... I wonder why... +inline bool contains(const QRegion ®ion, const TRect &rect) { + return QRegion(toQRect(rect)).subtracted(region).isEmpty(); } //---------------------------------------------------------------------------- -inline void saveCompressed(const TFilePath &fp, const TRasterP &ras) -{ - assert(ras->getLx() == latticeStep && ras->getLy() == latticeStep); - unsigned int size = sq(latticeStep) * ras->getPixelSize(); +inline void saveCompressed(const TFilePath &fp, const TRasterP &ras) { + assert(ras->getLx() == latticeStep && ras->getLy() == latticeStep); + unsigned int size = sq(latticeStep) * ras->getPixelSize(); - ras->lock(); - QByteArray data = qCompress((const char *)ras->getRawData(), size); - ras->unlock(); + ras->lock(); + QByteArray data = qCompress((const char *)ras->getRawData(), size); + ras->unlock(); - Tofstream oss(fp); - oss.write((const char *)&size, sizeof(unsigned int)); - oss.write(data.constData(), data.size()); - assert(!oss.fail()); + Tofstream oss(fp); + oss.write((const char *)&size, sizeof(unsigned int)); + oss.write(data.constData(), data.size()); + assert(!oss.fail()); } //---------------------------------------------------------------------------- -inline void loadCompressed(const TFilePath &fp, TRasterP &ras, TCacheResource::Type rasType) -{ - Tifstream is(fp); +inline void loadCompressed(const TFilePath &fp, TRasterP &ras, + TCacheResource::Type rasType) { + Tifstream is(fp); - if (rasType == TCacheResource::CM32) - ras = TRasterCM32P(latticeStep, latticeStep); - else if (rasType == TCacheResource::RGBM32) - ras = TRaster32P(latticeStep, latticeStep); - else if (rasType == TCacheResource::RGBM64) - ras = TRaster64P(latticeStep, latticeStep); - else - assert(false); + if (rasType == TCacheResource::CM32) + ras = TRasterCM32P(latticeStep, latticeStep); + else if (rasType == TCacheResource::RGBM32) + ras = TRaster32P(latticeStep, latticeStep); + else if (rasType == TCacheResource::RGBM64) + ras = TRaster64P(latticeStep, latticeStep); + else + assert(false); - ras->lock(); + ras->lock(); - char *rawData = (char *)ras->getRawData(); - unsigned int dataSize; - is.read((char *)&dataSize, sizeof(unsigned int)); - is.read(rawData, dataSize); + char *rawData = (char *)ras->getRawData(); + unsigned int dataSize; + is.read((char *)&dataSize, sizeof(unsigned int)); + is.read(rawData, dataSize); - //Observe that QByteArray::fromRawData does NOT cause a deep copy to occur. - QByteArray data(QByteArray::fromRawData(rawData, dataSize)); - data = qUncompress(data); - memcpy(rawData, data.constData(), data.size()); + // Observe that QByteArray::fromRawData does NOT cause a deep copy to occur. + QByteArray data(QByteArray::fromRawData(rawData, dataSize)); + data = qUncompress(data); + memcpy(rawData, data.constData(), data.size()); - ras->unlock(); + ras->unlock(); } } @@ -225,21 +233,20 @@ inline void loadCompressed(const TFilePath &fp, TRasterP &ras, TCacheResource::T // TCacheResourceP implementation //**************************************************************************************************** -TCacheResourceP::TCacheResourceP(const std::string &imageName, bool createIfNone) - : m_pointer(TCacheResourcePool::instance()->getResource(imageName, createIfNone)) -{ - if (m_pointer) - m_pointer->addRef(); +TCacheResourceP::TCacheResourceP(const std::string &imageName, + bool createIfNone) + : m_pointer(TCacheResourcePool::instance()->getResource(imageName, + createIfNone)) { + if (m_pointer) m_pointer->addRef(); } //---------------------------------------------------------------------------- -TCacheResourceP::~TCacheResourceP() -{ - if (m_pointer) { - m_pointer->release(); - m_pointer = 0; - } +TCacheResourceP::~TCacheResourceP() { + if (m_pointer) { + m_pointer->release(); + m_pointer = 0; + } } //**************************************************************************************************** @@ -251,204 +258,187 @@ TCacheResourceP::~TCacheResourceP() //--------------------- TCacheResource::TCacheResource() - : m_id(cacheId++), m_tileType(NONE), m_cellsCount(0), m_locksCount(0), m_backEnabled(false), m_invalidated(false) -{ -} + : m_id(cacheId++) + , m_tileType(NONE) + , m_cellsCount(0) + , m_locksCount(0) + , m_backEnabled(false) + , m_invalidated(false) {} //----------------------------------------------------------------- -TCacheResource::~TCacheResource() -{ - clear(); -} +TCacheResource::~TCacheResource() { clear(); } //----------------------------------------------------------------- -void TCacheResource::release() -{ - if ((--m_refCount) <= 0) { - //Attempt release from the resource pool - TCacheResourcePool::instance()->releaseResource(this); - } +void TCacheResource::release() { + if ((--m_refCount) <= 0) { + // Attempt release from the resource pool + TCacheResourcePool::instance()->releaseResource(this); + } } //----------------------------------------------------------------- -inline TCacheResource::PointLess TCacheResource::getCellIndex(const TPoint &pos) const -{ - return PointLess( - tfloor(pos.x / (double)latticeStep), - tfloor(pos.y / (double)latticeStep)); +inline TCacheResource::PointLess TCacheResource::getCellIndex( + const TPoint &pos) const { + return PointLess(tfloor(pos.x / (double)latticeStep), + tfloor(pos.y / (double)latticeStep)); } //----------------------------------------------------------------- -inline TPoint TCacheResource::getCellPos(const PointLess &cellIndex) const -{ - return TPoint(cellIndex.x * latticeStep, cellIndex.y * latticeStep); +inline TPoint TCacheResource::getCellPos(const PointLess &cellIndex) const { + return TPoint(cellIndex.x * latticeStep, cellIndex.y * latticeStep); } //----------------------------------------------------------------- -//Returns the lattice cell containing the position pos. -inline TPoint TCacheResource::getCellPos(const TPoint &pos) const -{ - TPoint cellIndex( - tfloor(pos.x / (double)latticeStep), - tfloor(pos.y / (double)latticeStep)); - return TPoint(cellIndex.x * latticeStep, cellIndex.y * latticeStep); +// Returns the lattice cell containing the position pos. +inline TPoint TCacheResource::getCellPos(const TPoint &pos) const { + TPoint cellIndex(tfloor(pos.x / (double)latticeStep), + tfloor(pos.y / (double)latticeStep)); + return TPoint(cellIndex.x * latticeStep, cellIndex.y * latticeStep); } //----------------------------------------------------------------- -//Returns the lattice cell containing the relative position pos. -inline TPoint TCacheResource::getCellPos(const TPointD &pos) const -{ - TPoint cellIndex( - tfloor(pos.x / (double)latticeStep), - tfloor(pos.y / (double)latticeStep)); - return TPoint(cellIndex.x * latticeStep, cellIndex.y * latticeStep); +// Returns the lattice cell containing the relative position pos. +inline TPoint TCacheResource::getCellPos(const TPointD &pos) const { + TPoint cellIndex(tfloor(pos.x / (double)latticeStep), + tfloor(pos.y / (double)latticeStep)); + return TPoint(cellIndex.x * latticeStep, cellIndex.y * latticeStep); } //**************************************************************************************************** // Tough stuff //**************************************************************************************************** -bool TCacheResource::checkRasterType(const TRasterP &ras, int &rasType) const -{ - rasType = ::getRasterType(ras); - if (rasType == NONE) { - assert(!"The passed raster has unkown type!"); - return false; - } - if (m_tileType != NONE && m_tileType != rasType) { - assert(!"The passed raster has not the same type of the cache resource!"); - return false; - } +bool TCacheResource::checkRasterType(const TRasterP &ras, int &rasType) const { + rasType = ::getRasterType(ras); + if (rasType == NONE) { + assert(!"The passed raster has unkown type!"); + return false; + } + if (m_tileType != NONE && m_tileType != rasType) { + assert(!"The passed raster has not the same type of the cache resource!"); + return false; + } - return true; + return true; } //---------------------------------------------------------------- -TRasterP TCacheResource::buildCompatibleRaster(const TDimension &size) -{ - TRasterP result; - if (m_tileType == RGBM32) - result = TRaster32P(size); - else if (m_tileType == RGBM64) - result = TRaster64P(size); - else if (m_tileType == CM32) - result = TRasterCM32P(size); +TRasterP TCacheResource::buildCompatibleRaster(const TDimension &size) { + TRasterP result; + if (m_tileType == RGBM32) + result = TRaster32P(size); + else if (m_tileType == RGBM64) + result = TRaster64P(size); + else if (m_tileType == CM32) + result = TRasterCM32P(size); - return result; + return result; } //---------------------------------------------------------------- -bool TCacheResource::checkTile(const TTile &tile) const -{ - //Ensure that tile has integer geoometry. - TPointD tileFracPos(tile.m_pos.x - tfloor(tile.m_pos.x), tile.m_pos.y - tfloor(tile.m_pos.y)); - if (tileFracPos.x != 0.0 || tileFracPos.y != 0.0) { - assert(!"The passed tile must have integer geometry!"); - return false; - } +bool TCacheResource::checkTile(const TTile &tile) const { + // Ensure that tile has integer geoometry. + TPointD tileFracPos(tile.m_pos.x - tfloor(tile.m_pos.x), + tile.m_pos.y - tfloor(tile.m_pos.y)); + if (tileFracPos.x != 0.0 || tileFracPos.y != 0.0) { + assert(!"The passed tile must have integer geometry!"); + return false; + } - return true; + return true; } //---------------------------------------------------------------- -inline std::string TCacheResource::getCellName(int idxX, int idxY) const -{ - return "cell" + std::to_string(idxX) + "," + std::to_string(idxY); +inline std::string TCacheResource::getCellName(int idxX, int idxY) const { + return "cell" + std::to_string(idxX) + "," + std::to_string(idxY); } //---------------------------------------------------------------- -inline std::string TCacheResource::getCellCacheId(int idxX, int idxY) const -{ - return "TCacheResource" + std::to_string(m_id) + getCellName(idxX, idxY); +inline std::string TCacheResource::getCellCacheId(int idxX, int idxY) const { + return "TCacheResource" + std::to_string(m_id) + getCellName(idxX, idxY); } //---------------------------------------------------------------- -inline std::string TCacheResource::getCellCacheId(const TPoint &cellPos) const -{ - return getCellCacheId(tfloor(cellPos.x / (double)latticeStep), - tfloor(cellPos.y / (double)latticeStep)); +inline std::string TCacheResource::getCellCacheId(const TPoint &cellPos) const { + return getCellCacheId(tfloor(cellPos.x / (double)latticeStep), + tfloor(cellPos.y / (double)latticeStep)); } //----------------------------------------------------------------- -inline TRasterP TCacheResource::createCellRaster(int rasterType, const std::string &cacheId) -{ - TRasterP result; +inline TRasterP TCacheResource::createCellRaster(int rasterType, + const std::string &cacheId) { + TRasterP result; - if (rasterType == TCacheResource::NONE) { - assert(!"Unknown raster type!"); - return result; - } + if (rasterType == TCacheResource::NONE) { + assert(!"Unknown raster type!"); + return result; + } - TImageP img; - if (rasterType == TCacheResource::RGBM32) { - result = TRaster32P(latticeStep, latticeStep); - img = TRasterImageP(result); - } else if (rasterType == TCacheResource::RGBM64) { - result = TRaster64P(latticeStep, latticeStep); - img = TRasterImageP(result); - } else if (rasterType == TCacheResource::CM32) { - result = TRasterCM32P(latticeStep, latticeStep); - img = TToonzImageP(result, result->getBounds()); - } + TImageP img; + if (rasterType == TCacheResource::RGBM32) { + result = TRaster32P(latticeStep, latticeStep); + img = TRasterImageP(result); + } else if (rasterType == TCacheResource::RGBM64) { + result = TRaster64P(latticeStep, latticeStep); + img = TRasterImageP(result); + } else if (rasterType == TCacheResource::CM32) { + result = TRasterCM32P(latticeStep, latticeStep); + img = TToonzImageP(result, result->getBounds()); + } - TImageCache::instance()->add(cacheId, img); - ++m_cellsCount; + TImageCache::instance()->add(cacheId, img); + ++m_cellsCount; - //DIAGNOSTICS_GLOADD("crCellsCnt", 1); + // DIAGNOSTICS_GLOADD("crCellsCnt", 1); - return result; + return result; } //---------------------------------------------------------------- -bool TCacheResource::canDownloadSome(const TRect &rect) const -{ - return m_region.intersects(toQRect(rect)); +bool TCacheResource::canDownloadSome(const TRect &rect) const { + return m_region.intersects(toQRect(rect)); } //---------------------------------------------------------------- -bool TCacheResource::canDownloadAll(const TRect &rect) const -{ - return contains(m_region, rect); +bool TCacheResource::canDownloadAll(const TRect &rect) const { + return contains(m_region, rect); } //---------------------------------------------------------------- -bool TCacheResource::canUpload(const TTile &tile) const -{ - int tileType; - return checkTile(tile) && checkRasterType(tile.getRaster(), tileType); +bool TCacheResource::canUpload(const TTile &tile) const { + int tileType; + return checkTile(tile) && checkRasterType(tile.getRaster(), tileType); } //---------------------------------------------------------------- //! Returns true if the passed tile is compatible with the complex, and some //! part of it is downloadable. -bool TCacheResource::canDownloadSome(const TTile &tile) const -{ - return checkTile(tile) && m_region.intersects(toQRect(getTileRect(tile))); +bool TCacheResource::canDownloadSome(const TTile &tile) const { + return checkTile(tile) && m_region.intersects(toQRect(getTileRect(tile))); } //---------------------------------------------------------------- //! Returns true if the passed tile is compatible, and it can be downloaded //! entirely. -bool TCacheResource::canDownloadAll(const TTile &tile) const -{ - return checkTile(tile) && contains(m_region, getTileRect(tile)); +bool TCacheResource::canDownloadAll(const TTile &tile) const { + return checkTile(tile) && contains(m_region, getTileRect(tile)); } //---------------------------------------------------------------- @@ -456,61 +446,61 @@ bool TCacheResource::canDownloadAll(const TTile &tile) const //! Copies the passed tile in the tile complex. The passed tile \b must //! possess integer geometry (ie tile.m_pos must have integer coordinates), //! otherwise this function is a no-op. -bool TCacheResource::upload(const TPoint &pos, TRasterP ras) -{ - int tileType; - if (!checkRasterType(ras, tileType)) - return false; +bool TCacheResource::upload(const TPoint &pos, TRasterP ras) { + int tileType; + if (!checkRasterType(ras, tileType)) return false; - if (m_tileType == NONE) - m_tileType = tileType; + if (m_tileType == NONE) m_tileType = tileType; - //For all cells of the lattice which intersect the tile, upload the content in the - //complex - TRect tileRect(ras->getBounds() + pos); - TPoint initialPos(getCellPos(tileRect.getP00())); + // For all cells of the lattice which intersect the tile, upload the content + // in the + // complex + TRect tileRect(ras->getBounds() + pos); + TPoint initialPos(getCellPos(tileRect.getP00())); - //DIAGNOSTICS_NUMBEREDSTRSET(prefix + QString::number((UINT) this) + " | Stack | ", - //"crStack", "upload", ::traduce(TRect(pos, ras->getSize()))); + // DIAGNOSTICS_NUMBEREDSTRSET(prefix + QString::number((UINT) this) + " | + // Stack | ", + //"crStack", "upload", ::traduce(TRect(pos, ras->getSize()))); - TPoint currPos; - for (currPos.x = initialPos.x; currPos.x <= tileRect.x1; currPos.x += latticeStep) - for (currPos.y = initialPos.y; currPos.y <= tileRect.y1; currPos.y += latticeStep) { - //Copy tile's content into the cell's raster. - TRect cellRect(currPos, TDimension(latticeStep, latticeStep)); + TPoint currPos; + for (currPos.x = initialPos.x; currPos.x <= tileRect.x1; + currPos.x += latticeStep) + for (currPos.y = initialPos.y; currPos.y <= tileRect.y1; + currPos.y += latticeStep) { + // Copy tile's content into the cell's raster. + TRect cellRect(currPos, TDimension(latticeStep, latticeStep)); - TRect overlapRect(tileRect * cellRect); - assert(!overlapRect.isEmpty()); + TRect overlapRect(tileRect * cellRect); + assert(!overlapRect.isEmpty()); - PointLess cellIndex(getCellIndex(currPos)); - std::pair cellInfos(touch(cellIndex)); - TRasterP cellRas(cellInfos.first); + PointLess cellIndex(getCellIndex(currPos)); + std::pair cellInfos(touch(cellIndex)); + TRasterP cellRas(cellInfos.first); - TRect temp(overlapRect - currPos); - TRasterP overlappingCellRas(cellRas->extract(temp)); - temp = TRect(overlapRect - tileRect.getP00()); - TRasterP overlappingTileRas(ras->extract(temp)); + TRect temp(overlapRect - currPos); + TRasterP overlappingCellRas(cellRas->extract(temp)); + temp = TRect(overlapRect - tileRect.getP00()); + TRasterP overlappingTileRas(ras->extract(temp)); - assert(overlappingCellRas->getBounds() == overlappingTileRas->getBounds()); - TRop::copy(overlappingCellRas, overlappingTileRas); + assert(overlappingCellRas->getBounds() == + overlappingTileRas->getBounds()); + TRop::copy(overlappingCellRas, overlappingTileRas); - cellInfos.second->m_modified = true; - } + cellInfos.second->m_modified = true; + } - //Update the complex's content region - m_region += toQRect(tileRect); + // Update the complex's content region + m_region += toQRect(tileRect); - return true; + return true; } //---------------------------------------------------------------- -bool TCacheResource::upload(const TTile &tile) -{ - if (!checkTile(tile)) - return false; +bool TCacheResource::upload(const TTile &tile) { + if (!checkTile(tile)) return false; - return upload(TPoint(tile.m_pos.x, tile.m_pos.y), tile.getRaster()); + return upload(TPoint(tile.m_pos.x, tile.m_pos.y), tile.getRaster()); } //---------------------------------------------------------------- @@ -518,477 +508,456 @@ bool TCacheResource::upload(const TTile &tile) //! Fills the passed tile with the data contained in the complex, returning //! the copied region. //! The same restriction of the upload() method applies here. -QRegion TCacheResource::download(const TPoint &pos, TRasterP ras) -{ - int tileType; - if (!checkRasterType(ras, tileType)) - return QRegion(); +QRegion TCacheResource::download(const TPoint &pos, TRasterP ras) { + int tileType; + if (!checkRasterType(ras, tileType)) return QRegion(); - //Build the tile's rect - TRect tileRect(ras->getBounds() + pos); + // Build the tile's rect + TRect tileRect(ras->getBounds() + pos); - if (!m_region.intersects(toQRect(tileRect))) - return QRegion(); + if (!m_region.intersects(toQRect(tileRect))) return QRegion(); - //For all cells intersecting the tile's rect, copy all those intersecting the - //complex's content region. - TPoint initialPos(getCellPos(tileRect.getP00())); + // For all cells intersecting the tile's rect, copy all those intersecting the + // complex's content region. + TPoint initialPos(getCellPos(tileRect.getP00())); - TPoint currPos; - for (currPos.x = initialPos.x; currPos.x <= tileRect.x1; currPos.x += latticeStep) - for (currPos.y = initialPos.y; currPos.y <= tileRect.y1; currPos.y += latticeStep) { - TRect cellRect(currPos, TDimension(latticeStep, latticeStep)); + TPoint currPos; + for (currPos.x = initialPos.x; currPos.x <= tileRect.x1; + currPos.x += latticeStep) + for (currPos.y = initialPos.y; currPos.y <= tileRect.y1; + currPos.y += latticeStep) { + TRect cellRect(currPos, TDimension(latticeStep, latticeStep)); - TRect overlapRect(tileRect * cellRect); - assert(!overlapRect.isEmpty()); - QRect overlapQRect(toQRect(overlapRect)); + TRect overlapRect(tileRect * cellRect); + assert(!overlapRect.isEmpty()); + QRect overlapQRect(toQRect(overlapRect)); - if (m_region.intersects(overlapQRect)) { - //Extract the associated rasters and perform the copy to the input tile. - std::pair cellInfos(touch(getCellIndex(currPos))); - TRasterP cellRas(cellInfos.first); + if (m_region.intersects(overlapQRect)) { + // Extract the associated rasters and perform the copy to the input + // tile. + std::pair cellInfos(touch(getCellIndex(currPos))); + TRasterP cellRas(cellInfos.first); - TRect temp(overlapRect - currPos); - TRasterP overlappingCellRas(cellRas->extract(temp)); - temp = TRect(overlapRect - tileRect.getP00()); - TRasterP overlappingTileRas(ras->extract(temp)); + TRect temp(overlapRect - currPos); + TRasterP overlappingCellRas(cellRas->extract(temp)); + temp = TRect(overlapRect - tileRect.getP00()); + TRasterP overlappingTileRas(ras->extract(temp)); - TRop::copy(overlappingTileRas, overlappingCellRas); - } - } + TRop::copy(overlappingTileRas, overlappingCellRas); + } + } - return m_region.intersected(QRegion(toQRect(tileRect))); + return m_region.intersected(QRegion(toQRect(tileRect))); } //---------------------------------------------------------------- -QRegion TCacheResource::download(TTile &tile) -{ - if (!checkTile(tile)) - return QRegion(); +QRegion TCacheResource::download(TTile &tile) { + if (!checkTile(tile)) return QRegion(); - return download(TPoint(tile.m_pos.x, tile.m_pos.y), tile.getRaster()); + return download(TPoint(tile.m_pos.x, tile.m_pos.y), tile.getRaster()); } //---------------------------------------------------------------- -bool TCacheResource::downloadAll(const TPoint &pos, TRasterP ras) -{ - int tileType; - if (!checkRasterType(ras, tileType)) - return false; +bool TCacheResource::downloadAll(const TPoint &pos, TRasterP ras) { + int tileType; + if (!checkRasterType(ras, tileType)) return false; - //Build the tile's rect - TRect tileRect(ras->getBounds() + pos); + // Build the tile's rect + TRect tileRect(ras->getBounds() + pos); - if (!contains(m_region, tileRect)) - return false; + if (!contains(m_region, tileRect)) return false; - //DIAGNOSTICS_NUMBEREDSTRSET(prefix + QString::number((UINT) this) + " | Stack | ", - //"crStack", "downloadAll", ::traduce(TRect(pos, ras->getSize()))); + // DIAGNOSTICS_NUMBEREDSTRSET(prefix + QString::number((UINT) this) + " | + // Stack | ", + //"crStack", "downloadAll", ::traduce(TRect(pos, ras->getSize()))); - //For all cells intersecting the tile's rect, copy all those intersecting the - //complex's content region. - TPoint initialPos(getCellPos(tileRect.getP00())); + // For all cells intersecting the tile's rect, copy all those intersecting the + // complex's content region. + TPoint initialPos(getCellPos(tileRect.getP00())); - TPoint currPos; - for (currPos.x = initialPos.x; currPos.x <= tileRect.x1; currPos.x += latticeStep) - for (currPos.y = initialPos.y; currPos.y <= tileRect.y1; currPos.y += latticeStep) { - TRect cellRect(currPos, TDimension(latticeStep, latticeStep)); + TPoint currPos; + for (currPos.x = initialPos.x; currPos.x <= tileRect.x1; + currPos.x += latticeStep) + for (currPos.y = initialPos.y; currPos.y <= tileRect.y1; + currPos.y += latticeStep) { + TRect cellRect(currPos, TDimension(latticeStep, latticeStep)); - TRect overlapRect(tileRect * cellRect); - assert(!overlapRect.isEmpty()); - QRect overlapQRect(toQRect(overlapRect)); + TRect overlapRect(tileRect * cellRect); + assert(!overlapRect.isEmpty()); + QRect overlapQRect(toQRect(overlapRect)); - if (m_region.intersects(overlapQRect)) { - //Extract the associated rasters and perform the copy to the input tile. - std::pair cellInfos(touch(getCellIndex(currPos))); - TRasterP cellRas(cellInfos.first); + if (m_region.intersects(overlapQRect)) { + // Extract the associated rasters and perform the copy to the input + // tile. + std::pair cellInfos(touch(getCellIndex(currPos))); + TRasterP cellRas(cellInfos.first); - TRect temp(overlapRect - currPos); - TRasterP overlappingCellRas(cellRas->extract(temp)); - temp = TRect(overlapRect - tileRect.getP00()); - TRasterP overlappingTileRas(ras->extract(temp)); + TRect temp(overlapRect - currPos); + TRasterP overlappingCellRas(cellRas->extract(temp)); + temp = TRect(overlapRect - tileRect.getP00()); + TRasterP overlappingTileRas(ras->extract(temp)); - TRop::copy(overlappingTileRas, overlappingCellRas); - } - } + TRop::copy(overlappingTileRas, overlappingCellRas); + } + } - return true; + return true; } //---------------------------------------------------------------- -bool TCacheResource::downloadAll(TTile &tile) -{ - if (!checkTile(tile)) - return false; +bool TCacheResource::downloadAll(TTile &tile) { + if (!checkTile(tile)) return false; - return downloadAll(TPoint(tile.m_pos.x, tile.m_pos.y), tile.getRaster()); + return downloadAll(TPoint(tile.m_pos.x, tile.m_pos.y), tile.getRaster()); } //----------------------------------------------------------------- -//! Clears the complex on the specified region. Please observe that the actually cleared region -//! consists of all lattice cells intersecting the passed region, therefore resulting in a cleared region +//! Clears the complex on the specified region. Please observe that the actually +//! cleared region +//! consists of all lattice cells intersecting the passed region, therefore +//! resulting in a cleared region //! typically larger than passed one, up to the lattice granularity. -void TCacheResource::clear(QRegion region) -{ - if (!m_region.intersects(region)) - return; - - //Get the region bbox - TRect bbox(toTRect(region.boundingRect())); - - //For all cells intersecting the bbox - TPoint initialPos(getCellPos(bbox.getP00())); - TPoint pos; - for (pos.x = initialPos.x; pos.x <= bbox.x1; pos.x += latticeStep) - for (pos.y = initialPos.y; pos.y <= bbox.y1; pos.y += latticeStep) { - QRect cellQRect(toQRect(TRect(pos, TDimension(latticeStep, latticeStep)))); - - if (region.intersects(cellQRect) && m_region.intersects(cellQRect)) { - //Release the associated cell from cache and clear the cell from the content region. - TImageCache::instance()->remove(getCellCacheId(pos)); - m_region -= cellQRect; - - --m_cellsCount; - - //DIAGNOSTICS_GLOADD("crCellsCnt", -1); - - //Release the cell from m_cellDatas - m_cellDatas[getCellIndex(pos)].m_modified = true; - } - } - - if (m_region.isEmpty()) { - m_tileType = NONE; - m_locksCount = 0; - } +void TCacheResource::clear(QRegion region) { + if (!m_region.intersects(region)) return; + + // Get the region bbox + TRect bbox(toTRect(region.boundingRect())); + + // For all cells intersecting the bbox + TPoint initialPos(getCellPos(bbox.getP00())); + TPoint pos; + for (pos.x = initialPos.x; pos.x <= bbox.x1; pos.x += latticeStep) + for (pos.y = initialPos.y; pos.y <= bbox.y1; pos.y += latticeStep) { + QRect cellQRect( + toQRect(TRect(pos, TDimension(latticeStep, latticeStep)))); + + if (region.intersects(cellQRect) && m_region.intersects(cellQRect)) { + // Release the associated cell from cache and clear the cell from the + // content region. + TImageCache::instance()->remove(getCellCacheId(pos)); + m_region -= cellQRect; + + --m_cellsCount; + + // DIAGNOSTICS_GLOADD("crCellsCnt", -1); + + // Release the cell from m_cellDatas + m_cellDatas[getCellIndex(pos)].m_modified = true; + } + } + + if (m_region.isEmpty()) { + m_tileType = NONE; + m_locksCount = 0; + } } //**************************************************************************************************** // Palette management //**************************************************************************************************** -bool TCacheResource::uploadPalette(TPaletteP palette) -{ - if (m_tileType == NONE) - m_tileType = CM32; +bool TCacheResource::uploadPalette(TPaletteP palette) { + if (m_tileType == NONE) m_tileType = CM32; - if (m_tileType != CM32) { - assert(!"The resource already holds a non-colormap content!"); - return false; - } + if (m_tileType != CM32) { + assert(!"The resource already holds a non-colormap content!"); + return false; + } - m_palette = palette; - return true; + m_palette = palette; + return true; } //----------------------------------------------------------------- -void TCacheResource::downloadPalette(TPaletteP &palette) -{ - palette = m_palette; +void TCacheResource::downloadPalette(TPaletteP &palette) { + palette = m_palette; } //**************************************************************************************************** // References management //**************************************************************************************************** -void TCacheResource::addRef2(const TRect &rect) -{ - //DIAGNOSTICS_NUMBEREDSTRSET(prefix + QString::number((UINT) this) + " | Stack | ", - //"crStack", "addRef", ::traduce(rect)); +void TCacheResource::addRef2(const TRect &rect) { + // DIAGNOSTICS_NUMBEREDSTRSET(prefix + QString::number((UINT) this) + " | + // Stack | ", + //"crStack", "addRef", ::traduce(rect)); - //Add a reference to all cells intersecting the passed one - TPoint initialPos(getCellPos(rect.getP00())); - TPoint pos; - for (pos.x = initialPos.x; pos.x <= rect.x1; pos.x += latticeStep) - for (pos.y = initialPos.y; pos.y <= rect.y1; pos.y += latticeStep) { - PointLess cellIndex(getCellIndex(pos)); - CellData &cellData = m_cellDatas[cellIndex]; - cellData.m_referenced = true; - cellData.m_refsCount++; - } + // Add a reference to all cells intersecting the passed one + TPoint initialPos(getCellPos(rect.getP00())); + TPoint pos; + for (pos.x = initialPos.x; pos.x <= rect.x1; pos.x += latticeStep) + for (pos.y = initialPos.y; pos.y <= rect.y1; pos.y += latticeStep) { + PointLess cellIndex(getCellIndex(pos)); + CellData &cellData = m_cellDatas[cellIndex]; + cellData.m_referenced = true; + cellData.m_refsCount++; + } } //----------------------------------------------------------------- -void TCacheResource::release2(const TRect &rect) -{ - //DIAGNOSTICS_NUMBEREDSTRSET(prefix + QString::number((UINT) this) + " | Stack | ", - //"crStack", "release", ::traduce(rect)); - - if (m_locksCount > 0) - return; - - std::map::iterator it; - for (it = m_cellDatas.begin(); it != m_cellDatas.end();) { - if (!it->second.m_referenced) { - ++it; - continue; - } - - TPoint cellPos(getCellPos(it->first)); - TRect cellRect(cellPos, TDimension(latticeStep, latticeStep)); - - if (isEmpty(cellRect * rect)) { - ++it; - continue; - } - - QRect cellQRect(toQRect(cellRect)); - if (--it->second.m_refsCount <= 0) { - releaseCell(cellQRect, it->first, it->second.m_modified); - std::map::iterator jt = it++; - m_cellDatas.erase(jt); - } else - ++it; - } +void TCacheResource::release2(const TRect &rect) { + // DIAGNOSTICS_NUMBEREDSTRSET(prefix + QString::number((UINT) this) + " | + // Stack | ", + //"crStack", "release", ::traduce(rect)); + + if (m_locksCount > 0) return; + + std::map::iterator it; + for (it = m_cellDatas.begin(); it != m_cellDatas.end();) { + if (!it->second.m_referenced) { + ++it; + continue; + } + + TPoint cellPos(getCellPos(it->first)); + TRect cellRect(cellPos, TDimension(latticeStep, latticeStep)); + + if (isEmpty(cellRect * rect)) { + ++it; + continue; + } + + QRect cellQRect(toQRect(cellRect)); + if (--it->second.m_refsCount <= 0) { + releaseCell(cellQRect, it->first, it->second.m_modified); + std::map::iterator jt = it++; + m_cellDatas.erase(jt); + } else + ++it; + } } //----------------------------------------------------------------- -void TCacheResource::addLock() -{ - //DIAGNOSTICS_NUMBEREDSTR(prefix + QString::number((UINT) this) + " | Stack | ", - //"crStack", "addLock"); +void TCacheResource::addLock() { + // DIAGNOSTICS_NUMBEREDSTR(prefix + QString::number((UINT) this) + " | Stack | + // ", + //"crStack", "addLock"); - ++m_locksCount; + ++m_locksCount; } //----------------------------------------------------------------- -void TCacheResource::releaseLock() -{ - //DIAGNOSTICS_NUMBEREDSTR(prefix + QString::number((UINT) this) + " | Stack | ", - //"crStack", "releaseLock"); +void TCacheResource::releaseLock() { + // DIAGNOSTICS_NUMBEREDSTR(prefix + QString::number((UINT) this) + " | Stack | + // ", + //"crStack", "releaseLock"); - m_locksCount = std::max(m_locksCount - 1, 0); + m_locksCount = std::max(m_locksCount - 1, 0); - if (m_locksCount > 0) - return; + if (m_locksCount > 0) return; - //Check for released cells - std::map::iterator it; - for (it = m_cellDatas.begin(); it != m_cellDatas.end();) - if (it->second.m_referenced) { - TPoint cellPos(getCellPos(it->first)); - QRect cellQRect(cellPos.x, cellPos.y, latticeStep, latticeStep); + // Check for released cells + std::map::iterator it; + for (it = m_cellDatas.begin(); it != m_cellDatas.end();) + if (it->second.m_referenced) { + TPoint cellPos(getCellPos(it->first)); + QRect cellQRect(cellPos.x, cellPos.y, latticeStep, latticeStep); - releaseCell(cellQRect, it->first, it->second.m_modified); - std::map::iterator jt = it++; - m_cellDatas.erase(jt); - } else - ++it; + releaseCell(cellQRect, it->first, it->second.m_modified); + std::map::iterator jt = it++; + m_cellDatas.erase(jt); + } else + ++it; } //----------------------------------------------------------------- -void TCacheResource::releaseCell(const QRect &cellQRect, const PointLess &cellIndex, bool doSave) -{ - if (m_region.intersects(cellQRect)) { - std::string cellCacheId(getCellCacheId(cellIndex.x, cellIndex.y)); +void TCacheResource::releaseCell(const QRect &cellQRect, + const PointLess &cellIndex, bool doSave) { + if (m_region.intersects(cellQRect)) { + std::string cellCacheId(getCellCacheId(cellIndex.x, cellIndex.y)); - if (!(doSave && save(cellIndex))) - m_region -= cellQRect; + if (!(doSave && save(cellIndex))) m_region -= cellQRect; - TImageCache::instance()->remove(cellCacheId); - --m_cellsCount; + TImageCache::instance()->remove(cellCacheId); + --m_cellsCount; - //DIAGNOSTICS_GLOADD("crCellsCnt", -1); - } + // DIAGNOSTICS_GLOADD("crCellsCnt", -1); + } } //----------------------------------------------------------------- //! Returns the current size, in MB, of the cache resource. -int TCacheResource::size() const -{ - //NOTE: It's better to store the size incrementally. This complies - //with the possibility of specifying a bbox to fit the stored cells to... +int TCacheResource::size() const { + // NOTE: It's better to store the size incrementally. This complies + // with the possibility of specifying a bbox to fit the stored cells to... - return m_tileType == NONE ? 0 : m_tileType == RGBM64 ? (m_cellsCount << 11) : (m_cellsCount << 10); + return m_tileType == NONE ? 0 + : m_tileType == RGBM64 ? (m_cellsCount << 11) + : (m_cellsCount << 10); } //**************************************************************************************************** // Hard disk backing procedures //**************************************************************************************************** -void TCacheResource::enableBackup() -{ - if (m_backEnabled) - return; - TCacheResourcePool::instance()->startBacking(this); +void TCacheResource::enableBackup() { + if (m_backEnabled) return; + TCacheResourcePool::instance()->startBacking(this); } //----------------------------------------------------------------- -void TCacheResource::invalidate() -{ - m_invalidated = true; -} +void TCacheResource::invalidate() { m_invalidated = true; } //----------------------------------------------------------------- -void TCacheResource::setPath(const TFilePath &path) -{ - m_path = path; -} +void TCacheResource::setPath(const TFilePath &path) { m_path = path; } //----------------------------------------------------------------- -const TFilePath &TCacheResource::getPath() const -{ - return m_path; -} +const TFilePath &TCacheResource::getPath() const { return m_path; } //----------------------------------------------------------------- -bool TCacheResource::save(const PointLess &cellIndex, TRasterP cellRas) const -{ - if (!m_backEnabled || m_invalidated) - return false; +bool TCacheResource::save(const PointLess &cellIndex, TRasterP cellRas) const { + if (!m_backEnabled || m_invalidated) return false; - assert(!m_path.isEmpty()); + assert(!m_path.isEmpty()); - if (!cellRas) - cellRas = getRaster(TImageCache::instance()->get( - getCellCacheId(cellIndex.x, cellIndex.y), false)); + if (!cellRas) + cellRas = getRaster(TImageCache::instance()->get( + getCellCacheId(cellIndex.x, cellIndex.y), false)); - assert(m_tileType != NONE); + assert(m_tileType != NONE); - TFilePath fp(TCacheResourcePool::instance()->getPath() + m_path + getCellName(cellIndex.x, cellIndex.y)); + TFilePath fp(TCacheResourcePool::instance()->getPath() + m_path + + getCellName(cellIndex.x, cellIndex.y)); - if (m_tileType == CM32) { - ::saveCompressed(fp, cellRas); - } else { - TImageWriter::save(fp.withType(".tif"), cellRas); - } + if (m_tileType == CM32) { + ::saveCompressed(fp, cellRas); + } else { + TImageWriter::save(fp.withType(".tif"), cellRas); + } - return true; + return true; } //----------------------------------------------------------------- -TRasterP TCacheResource::load(const PointLess &cellPos) -{ - if (m_path.isEmpty()) - return 0; +TRasterP TCacheResource::load(const PointLess &cellPos) { + if (m_path.isEmpty()) return 0; - TFilePath cellPath(TCacheResourcePool::instance()->getPath() + m_path + TFilePath(getCellName(cellPos.x, cellPos.y))); - TRasterP ras; - if (m_tileType == CM32) { - ::loadCompressed(cellPath, ras, CM32); - } else { - TImageReader::load(cellPath.withType(".tif"), ras); - } + TFilePath cellPath(TCacheResourcePool::instance()->getPath() + m_path + + TFilePath(getCellName(cellPos.x, cellPos.y))); + TRasterP ras; + if (m_tileType == CM32) { + ::loadCompressed(cellPath, ras, CM32); + } else { + TImageReader::load(cellPath.withType(".tif"), ras); + } - return ras; + return ras; } //----------------------------------------------------------------- -std::pair TCacheResource::touch(const PointLess &cellIndex) -{ - std::string cellId(getCellCacheId(cellIndex.x, cellIndex.y)); +std::pair TCacheResource::touch( + const PointLess &cellIndex) { + std::string cellId(getCellCacheId(cellIndex.x, cellIndex.y)); - std::map::iterator it = m_cellDatas.find(cellIndex); - if (it != m_cellDatas.end()) { - //Retrieve the raster from image cache - TImageP img(TImageCache::instance()->get(cellId, true)); - if (img) - return std::make_pair(getRaster(img), &it->second); - } + std::map::iterator it = m_cellDatas.find(cellIndex); + if (it != m_cellDatas.end()) { + // Retrieve the raster from image cache + TImageP img(TImageCache::instance()->get(cellId, true)); + if (img) return std::make_pair(getRaster(img), &it->second); + } - it = m_cellDatas.insert(std::make_pair(cellIndex, CellData())).first; + it = m_cellDatas.insert(std::make_pair(cellIndex, CellData())).first; - //Then, attempt retrieval from back resource - TRasterP ras(load(cellIndex)); - if (ras) { - TImageCache::instance()->add(cellId, TRasterImageP(ras)); - return std::make_pair(ras, &it->second); - } + // Then, attempt retrieval from back resource + TRasterP ras(load(cellIndex)); + if (ras) { + TImageCache::instance()->add(cellId, TRasterImageP(ras)); + return std::make_pair(ras, &it->second); + } - //Else, create it - return std::make_pair( - createCellRaster(m_tileType, cellId), //increases m_cellsCount too - &it->second); + // Else, create it + return std::make_pair( + createCellRaster(m_tileType, cellId), // increases m_cellsCount too + &it->second); } //----------------------------------------------------------------- -void TCacheResource::save() -{ - if (m_backEnabled && !m_invalidated) { - assert(!m_path.isEmpty()); +void TCacheResource::save() { + if (m_backEnabled && !m_invalidated) { + assert(!m_path.isEmpty()); - //Save each modified cell raster - std::map::iterator it; - for (it = m_cellDatas.begin(); it != m_cellDatas.end(); ++it) { - if (it->second.m_modified) - save(it->first); - } + // Save each modified cell raster + std::map::iterator it; + for (it = m_cellDatas.begin(); it != m_cellDatas.end(); ++it) { + if (it->second.m_modified) save(it->first); + } - //Save the palette, if any - //SHOULD BE MOVED TO THE CACHERESOURCEPOOL!! - /*if(m_palette) - { - TFilePath fp(TCacheResourcePool::instance()->getPath() + m_path); - TOStream oss(fp); + // Save the palette, if any + // SHOULD BE MOVED TO THE CACHERESOURCEPOOL!! + /*if(m_palette) +{ +TFilePath fp(TCacheResourcePool::instance()->getPath() + m_path); +TOStream oss(fp); - m_palette->saveData(oss); - }*/ - } +m_palette->saveData(oss); +}*/ + } } //----------------------------------------------------------------- -void TCacheResource::save(const TFilePath &fp) -{ - assert(!fp.isEmpty()); +void TCacheResource::save(const TFilePath &fp) { + assert(!fp.isEmpty()); - std::map::iterator it; - for (it = m_cellDatas.begin(); it != m_cellDatas.end(); ++it) { - TRasterP cellRas = getRaster(TImageCache::instance()->get( - getCellCacheId(it->first.x, it->first.y), false)); + std::map::iterator it; + for (it = m_cellDatas.begin(); it != m_cellDatas.end(); ++it) { + TRasterP cellRas = getRaster(TImageCache::instance()->get( + getCellCacheId(it->first.x, it->first.y), false)); - assert(m_tileType != NONE); + assert(m_tileType != NONE); - TFilePath cellFp(fp + TFilePath(getCellName(it->first.x, it->first.y))); + TFilePath cellFp(fp + TFilePath(getCellName(it->first.x, it->first.y))); - if (m_tileType == CM32) - ::saveCompressed(cellFp, cellRas); - else - TImageWriter::save(cellFp.withType(".tif"), cellRas); - } + if (m_tileType == CM32) + ::saveCompressed(cellFp, cellRas); + else + TImageWriter::save(cellFp.withType(".tif"), cellRas); + } } //----------------------------------------------------------------- -void TCacheResource::clear() -{ - std::map::iterator it; - for (it = m_cellDatas.begin(); it != m_cellDatas.end(); ++it) { - std::string cellCacheId(getCellCacheId(it->first.x, it->first.y)); - TImageCache::instance()->remove(cellCacheId); - } +void TCacheResource::clear() { + std::map::iterator it; + for (it = m_cellDatas.begin(); it != m_cellDatas.end(); ++it) { + std::string cellCacheId(getCellCacheId(it->first.x, it->first.y)); + TImageCache::instance()->remove(cellCacheId); + } - m_cellDatas.clear(); + m_cellDatas.clear(); } /* -// *************************************************************************************************** +// +*************************************************************************************************** // Disk reference -// *************************************************************************************************** +// +*************************************************************************************************** #include TCacheResource::DiskReference::DiskReference(const TFilePath& fp) { QSettings settings( - QString::fromStdWString((TCacheResourcePool::instance()->getPath() + m_path + "resource.ini").getWideString()), + QString::fromStdWString((TCacheResourcePool::instance()->getPath() + m_path ++ "resource.ini").getWideString()), QSettings::IniFormat); settings.setValue("MemReference", 1); @@ -999,7 +968,8 @@ TCacheResource::DiskReference::DiskReference(const TFilePath& fp) TCacheResource::DiskReference::~DiskReference() { QSettings settings( - QString::fromStdWString((TCacheResourcePool::instance()->getPath() + m_path + "resource.ini").getWideString()), + QString::fromStdWString((TCacheResourcePool::instance()->getPath() + m_path ++ "resource.ini").getWideString()), QSettings::IniFormat); int diskReference = settings.value("DiskReference").toInt(); diff --git a/toonz/sources/common/tfx/tcacheresourcepool.cpp b/toonz/sources/common/tfx/tcacheresourcepool.cpp index 03f16a7..7adf7f9 100644 --- a/toonz/sources/common/tfx/tcacheresourcepool.cpp +++ b/toonz/sources/common/tfx/tcacheresourcepool.cpp @@ -1,6 +1,6 @@ -//Qt includes +// Qt includes #include #include #include @@ -11,13 +11,13 @@ //#define USE_SQLITE_HDPOOL #ifdef USE_SQLITE_HDPOOL -//SQLite include +// SQLite include #include "sqlite/sqlite3.h" #endif #include "tcacheresourcepool.h" -//Debug +// Debug //#define DIAGNOSTICS //#include "diagnostics.h" @@ -25,33 +25,28 @@ // Cache Resource Pool BACKED ON DISK //****************************************************************************************** -//STILL UNDER DEVELOPMENT... -class THDCacheResourcePool -{ +// STILL UNDER DEVELOPMENT... +class THDCacheResourcePool { public: - THDCacheResourcePool() {} - ~THDCacheResourcePool() {} + THDCacheResourcePool() {} + ~THDCacheResourcePool() {} }; //************************************************************************************* // Cache resource pool methods involved with HD Pool management //************************************************************************************* -inline bool TCacheResourcePool::isHDActive() -{ +inline bool TCacheResourcePool::isHDActive() { #ifdef USE_SQLITE_HDPOOL - return m_hdPool && m_hdPool->isActive(); + return m_hdPool && m_hdPool->isActive(); #else - return false; + return false; #endif } //----------------------------------------------------------------------------------- -void TCacheResourcePool::reset() -{ - setPath("", "", ""); -} +void TCacheResourcePool::reset() { setPath("", "", ""); } //---------------------------------------------------------------------- @@ -59,20 +54,20 @@ void TCacheResourcePool::reset() // the actual content of the resource is NOT invalidated - since resources // are intended as 'reference-protected' material which is expected to last // as long as references are held. -void TCacheResourcePool::invalidateAll() -{ - QMutexLocker locker(&m_memMutex); +void TCacheResourcePool::invalidateAll() { + QMutexLocker locker(&m_memMutex); - MemResources::iterator it; - for (it = m_memResources.begin(); it != m_memResources.end(); ++it) - it->second->invalidate(); + MemResources::iterator it; + for (it = m_memResources.begin(); it != m_memResources.end(); ++it) + it->second->invalidate(); } //---------------------------------------------------------------------- -inline QString TCacheResourcePool::getPoolRoot(QString cacheRoot, QString projectName, QString sceneName) -{ - return QString(cacheRoot + "/render/" + projectName + "/" + sceneName + "/"); +inline QString TCacheResourcePool::getPoolRoot(QString cacheRoot, + QString projectName, + QString sceneName) { + return QString(cacheRoot + "/render/" + projectName + "/" + sceneName + "/"); } //---------------------------------------------------------------------- @@ -81,45 +76,44 @@ inline QString TCacheResourcePool::getPoolRoot(QString cacheRoot, QString projec //! \warning As this closes the current connection before opening a new one, //! make sure that no pool access happens at this point. You should also //! verify that no resource from the old pair still exists. -void TCacheResourcePool::setPath(QString cacheRoot, QString projectName, QString sceneName) -{ - //There should be no resource in memory. - assert(m_memResources.empty()); - - //However, just in case, invalidate all resources so that no more resource backing - //operation take place for current resources, from now on. - //No care is paid as to whether active transactions currently exist. You - //have been warned by the way.... - invalidateAll(); - - delete m_hdPool; - m_hdPool = 0; - m_path = TFilePath(); +void TCacheResourcePool::setPath(QString cacheRoot, QString projectName, + QString sceneName) { + // There should be no resource in memory. + assert(m_memResources.empty()); + + // However, just in case, invalidate all resources so that no more resource + // backing + // operation take place for current resources, from now on. + // No care is paid as to whether active transactions currently exist. You + // have been warned by the way.... + invalidateAll(); + + delete m_hdPool; + m_hdPool = 0; + m_path = TFilePath(); #ifdef USE_SQLITE_HDPOOL - if (!(cacheRoot.isEmpty() || projectName.isEmpty() || sceneName.isEmpty())) { - QString hdPoolRoot(getPoolRoot(cacheRoot, projectName, sceneName)); - m_hdPool = new THDCacheResourcePool(hdPoolRoot); - m_path = m_hdPool->getResourcesFilePath(); - } + if (!(cacheRoot.isEmpty() || projectName.isEmpty() || sceneName.isEmpty())) { + QString hdPoolRoot(getPoolRoot(cacheRoot, projectName, sceneName)); + m_hdPool = new THDCacheResourcePool(hdPoolRoot); + m_path = m_hdPool->getResourcesFilePath(); + } #endif } //----------------------------------------------------------------------------------- -void TCacheResourcePool::startBacking(TCacheResource *resource) -{ - assert(isHDActive()); - if (!isHDActive()) - return; +void TCacheResourcePool::startBacking(TCacheResource *resource) { + assert(isHDActive()); + if (!isHDActive()) return; #ifdef USE_SQLITE_HDPOOL - resource->m_backEnabled = true; + resource->m_backEnabled = true; - m_hdPool->buildBackingPath(resource); + m_hdPool->buildBackingPath(resource); #endif } @@ -128,168 +122,171 @@ void TCacheResourcePool::startBacking(TCacheResource *resource) // Cache resource pool implementation //****************************************************************************************** -TCacheResourcePool *TCacheResourcePool::instance() -{ - static TCacheResourcePool theInstance; - return &theInstance; +TCacheResourcePool *TCacheResourcePool::instance() { + static TCacheResourcePool theInstance; + return &theInstance; } //---------------------------------------------------------------------- TCacheResourcePool::TCacheResourcePool() - : m_memMutex(QMutex::Recursive), m_searchCount(0), m_foundIterator(false), m_searchIterator(m_memResources.end()), m_hdPool(0), m_path() -{ - //Open the settings for cache retrieval + : m_memMutex(QMutex::Recursive) + , m_searchCount(0) + , m_foundIterator(false) + , m_searchIterator(m_memResources.end()) + , m_hdPool(0) + , m_path() { + // Open the settings for cache retrieval } //---------------------------------------------------------------------- -TCacheResourcePool::~TCacheResourcePool() -{ - //Temporary - //performAutomaticCleanup(); +TCacheResourcePool::~TCacheResourcePool() { + // Temporary + // performAutomaticCleanup(); - delete m_hdPool; + delete m_hdPool; } //---------------------------------------------------------------------- -const TFilePath &TCacheResourcePool::getPath() const -{ - return m_path; -} +const TFilePath &TCacheResourcePool::getPath() const { return m_path; } //---------------------------------------------------------------------- -//! Initializes an optimized search on the pool for a specific resource, caching successive +//! Initializes an optimized search on the pool for a specific resource, caching +//! successive //! results. -//! \note Pool searches are serialized, and calls to this method lock the pool's mutex until a +//! \note Pool searches are serialized, and calls to this method lock the pool's +//! mutex until a //! corresponding number of endCachedSearch() methods are invoked. -void TCacheResourcePool::beginCachedSearch() -{ - m_memMutex.lock(); - m_searchCount++; +void TCacheResourcePool::beginCachedSearch() { + m_memMutex.lock(); + m_searchCount++; } //---------------------------------------------------------------------- -//! The inverse to beginCachedSearch(). This method \b MUST be called in correspondence to +//! The inverse to beginCachedSearch(). This method \b MUST be called in +//! correspondence to //! beginCachedSearch() calls. -void TCacheResourcePool::endCachedSearch() -{ - if (--m_searchCount <= 0) { - m_foundIterator = false; - m_searchIterator = m_memResources.end(); - } - m_memMutex.unlock(); +void TCacheResourcePool::endCachedSearch() { + if (--m_searchCount <= 0) { + m_foundIterator = false; + m_searchIterator = m_memResources.end(); + } + m_memMutex.unlock(); } //---------------------------------------------------------------------- -//! Attempts retrieval of the resource with specified name, and eventually creates it if +//! Attempts retrieval of the resource with specified name, and eventually +//! creates it if //! the createIfNone parameter is set. -TCacheResource *TCacheResourcePool::getResource(const std::string &name, bool createIfNone) -{ - //DIAGNOSTICS_TIMER("#times.txt | getResource Overall time"); - //DIAGNOSTICS_MEANTIMER("#times.txt | getResource Mean time"); - - TCacheResource *result = 0; - - //NOTA: Passa ad un oggetto lockatore. Quello e' in grado di gestire i casi di eccezioni ecc.. - beginCachedSearch(); - - //Search for an already allocated resource - if (m_searchIterator == m_memResources.end()) { - m_searchIterator = m_memResources.lower_bound(name); - if (m_searchIterator != m_memResources.end()) - if (!(name < m_searchIterator->first)) - m_foundIterator = true; - else if (m_searchIterator != m_memResources.begin()) - m_searchIterator--; - } - - if (m_foundIterator) { - result = m_searchIterator->second; - - endCachedSearch(); - return result; - } - - { - QString resourcePath; - QString resourceFlags; - - if (isHDActive()) { +TCacheResource *TCacheResourcePool::getResource(const std::string &name, + bool createIfNone) { + // DIAGNOSTICS_TIMER("#times.txt | getResource Overall time"); + // DIAGNOSTICS_MEANTIMER("#times.txt | getResource Mean time"); + + TCacheResource *result = 0; + + // NOTA: Passa ad un oggetto lockatore. Quello e' in grado di gestire i casi + // di eccezioni ecc.. + beginCachedSearch(); + + // Search for an already allocated resource + if (m_searchIterator == m_memResources.end()) { + m_searchIterator = m_memResources.lower_bound(name); + if (m_searchIterator != m_memResources.end()) + if (!(name < m_searchIterator->first)) + m_foundIterator = true; + else if (m_searchIterator != m_memResources.begin()) + m_searchIterator--; + } + + if (m_foundIterator) { + result = m_searchIterator->second; + + endCachedSearch(); + return result; + } + + { + QString resourcePath; + QString resourceFlags; + + if (isHDActive()) { #ifdef USE_SQLITE_HDPOOL - //DIAGNOSTICS_TIMER("#times.txt | HDPOOL getResource Overall time"); - //DIAGNOSTICS_MEANTIMER("#times.txt | HDPOOL getResource Mean time"); + // DIAGNOSTICS_TIMER("#times.txt | HDPOOL getResource Overall time"); + // DIAGNOSTICS_MEANTIMER("#times.txt | HDPOOL getResource Mean time"); - //Search in the HD pool - ReadQuery query(m_hdPool); + // Search in the HD pool + ReadQuery query(m_hdPool); - bool ret = query.prepare( - "SELECT Path, Flags FROM Resources WHERE Name = '" + QString::fromStdString(name) + "';"); + bool ret = + query.prepare("SELECT Path, Flags FROM Resources WHERE Name = '" + + QString::fromStdString(name) + "';"); - //If an error occurred, assume the resource does not exist. Doing nothing works fine. - assert(ret); + // If an error occurred, assume the resource does not exist. Doing nothing + // works fine. + assert(ret); - if (query.step()) { - resourcePath = query.value(0); - resourceFlags = query.value(1); - } + if (query.step()) { + resourcePath = query.value(0); + resourceFlags = query.value(1); + } #endif - } + } - if (!resourcePath.isEmpty() || createIfNone) { - TCacheResource *result = new TCacheResource; - result->m_pos = m_searchIterator = - m_memResources.insert(m_searchIterator, std::make_pair(name, result)); + if (!resourcePath.isEmpty() || createIfNone) { + TCacheResource *result = new TCacheResource; + result->m_pos = m_searchIterator = + m_memResources.insert(m_searchIterator, std::make_pair(name, result)); -//DIAGNOSTICS_STRSET("#resources.txt | RISORSE | " + QString::number((UINT) result) + " | Name", -//QString::fromStdString(name).left(70)); +// DIAGNOSTICS_STRSET("#resources.txt | RISORSE | " + QString::number((UINT) +// result) + " | Name", +// QString::fromStdString(name).left(70)); #ifdef USE_SQLITE_HDPOOL - if (isHDActive()) - m_hdPool->loadResourceInfos(result, resourcePath); + if (isHDActive()) m_hdPool->loadResourceInfos(result, resourcePath); #endif - m_foundIterator = true; - endCachedSearch(); + m_foundIterator = true; + endCachedSearch(); - return result; - } - } + return result; + } + } - endCachedSearch(); - return 0; + endCachedSearch(); + return 0; } //---------------------------------------------------------------------- -void TCacheResourcePool::releaseResource(TCacheResource *resource) -{ - QMutexLocker locker(&m_memMutex); +void TCacheResourcePool::releaseResource(TCacheResource *resource) { + QMutexLocker locker(&m_memMutex); - //Re-check the resource's reference count. This is necessary since a concurrent - //thread may have locked the memMutex for resource retrieval BEFORE this one. - //If that is the case, the resource's refCount has increased back above 0. - if (resource->m_refCount > 0) - return; + // Re-check the resource's reference count. This is necessary since a + // concurrent + // thread may have locked the memMutex for resource retrieval BEFORE this one. + // If that is the case, the resource's refCount has increased back above 0. + if (resource->m_refCount > 0) return; #ifdef USE_SQLITE_HDPOOL - QMutexLocker flushLocker(isHDActive() ? &m_hdPool->m_flushMutex : 0); + QMutexLocker flushLocker(isHDActive() ? &m_hdPool->m_flushMutex : 0); - if (isHDActive()) { - //Flush all resource updates as this resource is being destroyed - m_hdPool->flushResources(); + if (isHDActive()) { + // Flush all resource updates as this resource is being destroyed + m_hdPool->flushResources(); - //Save the resource infos - m_hdPool->saveResourceInfos(resource); - } + // Save the resource infos + m_hdPool->saveResourceInfos(resource); + } #endif - m_memResources.erase(resource->m_pos); - delete resource; + m_memResources.erase(resource->m_pos); + delete resource; } diff --git a/toonz/sources/common/tfx/tfx.cpp b/toonz/sources/common/tfx/tfx.cpp index f31b5f4..6750007 100644 --- a/toonz/sources/common/tfx/tfx.cpp +++ b/toonz/sources/common/tfx/tfx.cpp @@ -18,12 +18,11 @@ //============================================================================== -TIStream &operator>>(TIStream &in, TFxP &p) -{ - TPersist *tmp = 0; - in >> tmp; - p = TFxP(dynamic_cast(tmp)); - return in; +TIStream &operator>>(TIStream &in, TFxP &p) { + TPersist *tmp = 0; + in >> tmp; + p = TFxP(dynamic_cast(tmp)); + return in; } //============================================================================== @@ -32,8 +31,7 @@ TIStream &operator>>(TIStream &in, TFxP &p) // //------------------------------------------------------------------------------ -namespace -{ +namespace { //------------------------------------------------------------------------------ @@ -43,42 +41,37 @@ typedef std::vector PortArray; //------------------------------------------------------------------------------ -class PortNameEq -{ - std::string m_name; +class PortNameEq { + std::string m_name; public: - PortNameEq(const std::string &name) : m_name(name) {} - ~PortNameEq() {} - bool operator()(const NamePort &np) { return np.first == m_name; } + PortNameEq(const std::string &name) : m_name(name) {} + ~PortNameEq() {} + bool operator()(const NamePort &np) { return np.first == m_name; } }; //------------------------------------------------------------------------------ -void skipChild(TIStream &is) -{ - while (!is.eos()) { - std::string dummy = is.getString(); - std::string tagName; - while (is.openChild(tagName)) { - skipChild(is); - if (is.isBeginEndTag()) - is.matchTag(tagName); - is.closeChild(); - } - } +void skipChild(TIStream &is) { + while (!is.eos()) { + std::string dummy = is.getString(); + std::string tagName; + while (is.openChild(tagName)) { + skipChild(is); + if (is.isBeginEndTag()) is.matchTag(tagName); + is.closeChild(); + } + } } //------------------------------------------------------------------------------ -TPointD updateDagPosition(const TPointD &pos, const VersionNumber &tnzVersion) -{ - if (tnzVersion < VersionNumber(1, 16)) - return TConst::nowhere; - return pos; +TPointD updateDagPosition(const TPointD &pos, const VersionNumber &tnzVersion) { + if (tnzVersion < VersionNumber(1, 16)) return TConst::nowhere; + return pos; } -} // namespace +} // namespace //============================================================================== // @@ -86,17 +79,15 @@ TPointD updateDagPosition(const TPointD &pos, const VersionNumber &tnzVersion) // //------------------------------------------------------------------------------ -TFxParamChange::TFxParamChange(TFx *fx, double firstAffectedFrame, double lastAffectedFrame, bool dragging) - : TFxChange(fx, firstAffectedFrame, lastAffectedFrame, dragging) -{ -} +TFxParamChange::TFxParamChange(TFx *fx, double firstAffectedFrame, + double lastAffectedFrame, bool dragging) + : TFxChange(fx, firstAffectedFrame, lastAffectedFrame, dragging) {} //-------------------------------------------------- TFxParamChange::TFxParamChange(TFx *fx, const TParamChange &src) - : TFxChange(fx, src.m_firstAffectedFrame, src.m_lastAffectedFrame, src.m_dragging) -{ -} + : TFxChange(fx, src.m_firstAffectedFrame, src.m_lastAffectedFrame, + src.m_dragging) {} //============================================================================== // @@ -114,38 +105,29 @@ double TFxChange::m_maxFrame = +(std::numeric_limits::max)(); //------------------------------------------------------------------------------ TFxPortDynamicGroup::TFxPortDynamicGroup(const std::string &prefix, int minSize) - : m_portsPrefix(prefix), m_minPortsCount(minSize) -{ -} + : m_portsPrefix(prefix), m_minPortsCount(minSize) {} //-------------------------------------------------- -TFxPortDynamicGroup::~TFxPortDynamicGroup() -{ - clear(); -} +TFxPortDynamicGroup::~TFxPortDynamicGroup() { clear(); } //-------------------------------------------------- -void TFxPortDynamicGroup::addPort(TFxPort *port) -{ - m_ports.push_back(port); -} +void TFxPortDynamicGroup::addPort(TFxPort *port) { m_ports.push_back(port); } //-------------------------------------------------- -void TFxPortDynamicGroup::removePort(TFxPort *port) -{ - m_ports.resize(std::remove(m_ports.begin(), m_ports.end(), port) - m_ports.begin()); - delete port; +void TFxPortDynamicGroup::removePort(TFxPort *port) { + m_ports.resize(std::remove(m_ports.begin(), m_ports.end(), port) - + m_ports.begin()); + delete port; } //-------------------------------------------------- -void TFxPortDynamicGroup::clear() -{ - std::for_each(m_ports.begin(), m_ports.end(), TDeleteObjectFunctor()); - m_ports.clear(); +void TFxPortDynamicGroup::clear() { + std::for_each(m_ports.begin(), m_ports.end(), TDeleteObjectFunctor()); + m_ports.clear(); } //============================================================================== @@ -154,57 +136,53 @@ void TFxPortDynamicGroup::clear() // //------------------------------------------------------------------------------ -class TFxImp -{ +class TFxImp { public: - TFx *m_fx; //!< Fx back-pointer - TFxImp *m_prev, *m_next; //!< Linked fxs + TFx *m_fx; //!< Fx back-pointer + TFxImp *m_prev, *m_next; //!< Linked fxs - std::wstring m_name; - std::wstring m_fxId; + std::wstring m_name; + std::wstring m_fxId; - PortTable m_portTable; //!< Name -> port map - PortArray m_portArray; //!< Ports container + PortTable m_portTable; //!< Name -> port map + PortArray m_portArray; //!< Ports container - TParamContainer m_paramContainer; + TParamContainer m_paramContainer; - std::set m_outputPort; - TFxTimeRegion m_activeTimeRegion; - std::set m_observers; + std::set m_outputPort; + TFxTimeRegion m_activeTimeRegion; + std::set m_observers; - TFxAttributes m_attributes; + TFxAttributes m_attributes; - static unsigned long m_nextId; - unsigned long m_id; //!< Unique fx identifier, per Toonz session. - //!< It is intended to be used \b solely to build - //!< an internal string description of the fx. + static unsigned long m_nextId; + unsigned long m_id; //!< Unique fx identifier, per Toonz session. + //!< It is intended to be used \b solely to build + //!< an internal string description of the fx. public: - TFxImp(TFx *fx) - : m_fx(fx), m_activeTimeRegion(TFxTimeRegion::createUnlimited()), m_id() - { - m_prev = m_next = this; - } - - ~TFxImp() - { - m_prev->m_next = m_next; - m_next->m_prev = m_prev; - } - - bool checkLinks() const - { - assert(m_prev); - assert(m_next); - assert(m_prev->m_next == this); - assert(m_next->m_prev == this); - - return true; - } + TFxImp(TFx *fx) + : m_fx(fx), m_activeTimeRegion(TFxTimeRegion::createUnlimited()), m_id() { + m_prev = m_next = this; + } + + ~TFxImp() { + m_prev->m_next = m_next; + m_next->m_prev = m_prev; + } + + bool checkLinks() const { + assert(m_prev); + assert(m_next); + assert(m_prev->m_next == this); + assert(m_next->m_prev == this); + + return true; + } private: - // not copyable - TFxImp(const TFxImp &); - TFxImp &operator=(const TFxImp &); + // not copyable + TFxImp(const TFxImp &); + TFxImp &operator=(const TFxImp &); }; //-------------------------------------------------- @@ -217,55 +195,49 @@ unsigned long TFxImp::m_nextId = 0; // //------------------------------------------------------------------------------ -class TFxFactory // singleton +class TFxFactory // singleton { - typedef std::map> Table; + typedef std::map> Table; - Table m_table; - std::vector m_map; + Table m_table; + std::vector m_map; - TFxFactory() {} + TFxFactory() {} public: - static TFxFactory *instance() - { - static TFxFactory _instance; - return &_instance; - } - - void add(const TFxInfo &info, TFxDeclaration *decl) - { - // check for dups ??? - std::pair p(info, decl); - m_table[info.m_name] = p; - } - - TFx *create(std::string name) - { - Table::iterator it = m_table.find(name); - if (it != m_table.end()) { - TFxDeclaration *decl = it->second.second; - - TPersist *obj = decl->create(); - assert(obj); - - return dynamic_cast(obj); - } else - return TExternFx::create(name); - } - - void getFxInfos(std::vector &info) const - { - for (Table::const_iterator it = m_table.begin(); it != m_table.end(); ++it) - info.push_back(it->second.first); - } - - TFxInfo getFxInfo(const std::string &fxIdentifier) const - { - Table::const_iterator it = m_table.find(fxIdentifier); - return (it != m_table.end()) ? it->second.first : TFxInfo(); - } + static TFxFactory *instance() { + static TFxFactory _instance; + return &_instance; + } + + void add(const TFxInfo &info, TFxDeclaration *decl) { + // check for dups ??? + std::pair p(info, decl); + m_table[info.m_name] = p; + } + + TFx *create(std::string name) { + Table::iterator it = m_table.find(name); + if (it != m_table.end()) { + TFxDeclaration *decl = it->second.second; + + TPersist *obj = decl->create(); + assert(obj); + + return dynamic_cast(obj); + } else + return TExternFx::create(name); + } + + void getFxInfos(std::vector &info) const { + for (Table::const_iterator it = m_table.begin(); it != m_table.end(); ++it) + info.push_back(it->second.first); + } + + TFxInfo getFxInfo(const std::string &fxIdentifier) const { + Table::const_iterator it = m_table.find(fxIdentifier); + return (it != m_table.end()) ? it->second.first : TFxInfo(); + } }; //============================================================================== @@ -275,9 +247,8 @@ public: //------------------------------------------------------------------------------ TFxDeclaration::TFxDeclaration(const TFxInfo &info) - : TPersistDeclaration(info.m_name) -{ - TFxFactory::instance()->add(info, this); + : TPersistDeclaration(info.m_name) { + TFxFactory::instance()->add(info, this); } //============================================================================== @@ -291,807 +262,716 @@ DEFINE_CLASS_CODE(TFx, 3) //------------------------------------------------------------------------------ TFx::TFx() - : TSmartObject(m_classCode) // TPersist(TFxImp::m_instances) - , m_imp(new TFxImp(this)) -{ -} + : TSmartObject(m_classCode) // TPersist(TFxImp::m_instances) + , m_imp(new TFxImp(this)) {} //-------------------------------------------------- -TFx::~TFx() -{ - for (std::set::iterator it = m_imp->m_outputPort.begin(); - it != m_imp->m_outputPort.end(); ++it) { - TFxPort *port = *it; - port->setFx(0); - } +TFx::~TFx() { + for (std::set::iterator it = m_imp->m_outputPort.begin(); + it != m_imp->m_outputPort.end(); ++it) { + TFxPort *port = *it; + port->setFx(0); + } - delete m_imp; + delete m_imp; } //-------------------------------------------------- -std::wstring TFx::getName() const -{ - return m_imp->m_name; -} +std::wstring TFx::getName() const { return m_imp->m_name; } //-------------------------------------------------- -void TFx::setName(std::wstring name) -{ - m_imp->m_name = name; -} +void TFx::setName(std::wstring name) { m_imp->m_name = name; } //-------------------------------------------------- -std::wstring TFx::getFxId() const -{ - return m_imp->m_fxId; -} +std::wstring TFx::getFxId() const { return m_imp->m_fxId; } //-------------------------------------------------- -void TFx::setFxId(std::wstring id) -{ - m_imp->m_fxId = id; -} +void TFx::setFxId(std::wstring id) { m_imp->m_fxId = id; } //-------------------------------------------------- -TFxAttributes *TFx::getAttributes() const -{ - return &m_imp->m_attributes; -} +TFxAttributes *TFx::getAttributes() const { return &m_imp->m_attributes; } //-------------------------------------------------- -const TParamContainer *TFx::getParams() const -{ - return &m_imp->m_paramContainer; +const TParamContainer *TFx::getParams() const { + return &m_imp->m_paramContainer; } //-------------------------------------------------- -TParamContainer *TFx::getParams() -{ - return &m_imp->m_paramContainer; -} +TParamContainer *TFx::getParams() { return &m_imp->m_paramContainer; } //-------------------------------------------------- -TFx *TFx::clone(bool recursive) const -{ - TFx *fx = TFx::create(getFxType()); - assert(fx); - return this->clone(fx, recursive); +TFx *TFx::clone(bool recursive) const { + TFx *fx = TFx::create(getFxType()); + assert(fx); + return this->clone(fx, recursive); } -TFx *TFx::clone(TFx *fx, bool recursive) const -{ - // Copy misc stuff - - fx->m_imp->m_activeTimeRegion = m_imp->m_activeTimeRegion; - fx->setIdentifier(getIdentifier()); - fx->getParams()->copy(getParams()); - fx->setFxId(getFxId()); - fx->setName(getName()); - - // Copy attributes - *fx->getAttributes() = *getAttributes(); - - // Clone the dynamic ports pool - if (hasDynamicPortGroups()) { - int p, pCount = m_imp->m_portArray.size(); - for (p = 0; p != pCount; ++p) { - const NamePort &namedPort = m_imp->m_portArray[p]; - - int groupIdx = namedPort.second->getGroupIndex(); - if (groupIdx >= 0 && !fx->getInputPort(namedPort.first)) - fx->addInputPort(namedPort.first, new TRasterFxPort, groupIdx); - } - - assert(pCount == fx->getInputPortCount()); - } - - // copia ricorsiva sulle porte - if (recursive) { - int p, pCount = getInputPortCount(); - for (p = 0; p != pCount; ++p) { - TFxPort *port = getInputPort(p); - if (port->getFx()) - fx->connect(getInputPortName(p), port->getFx()->clone(true)); - } - } - - return fx; +TFx *TFx::clone(TFx *fx, bool recursive) const { + // Copy misc stuff + + fx->m_imp->m_activeTimeRegion = m_imp->m_activeTimeRegion; + fx->setIdentifier(getIdentifier()); + fx->getParams()->copy(getParams()); + fx->setFxId(getFxId()); + fx->setName(getName()); + + // Copy attributes + *fx->getAttributes() = *getAttributes(); + + // Clone the dynamic ports pool + if (hasDynamicPortGroups()) { + int p, pCount = m_imp->m_portArray.size(); + for (p = 0; p != pCount; ++p) { + const NamePort &namedPort = m_imp->m_portArray[p]; + + int groupIdx = namedPort.second->getGroupIndex(); + if (groupIdx >= 0 && !fx->getInputPort(namedPort.first)) + fx->addInputPort(namedPort.first, new TRasterFxPort, groupIdx); + } + + assert(pCount == fx->getInputPortCount()); + } + + // copia ricorsiva sulle porte + if (recursive) { + int p, pCount = getInputPortCount(); + for (p = 0; p != pCount; ++p) { + TFxPort *port = getInputPort(p); + if (port->getFx()) + fx->connect(getInputPortName(p), port->getFx()->clone(true)); + } + } + + return fx; } //-------------------------------------------------- -void TFx::linkParams(TFx *fx) -{ - if (this == fx) - return; - getParams()->link(fx->getParams()); - m_imp->m_activeTimeRegion = fx->m_imp->m_activeTimeRegion; +void TFx::linkParams(TFx *fx) { + if (this == fx) return; + getParams()->link(fx->getParams()); + m_imp->m_activeTimeRegion = fx->m_imp->m_activeTimeRegion; - // aggiorno i link - assert(m_imp->checkLinks()); - assert(fx->m_imp->checkLinks()); + // aggiorno i link + assert(m_imp->checkLinks()); + assert(fx->m_imp->checkLinks()); - tswap(m_imp->m_next, fx->m_imp->m_next); - tswap(m_imp->m_next->m_prev, fx->m_imp->m_next->m_prev); + tswap(m_imp->m_next, fx->m_imp->m_next); + tswap(m_imp->m_next->m_prev, fx->m_imp->m_next->m_prev); - assert(m_imp->checkLinks()); - assert(fx->m_imp->checkLinks()); + assert(m_imp->checkLinks()); + assert(fx->m_imp->checkLinks()); } //-------------------------------------------------- -void TFx::unlinkParams() -{ - // clone dei parametri - getParams()->unlink(); - - assert(m_imp->m_prev); - assert(m_imp->m_next); - assert(m_imp->m_prev->m_next == m_imp); - assert(m_imp->m_next->m_prev == m_imp); - m_imp->m_prev->m_next = m_imp->m_next; - m_imp->m_next->m_prev = m_imp->m_prev; - m_imp->m_next = m_imp->m_prev = m_imp; - - notify(TFxParamsUnlinked(this)); +void TFx::unlinkParams() { + // clone dei parametri + getParams()->unlink(); + + assert(m_imp->m_prev); + assert(m_imp->m_next); + assert(m_imp->m_prev->m_next == m_imp); + assert(m_imp->m_next->m_prev == m_imp); + m_imp->m_prev->m_next = m_imp->m_next; + m_imp->m_next->m_prev = m_imp->m_prev; + m_imp->m_next = m_imp->m_prev = m_imp; + + notify(TFxParamsUnlinked(this)); } //-------------------------------------------------- -bool TFx::addInputPort(const std::string &name, TFxPort &port) -{ - PortTable::iterator it = m_imp->m_portTable.find(name); - if (it != m_imp->m_portTable.end()) - return false; +bool TFx::addInputPort(const std::string &name, TFxPort &port) { + PortTable::iterator it = m_imp->m_portTable.find(name); + if (it != m_imp->m_portTable.end()) return false; - m_imp->m_portTable[name] = &port; - m_imp->m_portArray.push_back(NamePort(name, &port)); - port.setOwnerFx(this); // back pointer to the owner... + m_imp->m_portTable[name] = &port; + m_imp->m_portArray.push_back(NamePort(name, &port)); + port.setOwnerFx(this); // back pointer to the owner... - return true; + return true; } //-------------------------------------------------- -bool TFx::addInputPort(const std::string &name, TFxPort *port, int groupIndex) -{ - if (!port) { - assert(port); - return false; - } +bool TFx::addInputPort(const std::string &name, TFxPort *port, int groupIndex) { + if (!port) { + assert(port); + return false; + } - if (groupIndex >= dynamicPortGroupsCount()) { - assert(groupIndex < dynamicPortGroupsCount()); - return false; - } + if (groupIndex >= dynamicPortGroupsCount()) { + assert(groupIndex < dynamicPortGroupsCount()); + return false; + } - if (!addInputPort(name, *port)) - return false; + if (!addInputPort(name, *port)) return false; - // Assign the port to the associated group - port->m_groupIdx = groupIndex; + // Assign the port to the associated group + port->m_groupIdx = groupIndex; - TFxPortDG *group = const_cast(dynamicPortGroup(groupIndex)); - group->addPort(port); + TFxPortDG *group = const_cast(dynamicPortGroup(groupIndex)); + group->addPort(port); - assert(name.find(group->m_portsPrefix) == 0); + assert(name.find(group->m_portsPrefix) == 0); - return true; + return true; } //-------------------------------------------------- -bool TFx::removeInputPort(const std::string &name) -{ - m_imp->m_portTable.erase(name); +bool TFx::removeInputPort(const std::string &name) { + m_imp->m_portTable.erase(name); - PortArray::iterator it = std::find_if(m_imp->m_portArray.begin(), m_imp->m_portArray.end(), PortNameEq(name)); - if (it == m_imp->m_portArray.end()) - return false; + PortArray::iterator it = std::find_if( + m_imp->m_portArray.begin(), m_imp->m_portArray.end(), PortNameEq(name)); + if (it == m_imp->m_portArray.end()) return false; - TFxPort *port = it->second; - port->setOwnerFx(0); + TFxPort *port = it->second; + port->setOwnerFx(0); - if (port->m_groupIdx >= 0) { - TFxPortDG *group = const_cast(this->dynamicPortGroup(port->m_groupIdx)); - group->removePort(port); // The port is DELETED here - } + if (port->m_groupIdx >= 0) { + TFxPortDG *group = + const_cast(this->dynamicPortGroup(port->m_groupIdx)); + group->removePort(port); // The port is DELETED here + } - m_imp->m_portArray.erase(it); - return true; + m_imp->m_portArray.erase(it); + return true; } //-------------------------------------------------- -namespace -{ +namespace { struct IsPrefix { - const std::string &m_prefix; - bool operator()(const NamePort &nameport) - { - return (strncmp(m_prefix.c_str(), nameport.first.c_str(), m_prefix.size()) == 0); - } + const std::string &m_prefix; + bool operator()(const NamePort &nameport) { + return (strncmp(m_prefix.c_str(), nameport.first.c_str(), + m_prefix.size()) == 0); + } }; -} // namespace +} // namespace -void TFx::clearDynamicPortGroup(int g) -{ - TFxPortDG *dg = const_cast(this->dynamicPortGroup(g)); +void TFx::clearDynamicPortGroup(int g) { + TFxPortDG *dg = const_cast(this->dynamicPortGroup(g)); - const std::string &prefix = dg->portsPrefix(); + const std::string &prefix = dg->portsPrefix(); - std::string prefixEnd = prefix; - ++prefixEnd[prefixEnd.size() - 1]; + std::string prefixEnd = prefix; + ++prefixEnd[prefixEnd.size() - 1]; - { - // Delete all associated ports from the ports table - PortTable::iterator pBegin(m_imp->m_portTable.lower_bound(prefix)); - PortTable::iterator pEnd(m_imp->m_portTable.lower_bound(prefixEnd)); + { + // Delete all associated ports from the ports table + PortTable::iterator pBegin(m_imp->m_portTable.lower_bound(prefix)); + PortTable::iterator pEnd(m_imp->m_portTable.lower_bound(prefixEnd)); - m_imp->m_portTable.erase(pBegin, pEnd); + m_imp->m_portTable.erase(pBegin, pEnd); - // Traverse the ports array and remove all ports in the group - IsPrefix func = {prefix}; - m_imp->m_portArray.resize(std::remove_if(m_imp->m_portArray.begin(), m_imp->m_portArray.end(), func) - m_imp->m_portArray.begin()); - } + // Traverse the ports array and remove all ports in the group + IsPrefix func = {prefix}; + m_imp->m_portArray.resize(std::remove_if(m_imp->m_portArray.begin(), + m_imp->m_portArray.end(), func) - + m_imp->m_portArray.begin()); + } - dg->clear(); // Has ports ownership, so deletes them + dg->clear(); // Has ports ownership, so deletes them } //-------------------------------------------------- -bool TFx::addOutputConnection(TFxPort *port) -{ - assert(port->getFx() == this); - return m_imp->m_outputPort.insert(port).second; +bool TFx::addOutputConnection(TFxPort *port) { + assert(port->getFx() == this); + return m_imp->m_outputPort.insert(port).second; } //-------------------------------------------------- -bool TFx::removeOutputConnection(TFxPort *port) -{ - std::set::iterator it = m_imp->m_outputPort.find(port); - if (it == m_imp->m_outputPort.end()) - return false; +bool TFx::removeOutputConnection(TFxPort *port) { + std::set::iterator it = m_imp->m_outputPort.find(port); + if (it == m_imp->m_outputPort.end()) return false; - m_imp->m_outputPort.erase(it); - return true; + m_imp->m_outputPort.erase(it); + return true; } //-------------------------------------------------- -int TFx::getOutputConnectionCount() const -{ - return m_imp->m_outputPort.size(); -} +int TFx::getOutputConnectionCount() const { return m_imp->m_outputPort.size(); } //-------------------------------------------------- -TFxPort *TFx::getOutputConnection(int i) const -{ - assert(0 <= i && i <= (int)m_imp->m_outputPort.size()); - std::set::iterator it = m_imp->m_outputPort.begin(); - std::advance(it, i); - if (it == m_imp->m_outputPort.end()) - return 0; - return *it; +TFxPort *TFx::getOutputConnection(int i) const { + assert(0 <= i && i <= (int)m_imp->m_outputPort.size()); + std::set::iterator it = m_imp->m_outputPort.begin(); + std::advance(it, i); + if (it == m_imp->m_outputPort.end()) return 0; + return *it; } //-------------------------------------------------- -bool TFx::disconnect(const std::string &name) -{ - TFxPort *port = getInputPort(name); - if (!port) - return false; +bool TFx::disconnect(const std::string &name) { + TFxPort *port = getInputPort(name); + if (!port) return false; - port->setFx(0); - return true; + port->setFx(0); + return true; } //-------------------------------------------------- -bool TFx::connect(const std::string &name, TFx *fx) -{ - TFxPort *port = getInputPort(name); - if (!port) - return false; +bool TFx::connect(const std::string &name, TFx *fx) { + TFxPort *port = getInputPort(name); + if (!port) return false; - port->setFx(fx); - return true; + port->setFx(fx); + return true; } //-------------------------------------------------- -int TFx::getInputPortCount() const -{ - return m_imp->m_portArray.size(); -} +int TFx::getInputPortCount() const { return m_imp->m_portArray.size(); } //-------------------------------------------------- -TFxPort *TFx::getInputPort(int index) const -{ - assert(0 <= index && index < (int)m_imp->m_portArray.size()); - return m_imp->m_portArray[index].second; +TFxPort *TFx::getInputPort(int index) const { + assert(0 <= index && index < (int)m_imp->m_portArray.size()); + return m_imp->m_portArray[index].second; } //-------------------------------------------------- -std::string TFx::getInputPortName(int index) const -{ - assert(0 <= index && index < (int)(m_imp->m_portArray.size())); - return m_imp->m_portArray[index].first; +std::string TFx::getInputPortName(int index) const { + assert(0 <= index && index < (int)(m_imp->m_portArray.size())); + return m_imp->m_portArray[index].first; } //-------------------------------------------------- -bool TFx::renamePort(const std::string &oldName, const std::string &newName) -{ - PortTable::iterator it = m_imp->m_portTable.find(oldName); - if (it == m_imp->m_portTable.end()) - return false; +bool TFx::renamePort(const std::string &oldName, const std::string &newName) { + PortTable::iterator it = m_imp->m_portTable.find(oldName); + if (it == m_imp->m_portTable.end()) return false; - TFxPort *port = it->second; - m_imp->m_portTable.erase(it); - m_imp->m_portTable[newName] = port; + TFxPort *port = it->second; + m_imp->m_portTable.erase(it); + m_imp->m_portTable[newName] = port; - PortArray::iterator it2; - for (it2 = m_imp->m_portArray.begin(); it2 != m_imp->m_portArray.end(); ++it2) { - if (it2->first != oldName) - continue; + PortArray::iterator it2; + for (it2 = m_imp->m_portArray.begin(); it2 != m_imp->m_portArray.end(); + ++it2) { + if (it2->first != oldName) continue; - it2->first = newName; - break; - } + it2->first = newName; + break; + } - return true; + return true; } //-------------------------------------------------- -TFxPort *TFx::getInputPort(const std::string &name) const -{ - PortTable::iterator it = m_imp->m_portTable.find(name); - if (it == m_imp->m_portTable.end()) - return 0; +TFxPort *TFx::getInputPort(const std::string &name) const { + PortTable::iterator it = m_imp->m_portTable.find(name); + if (it == m_imp->m_portTable.end()) return 0; - return m_imp->m_portTable[name]; + return m_imp->m_portTable[name]; } //-------------------------------------------------- -int TFx::getReferenceColumnIndex() const -{ - if (!m_imp->m_portArray.empty()) { - TFx *fx = m_imp->m_portArray[0].second->getFx(); - if (fx) - return fx->getReferenceColumnIndex(); - } - return -1; +int TFx::getReferenceColumnIndex() const { + if (!m_imp->m_portArray.empty()) { + TFx *fx = m_imp->m_portArray[0].second->getFx(); + if (fx) return fx->getReferenceColumnIndex(); + } + return -1; } //-------------------------------------------------- -TFxTimeRegion TFx::getTimeRegion() const -{ - if (m_imp->m_portTable.empty()) - return TFxTimeRegion::createUnlimited(); - - TFxTimeRegion tr((std::numeric_limits::max)(), -(std::numeric_limits::max)()); - - PortTable::iterator it = m_imp->m_portTable.begin(); - for (; it != m_imp->m_portTable.end(); ++it) { - TFxPort *port = it->second; - if (port && port->isConnected() && !port->isaControlPort()) { - TFx *fx = port->getFx(); - assert(fx); - tr += fx->getTimeRegion(); - } - } - - return tr; -} +TFxTimeRegion TFx::getTimeRegion() const { + if (m_imp->m_portTable.empty()) return TFxTimeRegion::createUnlimited(); -//-------------------------------------------------- + TFxTimeRegion tr((std::numeric_limits::max)(), + -(std::numeric_limits::max)()); -void TFx::setActiveTimeRegion(const TFxTimeRegion &tr) -{ - m_imp->m_activeTimeRegion = tr; + PortTable::iterator it = m_imp->m_portTable.begin(); + for (; it != m_imp->m_portTable.end(); ++it) { + TFxPort *port = it->second; + if (port && port->isConnected() && !port->isaControlPort()) { + TFx *fx = port->getFx(); + assert(fx); + tr += fx->getTimeRegion(); + } + } + + return tr; } //-------------------------------------------------- -TFxTimeRegion TFx::getActiveTimeRegion() const -{ - return m_imp->m_activeTimeRegion; +void TFx::setActiveTimeRegion(const TFxTimeRegion &tr) { + m_imp->m_activeTimeRegion = tr; } //-------------------------------------------------- -void TFx::onChange(const TParamChange &c) -{ - TFxParamChange change(this, c); - notify(change); +TFxTimeRegion TFx::getActiveTimeRegion() const { + return m_imp->m_activeTimeRegion; } //-------------------------------------------------- -void TFx::addObserver(TFxObserver *obs) -{ - m_imp->m_observers.insert(obs); +void TFx::onChange(const TParamChange &c) { + TFxParamChange change(this, c); + notify(change); } //-------------------------------------------------- -void TFx::removeObserver(TFxObserver *obs) -{ - m_imp->m_observers.erase(obs); -} +void TFx::addObserver(TFxObserver *obs) { m_imp->m_observers.insert(obs); } //-------------------------------------------------- -void TFx::notify(const TFxChange &change) -{ - for (std::set::iterator it = m_imp->m_observers.begin(); - it != m_imp->m_observers.end(); ++it) - (*it)->onChange(change); -} +void TFx::removeObserver(TFxObserver *obs) { m_imp->m_observers.erase(obs); } //-------------------------------------------------- -void TFx::notify(const TFxPortAdded &change) -{ - for (std::set::iterator it = m_imp->m_observers.begin(); - it != m_imp->m_observers.end(); ++it) - (*it)->onChange(change); +void TFx::notify(const TFxChange &change) { + for (std::set::iterator it = m_imp->m_observers.begin(); + it != m_imp->m_observers.end(); ++it) + (*it)->onChange(change); } //-------------------------------------------------- -void TFx::notify(const TFxPortRemoved &change) -{ - for (std::set::iterator it = m_imp->m_observers.begin(); - it != m_imp->m_observers.end(); ++it) - (*it)->onChange(change); +void TFx::notify(const TFxPortAdded &change) { + for (std::set::iterator it = m_imp->m_observers.begin(); + it != m_imp->m_observers.end(); ++it) + (*it)->onChange(change); } //-------------------------------------------------- -void TFx::notify(const TFxParamAdded &change) -{ - for (std::set::iterator it = m_imp->m_observers.begin(); - it != m_imp->m_observers.end(); ++it) - (*it)->onChange(change); +void TFx::notify(const TFxPortRemoved &change) { + for (std::set::iterator it = m_imp->m_observers.begin(); + it != m_imp->m_observers.end(); ++it) + (*it)->onChange(change); } //-------------------------------------------------- -void TFx::notify(const TFxParamRemoved &change) -{ - for (std::set::iterator it = m_imp->m_observers.begin(); - it != m_imp->m_observers.end(); ++it) - (*it)->onChange(change); +void TFx::notify(const TFxParamAdded &change) { + for (std::set::iterator it = m_imp->m_observers.begin(); + it != m_imp->m_observers.end(); ++it) + (*it)->onChange(change); } //-------------------------------------------------- -unsigned long TFx::getIdentifier() const -{ - return m_imp->m_id; +void TFx::notify(const TFxParamRemoved &change) { + for (std::set::iterator it = m_imp->m_observers.begin(); + it != m_imp->m_observers.end(); ++it) + (*it)->onChange(change); } //-------------------------------------------------- -void TFx::setIdentifier(unsigned long id) -{ - m_imp->m_id = id; -} +unsigned long TFx::getIdentifier() const { return m_imp->m_id; } //-------------------------------------------------- -void TFx::setNewIdentifier() -{ - m_imp->m_id = ++m_imp->m_nextId; -} +void TFx::setIdentifier(unsigned long id) { m_imp->m_id = id; } //-------------------------------------------------- -void TFx::loadData(TIStream &is) -{ - std::string tagName; - VersionNumber tnzVersion = is.getVersion(); - - QList groupIds; - QList groupNames; - while (is.openChild(tagName)) { - if (tagName == "params") { - while (!is.eos()) { - std::string paramName; - while (is.openChild(paramName)) { - TParamP param = getParams()->getParam(paramName); - if (param) - param->loadData(is); - else // il parametro non e' presente -> skip - skipChild(is); - - is.closeChild(); - } - } - } else if (tagName == "paramsLinkedTo") { - TPersist *p = 0; - is >> p; - TFx *fx = dynamic_cast(p); - if (fx == 0) - throw TException("Missing linkedSetRoot"); - linkParams(fx); - } else if (tagName == "ports") { - std::string portName; - while (!is.eos()) { - while (is.openChild(portName)) { - VersionNumber version = is.getVersion(); - compatibilityTranslatePort(version.first, version.second, portName); - - // Try to find the specified port - TFxPort *port = getInputPort(portName); - if (!port) { - // Scan dynamic port groups for a containing one - add a port there if found - int g, gCount = dynamicPortGroupsCount(); - for (g = 0; g != gCount; ++g) { - TFxPortDG *group = const_cast(dynamicPortGroup(g)); - - if (group->contains(portName)) { - addInputPort(portName, port = new TRasterFxPort, g); - break; - } - } - } - - // Could not find (or add) a port with the corresponding name - throw - if (!port) - throw TException(std::string("port '") + portName + "' is not present"); - - if (!is.eos()) { - TPersist *p = 0; - is >> p; - TFx *fx = dynamic_cast(p); - port->setFx(fx); - } - - is.closeChild(); - } - } - } else if (tagName == "dagNodePos") { - TPointD p; - is >> p.x >> p.y; - m_imp->m_attributes.setDagNodePos(updateDagPosition(p, tnzVersion)); - } else if (tagName == "numberId") { - int numberId = 0; - is >> numberId; - m_imp->m_attributes.setId(numberId); - } else if (tagName == "passiveCacheId") { - int passiveCacheId = 0; - is >> passiveCacheId; - - assert(passiveCacheId > 0); - TPassiveCacheManager::instance()->declareCached(this, passiveCacheId); - } else if (tagName == "name") { - // passo attraverso un filepath solo per evitare i problemi di blank - // o caratteri strani dentro il nome (sospetto che tfilepath sia gestito - // correttamente mentre wstring no - TFilePath tmp; - is >> tmp; - setName(tmp.getWideName()); - } else if (tagName == "fxId") { - TFilePath tmp; - is >> tmp; - setFxId(tmp.getWideName()); - } else if (tagName == "enabled") { - int flag = 1; - is >> flag; - m_imp->m_attributes.enable(flag != 0); - } else if (tagName == "opened") { - int opened = 1; - is >> opened; - m_imp->m_attributes.setIsOpened(opened); - } else if (tagName == "groupIds") { - int groupId; - while (!is.eos()) { - is >> groupId; - groupIds.append(groupId); - } - } else if (tagName == "groupNames") { - std::wstring groupName; - while (!is.eos()) { - is >> groupName; - groupNames.append(groupName); - } - } else { - throw TException("Unknown tag!"); - } - is.closeChild(); - } - if (!groupIds.isEmpty()) { - assert(groupIds.size() == groupNames.size()); - int i; - for (i = 0; i < groupIds.size(); i++) { - m_imp->m_attributes.setGroupId(groupIds[i]); - m_imp->m_attributes.setGroupName(groupNames[i]); - } - } -} +void TFx::setNewIdentifier() { m_imp->m_id = ++m_imp->m_nextId; } //-------------------------------------------------- -void TFx::saveData(TOStream &os) -{ - TFx *linkedSetRoot = this; - if (m_imp->m_next != m_imp) { - TFxImp *imp = m_imp->m_next; - int guard = 0; - while (guard++ < 1000 && imp != m_imp) { - if (imp->m_fx < linkedSetRoot) - linkedSetRoot = imp->m_fx; - imp = imp->m_next; - } - assert(imp == m_imp); - assert(linkedSetRoot); - } - if (linkedSetRoot == this) { - os.openChild("params"); - for (int i = 0; i < getParams()->getParamCount(); i++) { - std::string paramName = getParams()->getParamName(i); - TParam *param = getParams()->getParam(i); - os.openChild(paramName); - param->saveData(os); - os.closeChild(); - } - os.closeChild(); - } else { - os.openChild("paramsLinkedTo"); - os << linkedSetRoot; - os.closeChild(); - } - - os.openChild("ports"); - for (PortTable::iterator pit = m_imp->m_portTable.begin(); - pit != m_imp->m_portTable.end(); ++pit) { - os.openChild(pit->first); - if (pit->second->isConnected()) - os << TFxP(pit->second->getFx()).getPointer(); - os.closeChild(); - } - os.closeChild(); - - TPointD p = m_imp->m_attributes.getDagNodePos(); - if (p != TConst::nowhere) - os.child("dagNodePos") << p.x << p.y; - int numberId = m_imp->m_attributes.getId(); - os.child("numberId") << numberId; - bool cacheEnabled = TPassiveCacheManager::instance()->cacheEnabled(this); - if (cacheEnabled) - os.child("passiveCacheId") << TPassiveCacheManager::instance()->getPassiveCacheId(this); - std::wstring name = getName(); - if (name != L"") - os.child("name") << TFilePath(name); - std::wstring fxId = getFxId(); - os.child("fxId") << fxId; - if (!m_imp->m_attributes.isEnabled()) - os.child("enabled") << 0; - os.child("opened") << (int)m_imp->m_attributes.isOpened(); - if (m_imp->m_attributes.isGrouped()) { - os.openChild("groupIds"); - QStack groupIdStack = m_imp->m_attributes.getGroupIdStack(); - int i; - for (i = 0; i < groupIdStack.size(); i++) - os << groupIdStack[i]; - os.closeChild(); - os.openChild("groupNames"); - QStack groupNameStack = m_imp->m_attributes.getGroupNameStack(); - for (i = 0; i < groupNameStack.size(); i++) - os << groupNameStack[i]; - os.closeChild(); - } -} +void TFx::loadData(TIStream &is) { + std::string tagName; + VersionNumber tnzVersion = is.getVersion(); -//-------------------------------------------------- + QList groupIds; + QList groupNames; + while (is.openChild(tagName)) { + if (tagName == "params") { + while (!is.eos()) { + std::string paramName; + while (is.openChild(paramName)) { + TParamP param = getParams()->getParam(paramName); + if (param) + param->loadData(is); + else // il parametro non e' presente -> skip + skipChild(is); -void TFx::loadPreset(TIStream &is) -{ - std::string tagName; - while (is.openChild(tagName)) { - if (tagName == "dvpreset") { - std::string fxId = is.getTagAttribute("fxId"); - if (fxId != getFxType()) - throw TException("Preset doesn't match the fx type"); - } else if (tagName == "params") { - while (!is.eos()) { - std::string paramName; - while (is.openChild(paramName)) { - try { - TParamP param = getParams()->getParam(paramName); - param->loadData(is); - } catch (TException &) { /*skip*/ - } // il parametro non e' presente - is.closeChild(); - } - } - } else { - throw TException("Fx preset unknown tag!"); - } - } + is.closeChild(); + } + } + } else if (tagName == "paramsLinkedTo") { + TPersist *p = 0; + is >> p; + TFx *fx = dynamic_cast(p); + if (fx == 0) throw TException("Missing linkedSetRoot"); + linkParams(fx); + } else if (tagName == "ports") { + std::string portName; + while (!is.eos()) { + while (is.openChild(portName)) { + VersionNumber version = is.getVersion(); + compatibilityTranslatePort(version.first, version.second, portName); + + // Try to find the specified port + TFxPort *port = getInputPort(portName); + if (!port) { + // Scan dynamic port groups for a containing one - add a port there + // if found + int g, gCount = dynamicPortGroupsCount(); + for (g = 0; g != gCount; ++g) { + TFxPortDG *group = const_cast(dynamicPortGroup(g)); + + if (group->contains(portName)) { + addInputPort(portName, port = new TRasterFxPort, g); + break; + } + } + } + + // Could not find (or add) a port with the corresponding name - throw + if (!port) + throw TException(std::string("port '") + portName + + "' is not present"); + + if (!is.eos()) { + TPersist *p = 0; + is >> p; + TFx *fx = dynamic_cast(p); + port->setFx(fx); + } + + is.closeChild(); + } + } + } else if (tagName == "dagNodePos") { + TPointD p; + is >> p.x >> p.y; + m_imp->m_attributes.setDagNodePos(updateDagPosition(p, tnzVersion)); + } else if (tagName == "numberId") { + int numberId = 0; + is >> numberId; + m_imp->m_attributes.setId(numberId); + } else if (tagName == "passiveCacheId") { + int passiveCacheId = 0; + is >> passiveCacheId; + + assert(passiveCacheId > 0); + TPassiveCacheManager::instance()->declareCached(this, passiveCacheId); + } else if (tagName == "name") { + // passo attraverso un filepath solo per evitare i problemi di blank + // o caratteri strani dentro il nome (sospetto che tfilepath sia gestito + // correttamente mentre wstring no + TFilePath tmp; + is >> tmp; + setName(tmp.getWideName()); + } else if (tagName == "fxId") { + TFilePath tmp; + is >> tmp; + setFxId(tmp.getWideName()); + } else if (tagName == "enabled") { + int flag = 1; + is >> flag; + m_imp->m_attributes.enable(flag != 0); + } else if (tagName == "opened") { + int opened = 1; + is >> opened; + m_imp->m_attributes.setIsOpened(opened); + } else if (tagName == "groupIds") { + int groupId; + while (!is.eos()) { + is >> groupId; + groupIds.append(groupId); + } + } else if (tagName == "groupNames") { + std::wstring groupName; + while (!is.eos()) { + is >> groupName; + groupNames.append(groupName); + } + } else { + throw TException("Unknown tag!"); + } + is.closeChild(); + } + if (!groupIds.isEmpty()) { + assert(groupIds.size() == groupNames.size()); + int i; + for (i = 0; i < groupIds.size(); i++) { + m_imp->m_attributes.setGroupId(groupIds[i]); + m_imp->m_attributes.setGroupName(groupNames[i]); + } + } +} + +//-------------------------------------------------- + +void TFx::saveData(TOStream &os) { + TFx *linkedSetRoot = this; + if (m_imp->m_next != m_imp) { + TFxImp *imp = m_imp->m_next; + int guard = 0; + while (guard++ < 1000 && imp != m_imp) { + if (imp->m_fx < linkedSetRoot) linkedSetRoot = imp->m_fx; + imp = imp->m_next; + } + assert(imp == m_imp); + assert(linkedSetRoot); + } + if (linkedSetRoot == this) { + os.openChild("params"); + for (int i = 0; i < getParams()->getParamCount(); i++) { + std::string paramName = getParams()->getParamName(i); + TParam *param = getParams()->getParam(i); + os.openChild(paramName); + param->saveData(os); + os.closeChild(); + } + os.closeChild(); + } else { + os.openChild("paramsLinkedTo"); + os << linkedSetRoot; + os.closeChild(); + } + + os.openChild("ports"); + for (PortTable::iterator pit = m_imp->m_portTable.begin(); + pit != m_imp->m_portTable.end(); ++pit) { + os.openChild(pit->first); + if (pit->second->isConnected()) + os << TFxP(pit->second->getFx()).getPointer(); + os.closeChild(); + } + os.closeChild(); + + TPointD p = m_imp->m_attributes.getDagNodePos(); + if (p != TConst::nowhere) os.child("dagNodePos") << p.x << p.y; + int numberId = m_imp->m_attributes.getId(); + os.child("numberId") << numberId; + bool cacheEnabled = TPassiveCacheManager::instance()->cacheEnabled(this); + if (cacheEnabled) + os.child("passiveCacheId") + << TPassiveCacheManager::instance()->getPassiveCacheId(this); + std::wstring name = getName(); + if (name != L"") os.child("name") << TFilePath(name); + std::wstring fxId = getFxId(); + os.child("fxId") << fxId; + if (!m_imp->m_attributes.isEnabled()) os.child("enabled") << 0; + os.child("opened") << (int)m_imp->m_attributes.isOpened(); + if (m_imp->m_attributes.isGrouped()) { + os.openChild("groupIds"); + QStack groupIdStack = m_imp->m_attributes.getGroupIdStack(); + int i; + for (i = 0; i < groupIdStack.size(); i++) os << groupIdStack[i]; + os.closeChild(); + os.openChild("groupNames"); + QStack groupNameStack = + m_imp->m_attributes.getGroupNameStack(); + for (i = 0; i < groupNameStack.size(); i++) os << groupNameStack[i]; + os.closeChild(); + } +} + +//-------------------------------------------------- + +void TFx::loadPreset(TIStream &is) { + std::string tagName; + while (is.openChild(tagName)) { + if (tagName == "dvpreset") { + std::string fxId = is.getTagAttribute("fxId"); + if (fxId != getFxType()) + throw TException("Preset doesn't match the fx type"); + } else if (tagName == "params") { + while (!is.eos()) { + std::string paramName; + while (is.openChild(paramName)) { + try { + TParamP param = getParams()->getParam(paramName); + param->loadData(is); + } catch (TException &) { /*skip*/ + } // il parametro non e' presente + is.closeChild(); + } + } + } else { + throw TException("Fx preset unknown tag!"); + } + } } //-------------------------------------------------- -void TFx::savePreset(TOStream &os) -{ - std::map attributes; - attributes.insert(std::make_pair(std::string("ver"), std::string("1.0"))); - attributes.insert(std::make_pair(std::string("fxId"), getFxType())); - - os.openChild("dvpreset", attributes); - - os.openChild("params"); - for (int i = 0; i < getParams()->getParamCount(); i++) { - std::string paramName = getParams()->getParamName(i); - TParam *param = getParams()->getParam(i); - os.openChild(paramName); - param->saveData(os); - os.closeChild(); - } - os.closeChild(); - - os.closeChild(); +void TFx::savePreset(TOStream &os) { + std::map attributes; + attributes.insert(std::make_pair(std::string("ver"), std::string("1.0"))); + attributes.insert(std::make_pair(std::string("fxId"), getFxType())); + + os.openChild("dvpreset", attributes); + + os.openChild("params"); + for (int i = 0; i < getParams()->getParamCount(); i++) { + std::string paramName = getParams()->getParamName(i); + TParam *param = getParams()->getParam(i); + os.openChild(paramName); + param->saveData(os); + os.closeChild(); + } + os.closeChild(); + + os.closeChild(); } //-------------------------------------------------- -void TFx::disconnectAll() -{ - int p, pCount = getInputPortCount(); - for (p = 0; p != pCount; ++p) - getInputPort(p)->setFx(0); +void TFx::disconnectAll() { + int p, pCount = getInputPortCount(); + for (p = 0; p != pCount; ++p) getInputPort(p)->setFx(0); } //-------------------------------------------------- -TFx *TFx::create(std::string name) -{ - return TFxFactory::instance()->create(name); +TFx *TFx::create(std::string name) { + return TFxFactory::instance()->create(name); } //-------------------------------------------------- -void TFx::listFxs(std::vector &info) -{ - TFxFactory::instance()->getFxInfos(info); +void TFx::listFxs(std::vector &info) { + TFxFactory::instance()->getFxInfos(info); } //-------------------------------------------------- -TFxInfo TFx::getFxInfo(const std::string &fxIdentifier) -{ - return TFxFactory::instance()->getFxInfo(fxIdentifier); +TFxInfo TFx::getFxInfo(const std::string &fxIdentifier) { + return TFxFactory::instance()->getFxInfo(fxIdentifier); } //-------------------------------------------------- -TFx *TFx::getLinkedFx() const -{ - assert(m_imp->m_next); - assert(m_imp->m_next->m_prev == m_imp); - assert(m_imp->m_next->m_fx != 0); - return m_imp->m_next->m_fx; +TFx *TFx::getLinkedFx() const { + assert(m_imp->m_next); + assert(m_imp->m_next->m_prev == m_imp); + assert(m_imp->m_next->m_fx != 0); + return m_imp->m_next->m_fx; } //=================================================== @@ -1102,74 +982,58 @@ TFx *TFx::getLinkedFx() const //! Creates an unlimited time region. TFxTimeRegion::TFxTimeRegion() - : m_start((std::numeric_limits::max)()), m_end(-(std::numeric_limits::max)()) -{ -} + : m_start((std::numeric_limits::max)()) + , m_end(-(std::numeric_limits::max)()) {} //-------------------------------------------------- //! Creates a time region with specified start (included) and end (\b excluded). TFxTimeRegion::TFxTimeRegion(double start, double end) - : m_start(start), m_end(end) -{ -} + : m_start(start), m_end(end) {} //-------------------------------------------------- -TFxTimeRegion TFxTimeRegion::createUnlimited() -{ - return TFxTimeRegion( - -(std::numeric_limits::max)(), - (std::numeric_limits::max)()); +TFxTimeRegion TFxTimeRegion::createUnlimited() { + return TFxTimeRegion(-(std::numeric_limits::max)(), + (std::numeric_limits::max)()); } //-------------------------------------------------- -bool TFxTimeRegion::contains(double time) const -{ - return (m_start <= time && time < m_end); +bool TFxTimeRegion::contains(double time) const { + return (m_start <= time && time < m_end); } //-------------------------------------------------- -bool TFxTimeRegion::isUnlimited() const -{ - return (m_start == -(std::numeric_limits::max)() || - m_end == (std::numeric_limits::max)()); +bool TFxTimeRegion::isUnlimited() const { + return (m_start == -(std::numeric_limits::max)() || + m_end == (std::numeric_limits::max)()); } //-------------------------------------------------- -bool TFxTimeRegion::isEmpty() const -{ - return (m_end <= m_start); -} +bool TFxTimeRegion::isEmpty() const { return (m_end <= m_start); } //-------------------------------------------------- -bool TFxTimeRegion::getFrameCount(int &count) const -{ - if (isUnlimited()) - return false; - count = tfloor(m_end) - tceil(m_start); - return true; +bool TFxTimeRegion::getFrameCount(int &count) const { + if (isUnlimited()) return false; + count = tfloor(m_end) - tceil(m_start); + return true; } //-------------------------------------------------- -int TFxTimeRegion::getFirstFrame() const -{ - return tceil(m_start); -} +int TFxTimeRegion::getFirstFrame() const { return tceil(m_start); } //-------------------------------------------------- -int TFxTimeRegion::getLastFrame() const -{ - if (m_end == (std::numeric_limits::max)()) - return (std::numeric_limits::max)(); - else - return tceil(m_end) - 1; +int TFxTimeRegion::getLastFrame() const { + if (m_end == (std::numeric_limits::max)()) + return (std::numeric_limits::max)(); + else + return tceil(m_end) - 1; } //=================================================== diff --git a/toonz/sources/common/tfx/tfxcachemanager.cpp b/toonz/sources/common/tfx/tfxcachemanager.cpp index 9a6bb76..ef567e7 100644 --- a/toonz/sources/common/tfx/tfxcachemanager.cpp +++ b/toonz/sources/common/tfx/tfxcachemanager.cpp @@ -7,7 +7,7 @@ #include "tfxcachemanager.h" -//Debug +// Debug //#define DIAGNOSTICS #ifdef DIAGNOSTICS @@ -17,18 +17,16 @@ //#define WRITESUBRECTS //#define WRITEGENERAL -namespace -{ -QString traduce(const TRectD &rect) -{ - return "[" + QString::number(rect.x0) + " " + QString::number(rect.y0) + " " + QString::number(rect.x1) + " " + QString::number(rect.y1) + "]"; +namespace { +QString traduce(const TRectD &rect) { + return "[" + QString::number(rect.x0) + " " + QString::number(rect.y0) + " " + + QString::number(rect.x1) + " " + QString::number(rect.y1) + "]"; } -QString traduce(const TTile &tile) -{ - TDimension dim(tile.getRaster()->getSize()); - TRectD tileRect(tile.m_pos, TDimensionD(dim.lx, dim.ly)); - return traduce(tileRect); +QString traduce(const TTile &tile) { + TDimension dim(tile.getRaster()->getSize()); + TRectD tileRect(tile.m_pos, TDimensionD(dim.lx, dim.ly)); + return traduce(tileRect); } QString prefixInfo("#info.txt | "); @@ -39,32 +37,40 @@ QString prefixComp("#Computing.txt | "); QString prefixSubTiles("#SubTiles.txt | "); } -#endif //DIAGNOSTICS +#endif // DIAGNOSTICS //**************************************************************************************************** // Explanation //**************************************************************************************************** /* -This file contains most of the code that deals with smart caching during a Toonz render process. +This file contains most of the code that deals with smart caching during a Toonz +render process. The paradigms on which the 'smart caching' takes place are: - - Only calculations resulting in an image positioned in a plane are dealt. These results are + - Only calculations resulting in an image positioned in a plane are dealt. +These results are called 'tiles' - and are modeled by a TTile instance. - These images MUST BE wrapped to INTEGER POSITIONS on the reference, and are intended so that + These images MUST BE wrapped to INTEGER POSITIONS on the reference, and are +intended so that a PIXEL corresponds to a UNIT SQUARE. - - Given one such calculation procedure, it MUST BE SIMULABLE, so that children calculations + - Given one such calculation procedure, it MUST BE SIMULABLE, so that children +calculations are invoked 'faithfully' with respect to the actual calculation. - This is necessary to predict results in advance in force of which we can efficiently store + This is necessary to predict results in advance in force of which we can +efficiently store results in the cache, releasing them when they will no longer be required. Now, the principal classes dealing with this job are: - - One TFxCacheManager per render instance, used to store predictive informations. - - A set of TFxCacheManagerDelegate per render instance, used to store references to cache resources + - One TFxCacheManager per render instance, used to store predictive +informations. + - A set of TFxCacheManagerDelegate per render instance, used to store +references to cache resources and providing reasons for caching results. - - The ResourceBuilder interface class, used by users to access the smart caching ensemble. This class + - The ResourceBuilder interface class, used by users to access the smart +caching ensemble. This class implements the actual resources build and simulation code. */ @@ -73,46 +79,49 @@ Now, the principal classes dealing with this job are: // Preliminaries //**************************************************************************************************** -namespace -{ -//Global variables +namespace { +// Global variables //----------------------------------------------------------------------------------------- -//Utility functions +// Utility functions -inline QRect toQRect(const TRect &r) { return QRect(r.x0, r.y0, r.getLx(), r.getLy()); } -inline TRect toTRect(const QRect &r) { return TRect(r.left(), r.top(), r.right(), r.bottom()); } +inline QRect toQRect(const TRect &r) { + return QRect(r.x0, r.y0, r.getLx(), r.getLy()); +} +inline TRect toTRect(const QRect &r) { + return TRect(r.left(), r.top(), r.right(), r.bottom()); +} inline QPoint toQPoint(const TPoint &p) { return QPoint(p.x, p.y); } -inline bool isEmpty(const TRectD &rect) { return rect.x0 >= rect.x1 || rect.y0 >= rect.y1; } -inline void enlargeToI(TRectD &r) -{ - TRectD temp(tfloor(r.x0), tfloor(r.y0), tceil(r.x1), tceil(r.y1)); - if (!isEmpty(temp)) - r = temp; //Since r could have TConsts::infiniteRectD-like coordinates... +inline bool isEmpty(const TRectD &rect) { + return rect.x0 >= rect.x1 || rect.y0 >= rect.y1; +} +inline void enlargeToI(TRectD &r) { + TRectD temp(tfloor(r.x0), tfloor(r.y0), tceil(r.x1), tceil(r.y1)); + if (!isEmpty(temp)) + r = temp; // Since r could have TConsts::infiniteRectD-like coordinates... } -//Qt's contains actually returns QRegion::intersected... I wonder why... -inline bool contains(const QRegion ®ion, const TRect &rect) -{ - return QRegion(toQRect(rect)).subtracted(region).isEmpty(); +// Qt's contains actually returns QRegion::intersected... I wonder why... +inline bool contains(const QRegion ®ion, const TRect &rect) { + return QRegion(toQRect(rect)).subtracted(region).isEmpty(); } -bool getTilesToBuild(const ResourceData &data, const TRectD &rect, - std::vector &rectsToCalculate); +bool getTilesToBuild( + const ResourceData &data, const TRectD &rect, + std::vector &rectsToCalculate); } //**************************************************************************************************** // TFxCacheManager Generator //**************************************************************************************************** -class TFxCacheManagerGenerator : public TRenderResourceManagerGenerator -{ +class TFxCacheManagerGenerator : public TRenderResourceManagerGenerator { public: - TFxCacheManagerGenerator() : TRenderResourceManagerGenerator(true) {} + TFxCacheManagerGenerator() : TRenderResourceManagerGenerator(true) {} - TRenderResourceManager *operator()() { return new TFxCacheManager; } + TRenderResourceManager *operator()() { return new TFxCacheManager; } }; MANAGER_FILESCOPE_DECLARATION(TFxCacheManager, TFxCacheManagerGenerator); @@ -121,24 +130,24 @@ MANAGER_FILESCOPE_DECLARATION(TFxCacheManager, TFxCacheManagerGenerator); // TFxCacheManager implementation //**************************************************************************************************** -class TFxCacheManager::Imp -{ +class TFxCacheManager::Imp { public: - typedef std::map ResourceInstanceDataMap; + typedef std::map ResourceInstanceDataMap; - ResourceInstanceDataMap m_resourcesData; - std::map m_rawData; - int m_renderStatus; + ResourceInstanceDataMap m_resourcesData; + std::map m_rawData; + int m_renderStatus; - QMutex m_mutex; + QMutex m_mutex; public: - void prepareTilesToCalculate(ResourceDeclaration &data); - inline void subdivideIntoSmallerTiles(const TRectD &rect, std::vector &tileSet); - void recursiveRectSubdivide( - std::vector &results, TRasterFx *fx, - const TRectD &rect, double frame, const TRenderSettings &info, - int dropTol = (std::numeric_limits::max)()); + void prepareTilesToCalculate(ResourceDeclaration &data); + inline void subdivideIntoSmallerTiles(const TRectD &rect, + std::vector &tileSet); + void recursiveRectSubdivide( + std::vector &results, TRasterFx *fx, + const TRectD &rect, double frame, const TRenderSettings &info, + int dropTol = (std::numeric_limits::max)()); }; //**************************************************************************************************** @@ -149,54 +158,46 @@ public: // TFxCacheManager //------------------------ -TFxCacheManager::TFxCacheManager() - : m_imp(new Imp) -{ -} +TFxCacheManager::TFxCacheManager() : m_imp(new Imp) {} //----------------------------------------------------------------------------------- -TFxCacheManager::~TFxCacheManager() -{ - //Release all the static-cached images - std::set::iterator it; - for (it = m_staticCacheIds.begin(); it != m_staticCacheIds.end(); ++it) - TImageCache::instance()->remove(*it); +TFxCacheManager::~TFxCacheManager() { + // Release all the static-cached images + std::set::iterator it; + for (it = m_staticCacheIds.begin(); it != m_staticCacheIds.end(); ++it) + TImageCache::instance()->remove(*it); } //----------------------------------------------------------------------------------- -TFxCacheManager *TFxCacheManager::instance() -{ - return static_cast( - TFxCacheManager::gen()->getManager(TRenderer::renderId())); +TFxCacheManager *TFxCacheManager::instance() { + return static_cast( + TFxCacheManager::gen()->getManager(TRenderer::renderId())); } //----------------------------------------------------------------------------------- -void TFxCacheManager::add(const std::string &cacheId, TImageP img) -{ - TImageCache::instance()->add(cacheId, img); +void TFxCacheManager::add(const std::string &cacheId, TImageP img) { + TImageCache::instance()->add(cacheId, img); - QMutexLocker locker(&m_imp->m_mutex); - m_staticCacheIds.insert(cacheId); + QMutexLocker locker(&m_imp->m_mutex); + m_staticCacheIds.insert(cacheId); } //----------------------------------------------------------------------------------- -void TFxCacheManager::remove(const std::string &cacheId) -{ - TImageCache::instance()->remove(cacheId); +void TFxCacheManager::remove(const std::string &cacheId) { + TImageCache::instance()->remove(cacheId); - QMutexLocker locker(&m_imp->m_mutex); - m_staticCacheIds.erase(cacheId); + QMutexLocker locker(&m_imp->m_mutex); + m_staticCacheIds.erase(cacheId); } //----------------------------------------------------------------------------------- -void TFxCacheManager::install(TFxCacheManagerDelegate *managerDelegate) -{ - m_delegates.insert(managerDelegate); +void TFxCacheManager::install(TFxCacheManagerDelegate *managerDelegate) { + m_delegates.insert(managerDelegate); } //----------------------------------------------------------------------------------- @@ -208,7 +209,8 @@ void TFxCacheManager::install(TFxCacheManagerDelegate *managerDelegate) //----------------------------------------------------------------------------------- -void TFxCacheManager::notifyResourceUpload(const TCacheResourceP& resource, const TRect& rect) +void TFxCacheManager::notifyResourceUpload(const TCacheResourceP& resource, +const TRect& rect) { std::set::iterator it; for(it = m_listeners.begin(); it != m_listeners.end(); ++it) @@ -217,7 +219,8 @@ void TFxCacheManager::notifyResourceUpload(const TCacheResourceP& resource, cons //----------------------------------------------------------------------------------- -void TFxCacheManager::notifyResourceDownload(const TCacheResourceP& resource, const TRect& rect) +void TFxCacheManager::notifyResourceDownload(const TCacheResourceP& resource, +const TRect& rect) { std::set::iterator it; for(it = m_listeners.begin(); it != m_listeners.end(); ++it) @@ -237,141 +240,154 @@ void TFxCacheManager::notifyPredictedRelease(const TCacheResourceP& resource) // Resources dealing //**************************************************************************************************** -void TFxCacheManager::declareResource( - const std::string &alias, const TFxP &fx, - const TRectD &rect, double frame, const TRenderSettings &rs, - bool subtileable) -{ - Imp::ResourceInstanceDataMap::iterator it; - it = m_imp->m_resourcesData.insert(std::make_pair(alias, ResourceDeclaration())).first; - it->second.m_rawData = - &m_imp->m_rawData.insert(std::make_pair(&it->second, ResourceDeclaration::RawData())).first->second; - - ResourceDeclaration::RawData &rawData = *it->second.m_rawData; - - //Assign the sim data - rawData.m_fx = fx; - rawData.m_tiles.push_back(rect); - rawData.m_rs = rs; - rawData.m_frame = frame; - //rawData.m_bbox = bbox; - rawData.m_subtileable = subtileable; +void TFxCacheManager::declareResource(const std::string &alias, const TFxP &fx, + const TRectD &rect, double frame, + const TRenderSettings &rs, + bool subtileable) { + Imp::ResourceInstanceDataMap::iterator it; + it = m_imp->m_resourcesData + .insert(std::make_pair(alias, ResourceDeclaration())) + .first; + it->second.m_rawData = + &m_imp->m_rawData + .insert(std::make_pair(&it->second, ResourceDeclaration::RawData())) + .first->second; + + ResourceDeclaration::RawData &rawData = *it->second.m_rawData; + + // Assign the sim data + rawData.m_fx = fx; + rawData.m_tiles.push_back(rect); + rawData.m_rs = rs; + rawData.m_frame = frame; + // rawData.m_bbox = bbox; + rawData.m_subtileable = subtileable; } //----------------------------------------------------------------------------------- -ResourceData TFxCacheManager::getResource( - const std::string &alias, - const TFxP &fx, double frame, const TRenderSettings &rs) -{ - TCacheResourceP result, temp; +ResourceData TFxCacheManager::getResource(const std::string &alias, + const TFxP &fx, double frame, + const TRenderSettings &rs) { + TCacheResourceP result, temp; - //Seek the associated infos - Imp::ResourceInstanceDataMap::iterator jt = - m_imp->m_resourcesData.find(alias); - ResourceDeclaration *decl = (jt == m_imp->m_resourcesData.end()) ? 0 : &jt->second; + // Seek the associated infos + Imp::ResourceInstanceDataMap::iterator jt = + m_imp->m_resourcesData.find(alias); + ResourceDeclaration *decl = + (jt == m_imp->m_resourcesData.end()) ? 0 : &jt->second; - //Search the resource in cached mode. - //TCacheResourcePool* pool = TCacheResourcePool::instance(); - //pool->beginCachedSearch(); + // Search the resource in cached mode. + // TCacheResourcePool* pool = TCacheResourcePool::instance(); + // pool->beginCachedSearch(); - //Ask every installed delegate if it's managing - or want to manage - //the passed resource specs. - std::set::iterator it; - for (it = m_delegates.begin(); it != m_delegates.end(); ++it) { - (*it)->getResource(temp, alias, fx, frame, rs, decl); - if (!result && temp) - result = temp; - } + // Ask every installed delegate if it's managing - or want to manage + // the passed resource specs. + std::set::iterator it; + for (it = m_delegates.begin(); it != m_delegates.end(); ++it) { + (*it)->getResource(temp, alias, fx, frame, rs, decl); + if (!result && temp) result = temp; + } - //pool->endCachedSearch(); + // pool->endCachedSearch(); - return ResourceData(decl, result); + return ResourceData(decl, result); } //----------------------------------------------------------------------------------- -void TFxCacheManager::onRenderStatusStart(int renderStatus) -{ - //Store current render status - m_imp->m_renderStatus = renderStatus; +void TFxCacheManager::onRenderStatusStart(int renderStatus) { + // Store current render status + m_imp->m_renderStatus = renderStatus; #ifdef WRITESTACK - if (renderStatus == TRenderer::TESTRUN) { - DIAGNOSTICS_GLOSTRSET("status", "test"); - DIAGNOSTICS_GLOSET("testInst", DIAGNOSTICS_GLOGET("compInst") + 1); - DIAGNOSTICS_GLOSTRSET("instVar", QString::number(DIAGNOSTICS_GLOGET("testInst"))); - DIAGNOSTICS_GLOSTRSET("testRenderStr", "Render #" + QString::number(DIAGNOSTICS_GLOGET("testInst")) + " | "); - } else if (renderStatus == TRenderer::COMPUTING) { - DIAGNOSTICS_GLOSTRSET("status", "comp"); - DIAGNOSTICS_GLOSTRSET("instVar", QString::number(DIAGNOSTICS_GLOGET("compInst"))); - DIAGNOSTICS_GLOSTRSET("compRenderStr", "Render #" + QString::number(DIAGNOSTICS_GLOGET("compInst")) + " | "); - DIAGNOSTICS_GLOSET(DIAGNOSTICS_THRSTRGET("stackVar"), 0); - } + if (renderStatus == TRenderer::TESTRUN) { + DIAGNOSTICS_GLOSTRSET("status", "test"); + DIAGNOSTICS_GLOSET("testInst", DIAGNOSTICS_GLOGET("compInst") + 1); + DIAGNOSTICS_GLOSTRSET("instVar", + QString::number(DIAGNOSTICS_GLOGET("testInst"))); + DIAGNOSTICS_GLOSTRSET( + "testRenderStr", + "Render #" + QString::number(DIAGNOSTICS_GLOGET("testInst")) + " | "); + } else if (renderStatus == TRenderer::COMPUTING) { + DIAGNOSTICS_GLOSTRSET("status", "comp"); + DIAGNOSTICS_GLOSTRSET("instVar", + QString::number(DIAGNOSTICS_GLOGET("compInst"))); + DIAGNOSTICS_GLOSTRSET( + "compRenderStr", + "Render #" + QString::number(DIAGNOSTICS_GLOGET("compInst")) + " | "); + DIAGNOSTICS_GLOSET(DIAGNOSTICS_THRSTRGET("stackVar"), 0); + } #endif } //----------------------------------------------------------------------------------- -void TFxCacheManager::onRenderStatusEnd(int renderStatus) -{ - if (renderStatus == TRenderer::FIRSTRUN) { - Imp::ResourceInstanceDataMap &resMap = m_imp->m_resourcesData; +void TFxCacheManager::onRenderStatusEnd(int renderStatus) { + if (renderStatus == TRenderer::FIRSTRUN) { + Imp::ResourceInstanceDataMap &resMap = m_imp->m_resourcesData; + + Imp::ResourceInstanceDataMap::iterator it; + for (it = resMap.begin(); it != resMap.end();) { + m_imp->prepareTilesToCalculate(it->second); - Imp::ResourceInstanceDataMap::iterator it; - for (it = resMap.begin(); it != resMap.end();) { - m_imp->prepareTilesToCalculate(it->second); + // Cannot be done. The resource could still be feasible to caching, + // due to external requests. - //Cannot be done. The resource could still be feasible to caching, - //due to external requests. + // Erase all resource datas which have been declared and prepared only + // once + /*if(it->second.m_tiles.size() == 1 && +it->second.m_simData->m_tiles.size() == 1) +{ +it = resMap.erase(it); +continue; +}*/ - //Erase all resource datas which have been declared and prepared only once - /*if(it->second.m_tiles.size() == 1 && it->second.m_simData->m_tiles.size() == 1) - { - it = resMap.erase(it); + ++it; + } + } else if (renderStatus == TRenderer::TESTRUN) { + Imp::ResourceInstanceDataMap &resMap = m_imp->m_resourcesData; + Imp::ResourceInstanceDataMap::iterator it; + for (it = resMap.begin(); it != resMap.end();) { + // Release all resource declarations which are declared to be used only + // once. + if (it->second.m_tiles.size() == 1 && + it->second.m_tiles[0].m_refCount == 1) { + Imp::ResourceInstanceDataMap::iterator jt = it++; + resMap.erase(jt); continue; - }*/ - - ++it; - } - } else if (renderStatus == TRenderer::TESTRUN) { - Imp::ResourceInstanceDataMap &resMap = m_imp->m_resourcesData; - Imp::ResourceInstanceDataMap::iterator it; - for (it = resMap.begin(); it != resMap.end();) { - //Release all resource declarations which are declared to be used only once. - if (it->second.m_tiles.size() == 1 && it->second.m_tiles[0].m_refCount == 1) { - Imp::ResourceInstanceDataMap::iterator jt = it++; - resMap.erase(jt); - continue; - } - - //In any case, release all simulation datas - they are no longer useful. - //An associated cache resource avoids deletion only in case some manager - //retained it. - it->second.m_rawData = 0; - - ++it; - } + } + + // In any case, release all simulation datas - they are no longer useful. + // An associated cache resource avoids deletion only in case some manager + // retained it. + it->second.m_rawData = 0; + + ++it; + } #ifdef WRITEGENERAL - DIAGNOSTICS_SET("Declarations used more than once", resMap.size()); + DIAGNOSTICS_SET("Declarations used more than once", resMap.size()); #endif - m_imp->m_rawData.clear(); - } + m_imp->m_rawData.clear(); + } #ifdef WRITEGENERAL - else { - //Print the number of not depleted declarations - Imp::ResourceInstanceDataMap &resMap = m_imp->m_resourcesData; - Imp::ResourceInstanceDataMap::iterator it; - - DIAGNOSTICS_ADD(prefixErr + "Computing | Declarations survived after Test Run", resMap.size()); - if (resMap.size() > 0) { - for (it = resMap.begin(); it != resMap.end(); ++it) { - DIAGNOSTICS_STR(prefixErr + "Survived Declarations | " + QString::fromStdString(it->first).left(40)); - } - } - } + else { + // Print the number of not depleted declarations + Imp::ResourceInstanceDataMap &resMap = m_imp->m_resourcesData; + Imp::ResourceInstanceDataMap::iterator it; + + DIAGNOSTICS_ADD( + prefixErr + "Computing | Declarations survived after Test Run", + resMap.size()); + if (resMap.size() > 0) { + for (it = resMap.begin(); it != resMap.end(); ++it) { + DIAGNOSTICS_STR(prefixErr + "Survived Declarations | " + + QString::fromStdString(it->first).left(40)); + } + } + } #endif } @@ -379,468 +395,502 @@ void TFxCacheManager::onRenderStatusEnd(int renderStatus) // Tiles to calculate - methods //**************************************************************************************************** -void TFxCacheManager::Imp::prepareTilesToCalculate(ResourceDeclaration &data) -{ - //First, build the total sum of declared tiles - TRectD sum; - int tilesCount = data.m_rawData->m_tiles.size(); +void TFxCacheManager::Imp::prepareTilesToCalculate(ResourceDeclaration &data) { + // First, build the total sum of declared tiles + TRectD sum; + int tilesCount = data.m_rawData->m_tiles.size(); - for (int i = 0; i < tilesCount; ++i) - sum += data.m_rawData->m_tiles[i]; + for (int i = 0; i < tilesCount; ++i) sum += data.m_rawData->m_tiles[i]; - //Intersect the sum with bbox and ensure integer geometry - //sum *= data.m_rawData->m_bbox; - enlargeToI(sum); + // Intersect the sum with bbox and ensure integer geometry + // sum *= data.m_rawData->m_bbox; + enlargeToI(sum); - if (!data.m_rawData->m_subtileable) { - data.m_tiles.push_back(sum); - return; - } + if (!data.m_rawData->m_subtileable) { + data.m_tiles.push_back(sum); + return; + } - TRasterFx *fx = dynamic_cast(data.m_rawData->m_fx.getPointer()); + TRasterFx *fx = dynamic_cast(data.m_rawData->m_fx.getPointer()); - //Now, subdivide the sum - recursiveRectSubdivide(data.m_tiles, fx, sum, data.m_rawData->m_frame, data.m_rawData->m_rs); + // Now, subdivide the sum + recursiveRectSubdivide(data.m_tiles, fx, sum, data.m_rawData->m_frame, + data.m_rawData->m_rs); } //--------------------------------------------------------------------------- -//! Calculates at max 4 smaller subrects of passed one. Returns true or false whether the subdivision was +//! Calculates at max 4 smaller subrects of passed one. Returns true or false +//! whether the subdivision was //! successfully applied. inline void TFxCacheManager::Imp::subdivideIntoSmallerTiles( - const TRectD &rect, std::vector &tileSet) -{ - //Find the greater rect edge - TRectD subTile1, subTile2; - if (rect.getLx() > rect.getLy()) { - int sep = rect.x0 + tceil(0.5 * rect.getLx()); - subTile1 = TRectD(rect.x0, rect.y0, sep, rect.y1); - subTile2 = TRectD(sep, rect.y0, rect.x1, rect.y1); - } else { - int sep = rect.y0 + tceil(0.5 * rect.getLy()); - subTile1 = TRectD(rect.x0, rect.y0, rect.x1, sep); - subTile2 = TRectD(rect.x0, sep, rect.x1, rect.y1); - } - - tileSet.push_back(subTile1); - tileSet.push_back(subTile2); + const TRectD &rect, std::vector &tileSet) { + // Find the greater rect edge + TRectD subTile1, subTile2; + if (rect.getLx() > rect.getLy()) { + int sep = rect.x0 + tceil(0.5 * rect.getLx()); + subTile1 = TRectD(rect.x0, rect.y0, sep, rect.y1); + subTile2 = TRectD(sep, rect.y0, rect.x1, rect.y1); + } else { + int sep = rect.y0 + tceil(0.5 * rect.getLy()); + subTile1 = TRectD(rect.x0, rect.y0, rect.x1, sep); + subTile2 = TRectD(rect.x0, sep, rect.x1, rect.y1); + } + + tileSet.push_back(subTile1); + tileSet.push_back(subTile2); } //--------------------------------------------------------------------------- void TFxCacheManager::Imp::recursiveRectSubdivide( - std::vector &results, - TRasterFx *fx, - const TRectD &rect, - double frame, - const TRenderSettings &info, - int dropTol) -{ - //Here is the subdivision strategy: - // - First, since cache tiles are newly ALLOCATED, we impose the raster - // size restriction on them directly - // - Then, we check that the memory requirement for the fx (max raster size - // that it will allocate) is little. - // - As an exception to previous point, if the memory requirement stagnates - // near the same memory size, quit - //NOTE: Level images pass here, but haven't any fx. So they are currently not subdivided. - - //Retrieve the memory requirement for this input. - int memReq = fx ? fx->getMemoryRequirement(rect, frame, info) : 0; - - //In case memReq < 0, we assume a strong subdivision denial, just as if the usage was - //explicitly set as unsubdividable. - if (memReq < 0) { - results.push_back(rect); - return; - } - - if ((memReq > info.m_maxTileSize && memReq < dropTol) || - TRasterFx::memorySize(rect, info.m_bpp) > info.m_maxTileSize) { - std::vector subTileRects; - subdivideIntoSmallerTiles(rect, subTileRects); - - while (!subTileRects.empty()) { - TRectD subTileRect(subTileRects.back()); - subTileRects.pop_back(); - - //Pass subdivision below, with updated drop-tolerance - recursiveRectSubdivide(results, fx, subTileRect, frame, info, - memReq - (memReq >> 2)); - - //The newly required memory must be under 3/4 of the previous. - //This is required in order to make it worth subdividing. - } - - return; - } - - results.push_back(ResourceDeclaration::TileData(rect)); + std::vector &results, TRasterFx *fx, + const TRectD &rect, double frame, const TRenderSettings &info, + int dropTol) { + // Here is the subdivision strategy: + // - First, since cache tiles are newly ALLOCATED, we impose the raster + // size restriction on them directly + // - Then, we check that the memory requirement for the fx (max raster size + // that it will allocate) is little. + // - As an exception to previous point, if the memory requirement stagnates + // near the same memory size, quit + // NOTE: Level images pass here, but haven't any fx. So they are currently not + // subdivided. + + // Retrieve the memory requirement for this input. + int memReq = fx ? fx->getMemoryRequirement(rect, frame, info) : 0; + + // In case memReq < 0, we assume a strong subdivision denial, just as if the + // usage was + // explicitly set as unsubdividable. + if (memReq < 0) { + results.push_back(rect); + return; + } + + if ((memReq > info.m_maxTileSize && memReq < dropTol) || + TRasterFx::memorySize(rect, info.m_bpp) > info.m_maxTileSize) { + std::vector subTileRects; + subdivideIntoSmallerTiles(rect, subTileRects); + + while (!subTileRects.empty()) { + TRectD subTileRect(subTileRects.back()); + subTileRects.pop_back(); + + // Pass subdivision below, with updated drop-tolerance + recursiveRectSubdivide(results, fx, subTileRect, frame, info, + memReq - (memReq >> 2)); + + // The newly required memory must be under 3/4 of the previous. + // This is required in order to make it worth subdividing. + } + + return; + } + + results.push_back(ResourceDeclaration::TileData(rect)); } //**************************************************************************************************** // ResourceBuilder //**************************************************************************************************** -ResourceBuilder::ResourceBuilder( - const std::string &resourceName, - const TFxP &fx, double frame, const TRenderSettings &rs) - : m_cacheManager(TFxCacheManager::instance()), m_data(m_cacheManager->getResource(resourceName, fx, frame, rs)) -{ +ResourceBuilder::ResourceBuilder(const std::string &resourceName, + const TFxP &fx, double frame, + const TRenderSettings &rs) + : m_cacheManager(TFxCacheManager::instance()) + , m_data(m_cacheManager->getResource(resourceName, fx, frame, rs)) { #ifdef WRITESTACK - DIAGNOSTICS_THRSET("frame", frame); - DIAGNOSTICS_THRSTRSET("frameStr", "Frame " + QString::number(frame).rightJustified(4, ' ') + " | "); - DIAGNOSTICS_THRSTRSET("stackVar", - DIAGNOSTICS_GLOSTRGET("status") + "sv" + DIAGNOSTICS_GLOSTRGET("instVar") + "fr" + QString::number(frame)); - DIAGNOSTICS_THRSTRSET("ResourceName", QString::fromStdString(resourceName).left(35)); + DIAGNOSTICS_THRSET("frame", frame); + DIAGNOSTICS_THRSTRSET( + "frameStr", + "Frame " + QString::number(frame).rightJustified(4, ' ') + " | "); + DIAGNOSTICS_THRSTRSET("stackVar", DIAGNOSTICS_GLOSTRGET("status") + "sv" + + DIAGNOSTICS_GLOSTRGET("instVar") + + "fr" + QString::number(frame)); + DIAGNOSTICS_THRSTRSET("ResourceName", + QString::fromStdString(resourceName).left(35)); #endif } //----------------------------------------------------------------------------------- -void ResourceBuilder::declareResource( - const std::string &alias, const TFxP &fx, - const TRectD &rect, double frame, const TRenderSettings &rs, - bool subtileable) -{ - TFxCacheManager::instance()->declareResource( - alias, fx, rect, frame, rs, subtileable); +void ResourceBuilder::declareResource(const std::string &alias, const TFxP &fx, + const TRectD &rect, double frame, + const TRenderSettings &rs, + bool subtileable) { + TFxCacheManager::instance()->declareResource(alias, fx, rect, frame, rs, + subtileable); } //----------------------------------------------------------------------------------- -namespace -{ +namespace { // Retrieves all interesting tiles with respect to the build procedure. -// Explicitly, this refers to tiles intersecting the required rect, that are either +// Explicitly, this refers to tiles intersecting the required rect, that are +// either // not in the resource, or supposed to be not. -// Returns true if the required tile is contained in the sum of the predicted ones +// Returns true if the required tile is contained in the sum of the predicted +// ones // (which should definitely happen if the predictive step is coherent with the // computation one). bool getTilesToBuild( - const ResourceData &data, const TRectD &rect, std::vector &rectsToCalculate) -{ - assert(data.first); //The declaration must DEFINITELY be present - assert(data.second); //The resource should be present here + const ResourceData &data, const TRectD &rect, + std::vector &rectsToCalculate) { + assert(data.first); // The declaration must DEFINITELY be present + assert(data.second); // The resource should be present here - //Now, fill in with all prepared rects which intersect input rect and are not - //already in the resource + // Now, fill in with all prepared rects which intersect input rect and are not + // already in the resource - std::vector &preparedRects = - data.first->m_tiles; - std::vector::iterator jt; + std::vector &preparedRects = + data.first->m_tiles; + std::vector::iterator jt; - TRectD sum; - for (jt = preparedRects.begin(); jt != preparedRects.end(); ++jt) { - sum += jt->m_rect; + TRectD sum; + for (jt = preparedRects.begin(); jt != preparedRects.end(); ++jt) { + sum += jt->m_rect; - if (!(isEmpty(rect * jt->m_rect) || jt->m_calculated)) - rectsToCalculate.push_back(&(*jt)); - } + if (!(isEmpty(rect * jt->m_rect) || jt->m_calculated)) + rectsToCalculate.push_back(&(*jt)); + } - return sum.contains(rect); + return sum.contains(rect); } -} // namespace +} // namespace //----------------------------------------------------------------------------------- -void ResourceBuilder::simBuild(const TRectD &rect) -{ - //Retrieve the render status - int renderStatus = m_cacheManager->m_imp->m_renderStatus; +void ResourceBuilder::simBuild(const TRectD &rect) { + // Retrieve the render status + int renderStatus = m_cacheManager->m_imp->m_renderStatus; - //In the initial precomputing stage, just retrieve all the declarations without efforts. - if (renderStatus == TRenderer::FIRSTRUN) { - simCompute(rect); - return; - } + // In the initial precomputing stage, just retrieve all the declarations + // without efforts. + if (renderStatus == TRenderer::FIRSTRUN) { + simCompute(rect); + return; + } - //Perform the test run - if (renderStatus == TRenderer::TESTRUN) { - if (!(m_data.first && m_data.second)) - return; + // Perform the test run + if (renderStatus == TRenderer::TESTRUN) { + if (!(m_data.first && m_data.second)) return; #ifdef WRITESTACK - QString resName(DIAGNOSTICS_THRSTRGET("ResourceName")); - - QString renderStr(DIAGNOSTICS_GLOSTRGET("testRenderStr")); - QString frameStr(DIAGNOSTICS_THRSTRGET("frameStr")); - DIAGNOSTICS_NUMBEREDSTRSET(prefixTest + renderStr + frameStr, - DIAGNOSTICS_THRSTRGET("stackVar"), DIAGNOSTICS_STACKGET("parentResource") + " " + resName, - ::traduce(rect), 4); - DIAGNOSTICS_PUSHAUTO("parentResource", - QString::number(DIAGNOSTICS_GLOGET(DIAGNOSTICS_THRSTRGET("stackVar"))), bla); + QString resName(DIAGNOSTICS_THRSTRGET("ResourceName")); + + QString renderStr(DIAGNOSTICS_GLOSTRGET("testRenderStr")); + QString frameStr(DIAGNOSTICS_THRSTRGET("frameStr")); + DIAGNOSTICS_NUMBEREDSTRSET( + prefixTest + renderStr + frameStr, DIAGNOSTICS_THRSTRGET("stackVar"), + DIAGNOSTICS_STACKGET("parentResource") + " " + resName, ::traduce(rect), + 4); + DIAGNOSTICS_PUSHAUTO( + "parentResource", + QString::number(DIAGNOSTICS_GLOGET(DIAGNOSTICS_THRSTRGET("stackVar"))), + bla); #endif - //Retrieve the tiles to build - std::vector &tiles = m_data.first->m_tiles; + // Retrieve the tiles to build + std::vector &tiles = m_data.first->m_tiles; - //For every tile intersecting rect - std::vector::iterator it; - for (it = tiles.begin(); it != tiles.end(); ++it) { - ResourceDeclaration::TileData &tileData = *it; + // For every tile intersecting rect + std::vector::iterator it; + for (it = tiles.begin(); it != tiles.end(); ++it) { + ResourceDeclaration::TileData &tileData = *it; - if (!isEmpty(tileData.m_rect * rect)) { - //If the tile ref count == 0, assume that this tile has not yet been simComputed. - //Do so, then; further, add 1 to the number of predicted actively accessed tiles. - if (tileData.m_refCount == 0) { + if (!isEmpty(tileData.m_rect * rect)) { + // If the tile ref count == 0, assume that this tile has not yet been + // simComputed. + // Do so, then; further, add 1 to the number of predicted actively + // accessed tiles. + if (tileData.m_refCount == 0) { #ifdef WRITESUBRECTS - DIAGNOSTICS_NUMBEREDSTRSET(prefixTest + renderStr + frameStr, - DIAGNOSTICS_THRSTRGET("stackVar"), DIAGNOSTICS_STACKGET("parentResource") + " " + resName, - ::traduce(tileData.m_rect), 4); - DIAGNOSTICS_PUSHAUTO("parentResource", - QString::number(DIAGNOSTICS_GLOGET(DIAGNOSTICS_THRSTRGET("stackVar"))), bla2); + DIAGNOSTICS_NUMBEREDSTRSET( + prefixTest + renderStr + frameStr, + DIAGNOSTICS_THRSTRGET("stackVar"), + DIAGNOSTICS_STACKGET("parentResource") + " " + resName, + ::traduce(tileData.m_rect), 4); + DIAGNOSTICS_PUSHAUTO("parentResource", + QString::number(DIAGNOSTICS_GLOGET( + DIAGNOSTICS_THRSTRGET("stackVar"))), + bla2); #endif - simCompute(tileData.m_rect); - ++m_data.first->m_tilesCount; - } - - //Add a reference to this tile - ++tileData.m_refCount; - - if (m_data.second) { - QMutexLocker locker(m_data.second->getMutex()); - - TRect tileRectI( - tileData.m_rect.x0, tileData.m_rect.y0, - tileData.m_rect.x1 - 1, tileData.m_rect.y1 - 1); - - m_data.second->addRef2(tileRectI); - } - } - } - - return; - } - - //In this case, the simulation is used to declare that this rect will NOT be calculated. - //So, this is the behaviour: 1 refCount is depleted by all cells intersecting the rect - // - if the refCount is still >0, then another request will occur that will make the - //tile calculated. If it is == 0, and the tile has not yet been calculated, then the tile - //will supposedly be NO MORE calculated, so the simCompute has to be launched on that tile, too. - - if (renderStatus == TRenderer::COMPUTING) { - if (!(m_data.first && m_data.second)) - return; - - QMutexLocker locker(m_data.second->getMutex()); - - //Retrieve the tiles to build - std::vector &tiles = m_data.first->m_tiles; - - //Please note that the request should definitely be fitting the predicted results, - //since the original rect which generated these simCompute calls must have been fitting. - - //For every tile to build - std::vector::iterator it; - for (it = tiles.begin(); it != tiles.end(); ++it) { - ResourceDeclaration::TileData &tileData = *it; - - if (!isEmpty(tileData.m_rect * rect)) { - if (tileData.m_refCount <= 0) - continue; - - if (--tileData.m_refCount == 0 && !tileData.m_calculated) { - --m_data.first->m_tilesCount; - simCompute(tileData.m_rect); - } - - if (m_data.second) { - TRect tileRectI( - tileData.m_rect.x0, tileData.m_rect.y0, - tileData.m_rect.x1 - 1, tileData.m_rect.y1 - 1); - - m_data.second->release2(tileRectI); - } - } - } - } + simCompute(tileData.m_rect); + ++m_data.first->m_tilesCount; + } + + // Add a reference to this tile + ++tileData.m_refCount; + + if (m_data.second) { + QMutexLocker locker(m_data.second->getMutex()); + + TRect tileRectI(tileData.m_rect.x0, tileData.m_rect.y0, + tileData.m_rect.x1 - 1, tileData.m_rect.y1 - 1); + + m_data.second->addRef2(tileRectI); + } + } + } + + return; + } + + // In this case, the simulation is used to declare that this rect will NOT be + // calculated. + // So, this is the behaviour: 1 refCount is depleted by all cells intersecting + // the rect + // - if the refCount is still >0, then another request will occur that will + // make the + // tile calculated. If it is == 0, and the tile has not yet been calculated, + // then the tile + // will supposedly be NO MORE calculated, so the simCompute has to be launched + // on that tile, too. + + if (renderStatus == TRenderer::COMPUTING) { + if (!(m_data.first && m_data.second)) return; + + QMutexLocker locker(m_data.second->getMutex()); + + // Retrieve the tiles to build + std::vector &tiles = m_data.first->m_tiles; + + // Please note that the request should definitely be fitting the predicted + // results, + // since the original rect which generated these simCompute calls must have + // been fitting. + + // For every tile to build + std::vector::iterator it; + for (it = tiles.begin(); it != tiles.end(); ++it) { + ResourceDeclaration::TileData &tileData = *it; + + if (!isEmpty(tileData.m_rect * rect)) { + if (tileData.m_refCount <= 0) continue; + + if (--tileData.m_refCount == 0 && !tileData.m_calculated) { + --m_data.first->m_tilesCount; + simCompute(tileData.m_rect); + } + + if (m_data.second) { + TRect tileRectI(tileData.m_rect.x0, tileData.m_rect.y0, + tileData.m_rect.x1 - 1, tileData.m_rect.y1 - 1); + + m_data.second->release2(tileRectI); + } + } + } + } } //----------------------------------------------------------------------------------- -void ResourceBuilder::build(const TRectD &tileRect) -{ +void ResourceBuilder::build(const TRectD &tileRect) { #ifdef WRITESTACK - QString resName(DIAGNOSTICS_THRSTRGET("ResourceName")); - - QString renderStr(DIAGNOSTICS_GLOSTRGET("compRenderStr")); - QString frameStr(DIAGNOSTICS_THRSTRGET("frameStr")); - DIAGNOSTICS_NUMBEREDSTRSET(prefixComp + renderStr + frameStr, - DIAGNOSTICS_THRSTRGET("stackVar"), DIAGNOSTICS_STACKGET("parentResource") + " " + resName, - ::traduce(tileRect), 4); - DIAGNOSTICS_PUSHAUTO("parentResource", - QString::number(DIAGNOSTICS_GLOGET(DIAGNOSTICS_THRSTRGET("stackVar"))), bla); + QString resName(DIAGNOSTICS_THRSTRGET("ResourceName")); + + QString renderStr(DIAGNOSTICS_GLOSTRGET("compRenderStr")); + QString frameStr(DIAGNOSTICS_THRSTRGET("frameStr")); + DIAGNOSTICS_NUMBEREDSTRSET( + prefixComp + renderStr + frameStr, DIAGNOSTICS_THRSTRGET("stackVar"), + DIAGNOSTICS_STACKGET("parentResource") + " " + resName, + ::traduce(tileRect), 4); + DIAGNOSTICS_PUSHAUTO( + "parentResource", + QString::number(DIAGNOSTICS_GLOGET(DIAGNOSTICS_THRSTRGET("stackVar"))), + bla); #endif - //If there is no resource, just compute the tile directly. - if (!m_data.second) { + // If there is no resource, just compute the tile directly. + if (!m_data.second) { #ifdef WRITEGENERAL - if (m_data.first) - if (m_data.first->m_tilesCount > 0) - DIAGNOSTICS_ADD(prefixErr + "Computing | No-resource build, active decl, tilesCount > 0", 1); - else - DIAGNOSTICS_ADD(prefixErr + "Computing | No-resource build, active decl, tilesCount <= 0", 1); + if (m_data.first) + if (m_data.first->m_tilesCount > 0) + DIAGNOSTICS_ADD( + prefixErr + + "Computing | No-resource build, active decl, tilesCount > 0", + 1); + else + DIAGNOSTICS_ADD( + prefixErr + + "Computing | No-resource build, active decl, tilesCount <= 0", + 1); #endif - //assert(!m_data.first); //Should have been erased before the COMPUTING run. - compute(tileRect); - return; - } + // assert(!m_data.first); //Should have been erased before the COMPUTING + // run. + compute(tileRect); + return; + } - //Since this function must be thread-safe, use the appropriate synchronization tool. - QMutexLocker locker(m_data.second->getMutex()); + // Since this function must be thread-safe, use the appropriate + // synchronization tool. + QMutexLocker locker(m_data.second->getMutex()); - //Without declaration, you can just deal with the required tile. - if (!(m_data.first && m_data.first->m_tilesCount > 0)) { + // Without declaration, you can just deal with the required tile. + if (!(m_data.first && m_data.first->m_tilesCount > 0)) { #ifdef WRITEGENERAL - if (!m_data.first) - DIAGNOSTICS_ADD("#error.txt | Resources without declaration", 1); - else - DIAGNOSTICS_ADD("#error.txt | Resources with declaration, tilesCount <=0", 1); + if (!m_data.first) + DIAGNOSTICS_ADD("#error.txt | Resources without declaration", 1); + else + DIAGNOSTICS_ADD("#error.txt | Resources with declaration, tilesCount <=0", + 1); #endif - if (download(m_data.second)) - return; + if (download(m_data.second)) return; - compute(tileRect); + compute(tileRect); - //Since there is an associated resource, the calculated content is supposedly - //an interesting one. Upload it. - upload(m_data.second); + // Since there is an associated resource, the calculated content is + // supposedly + // an interesting one. Upload it. + upload(m_data.second); - return; - } + return; + } - //Now, both the declaration and the resource exist. + // Now, both the declaration and the resource exist. - //Retrieve the predicted tile that must be built in place of tile. - TDimension dim(tileRect.getLx(), tileRect.getLy()); + // Retrieve the predicted tile that must be built in place of tile. + TDimension dim(tileRect.getLx(), tileRect.getLy()); - std::vector tiles; - bool fittingPrediction = getTilesToBuild(m_data, tileRect, tiles); + std::vector tiles; + bool fittingPrediction = getTilesToBuild(m_data, tileRect, tiles); - if (!fittingPrediction) { + if (!fittingPrediction) { #ifdef WRITEGENERAL - DIAGNOSTICS_ADD(prefixErr + "Computing | Not fitting tiles", 1); + DIAGNOSTICS_ADD(prefixErr + "Computing | Not fitting tiles", 1); #endif - //If the required tile is not fitting the prediction, we assume it is a - //full un-predicted one - so no reference count will be updated (this would comply - //with the simCompute() method, in case we assume that mis-predicted - //computes are always prudently built IN EXCESS). - - //For now, just calculate it and stop. - locker.unlock(); - - compute(tileRect); - return; - } - - //If necessary, calculate something - if (tiles.size() > 0) { - //For every tile to build - std::vector::iterator it; - for (it = tiles.begin(); it != tiles.end(); ++it) { - ResourceDeclaration::TileData &tileData = **it; - - //If the tile can be downloaded from the resource, it's because it has actually - //been calculated by another render process - either a concurrent one, or any - //which has written this resource part on disk storage. - - //Since reference counts built in the simCompute assume that tiles downloaded - //from the resource have been calculated in THIS very render process, - //therefore having tileData.m_calculated == true, in this case - //heir refCounts must be updated since no computing will happen on them - //due to the predicted node builds of this resource. - TRect tileRectI( - tileData.m_rect.x0, tileData.m_rect.y0, - tileData.m_rect.x1 - 1, tileData.m_rect.y1 - 1); - - if (m_data.second->canDownloadAll(tileRectI)) { - if (!tileData.m_calculated && tileData.m_refCount > 0) { - /*#ifdef WRITESTACK - QString renderStr(DIAGNOSTICS_GLOSTRGET("compRenderStr")); - QString frameStr(DIAGNOSTICS_THRSTRGET("frameStr")); - DIAGNOSTICS_NUMBEREDSTRSET(prefixComp + renderStr + frameStr, - DIAGNOSTICS_THRSTRGET("stackVar"), "$ > " + resName, - ::traduce(tileData.m_rect), 4); + // If the required tile is not fitting the prediction, we assume it is a + // full un-predicted one - so no reference count will be updated (this would + // comply + // with the simCompute() method, in case we assume that mis-predicted + // computes are always prudently built IN EXCESS). + + // For now, just calculate it and stop. + locker.unlock(); + + compute(tileRect); + return; + } + + // If necessary, calculate something + if (tiles.size() > 0) { + // For every tile to build + std::vector::iterator it; + for (it = tiles.begin(); it != tiles.end(); ++it) { + ResourceDeclaration::TileData &tileData = **it; + + // If the tile can be downloaded from the resource, it's because it has + // actually + // been calculated by another render process - either a concurrent one, or + // any + // which has written this resource part on disk storage. + + // Since reference counts built in the simCompute assume that tiles + // downloaded + // from the resource have been calculated in THIS very render process, + // therefore having tileData.m_calculated == true, in this case + // heir refCounts must be updated since no computing will happen on them + // due to the predicted node builds of this resource. + TRect tileRectI(tileData.m_rect.x0, tileData.m_rect.y0, + tileData.m_rect.x1 - 1, tileData.m_rect.y1 - 1); + + if (m_data.second->canDownloadAll(tileRectI)) { + if (!tileData.m_calculated && tileData.m_refCount > 0) { + /*#ifdef WRITESTACK +QString renderStr(DIAGNOSTICS_GLOSTRGET("compRenderStr")); +QString frameStr(DIAGNOSTICS_THRSTRGET("frameStr")); +DIAGNOSTICS_NUMBEREDSTRSET(prefixComp + renderStr + frameStr, +DIAGNOSTICS_THRSTRGET("stackVar"), "$ > " + resName, +::traduce(tileData.m_rect), 4); #endif*/ - //Deplete children refsCount - rely on the simulated procedure - simCompute(tileData.m_rect); - } - } else { + // Deplete children refsCount - rely on the simulated procedure + simCompute(tileData.m_rect); + } + } else { #ifdef WRITESUBRECTS - DIAGNOSTICS_NUMBEREDSTRSET(prefixComp + renderStr + frameStr, - DIAGNOSTICS_THRSTRGET("stackVar"), DIAGNOSTICS_STACKGET("parentResource") + " " + resName, - ::traduce(tileData.m_rect), 4); - DIAGNOSTICS_PUSHAUTO("parentResource", - QString::number(DIAGNOSTICS_GLOGET(DIAGNOSTICS_THRSTRGET("stackVar"))), bla2); + DIAGNOSTICS_NUMBEREDSTRSET( + prefixComp + renderStr + frameStr, + DIAGNOSTICS_THRSTRGET("stackVar"), + DIAGNOSTICS_STACKGET("parentResource") + " " + resName, + ::traduce(tileData.m_rect), 4); + DIAGNOSTICS_PUSHAUTO("parentResource", + QString::number(DIAGNOSTICS_GLOGET( + DIAGNOSTICS_THRSTRGET("stackVar"))), + bla2); #endif - //Compute the tile to be calculated - compute(tileData.m_rect); - if (tileData.m_refCount > 0) - tileData.m_calculated = true; + // Compute the tile to be calculated + compute(tileData.m_rect); + if (tileData.m_refCount > 0) tileData.m_calculated = true; - //Upload the tile into the resource - do so even if the tile - //was unpredicted. In this case, we rely on the resource refCount to - //provide the deallocations... Should be so? - upload(m_data.second); - } - } - } + // Upload the tile into the resource - do so even if the tile + // was unpredicted. In this case, we rely on the resource refCount to + // provide the deallocations... Should be so? + upload(m_data.second); + } + } + } - //Finally, download the built resource in the required tile - bool ret = download(m_data.second); - assert(ret); + // Finally, download the built resource in the required tile + bool ret = download(m_data.second); + assert(ret); #ifdef WRITESTACK - if (!ret) - DIAGNOSTICS_STRSET(prefixErr + "Download falliti | " + - DIAGNOSTICS_GLOSTRGET("compRenderStr") + DIAGNOSTICS_THRSTRGET("frameStr") + - QString::number(DIAGNOSTICS_GLOGET(DIAGNOSTICS_THRSTRGET("stackVar"))), - "CROP #" + QString::number(DIAGNOSTICS_GLOGET("crStack"))); + if (!ret) + DIAGNOSTICS_STRSET( + prefixErr + "Download falliti | " + + DIAGNOSTICS_GLOSTRGET("compRenderStr") + + DIAGNOSTICS_THRSTRGET("frameStr") + + QString::number( + DIAGNOSTICS_GLOGET(DIAGNOSTICS_THRSTRGET("stackVar"))), + "CROP #" + QString::number(DIAGNOSTICS_GLOGET("crStack"))); #endif - //Deplete a usage for all tiles intersecting the downloaded one. Fully depleted - //tiles become unpredicted from now on. - std::vector &resTiles = m_data.first->m_tiles; - std::vector::iterator it; - for (it = resTiles.begin(); it != resTiles.end(); ++it) { - ResourceDeclaration::TileData &tileData = *it; + // Deplete a usage for all tiles intersecting the downloaded one. Fully + // depleted + // tiles become unpredicted from now on. + std::vector &resTiles = m_data.first->m_tiles; + std::vector::iterator it; + for (it = resTiles.begin(); it != resTiles.end(); ++it) { + ResourceDeclaration::TileData &tileData = *it; - if (!isEmpty(tileData.m_rect * tileRect)) { - if (tileData.m_refCount <= 0) { + if (!isEmpty(tileData.m_rect * tileRect)) { + if (tileData.m_refCount <= 0) { #ifdef WRITEGENERAL - DIAGNOSTICS_ADD(prefixErr + "Computing | Over-used subtiles", 1); + DIAGNOSTICS_ADD(prefixErr + "Computing | Over-used subtiles", 1); #endif - continue; - } - - if (--tileData.m_refCount == 0) { - tileData.m_calculated = false; - --m_data.first->m_tilesCount; - } - - TRect tileRectI( - tileData.m_rect.x0, tileData.m_rect.y0, - tileData.m_rect.x1 - 1, tileData.m_rect.y1 - 1); - - m_data.second->release2(tileRectI); - } - } - - //If the declaration has been completely used up, destroy it. - //NOTE: Keeping the declarations is useful for diagnostic purposes. The following code - //could be reactivated - but declarations tend to be lightweight now... - //NOTE: If re-enabled, competing mutexes must be set where the resourcesData map is used... - /*if(m_data.first->m_tilesCount <= 0) - { - QMutexLocker locker(&m_cacheManager->m_imp->m_mutex); - m_cacheManager->m_imp->m_resourcesData.erase(m_data.second->getName()); - }*/ + continue; + } + + if (--tileData.m_refCount == 0) { + tileData.m_calculated = false; + --m_data.first->m_tilesCount; + } + + TRect tileRectI(tileData.m_rect.x0, tileData.m_rect.y0, + tileData.m_rect.x1 - 1, tileData.m_rect.y1 - 1); + + m_data.second->release2(tileRectI); + } + } + + // If the declaration has been completely used up, destroy it. + // NOTE: Keeping the declarations is useful for diagnostic purposes. The + // following code + // could be reactivated - but declarations tend to be lightweight now... + // NOTE: If re-enabled, competing mutexes must be set where the resourcesData + // map is used... + /*if(m_data.first->m_tilesCount <= 0) +{ +QMutexLocker locker(&m_cacheManager->m_imp->m_mutex); +m_cacheManager->m_imp->m_resourcesData.erase(m_data.second->getName()); +}*/ } diff --git a/toonz/sources/common/tfx/tmacrofx.cpp b/toonz/sources/common/tfx/tmacrofx.cpp index 7113d8e..c643533 100644 --- a/toonz/sources/common/tfx/tmacrofx.cpp +++ b/toonz/sources/common/tfx/tmacrofx.cpp @@ -11,199 +11,191 @@ //-------------------------------------------------- -namespace -{ +namespace { -class MatchesFx -{ +class MatchesFx { public: - MatchesFx(const TFxP &fx) : m_fx(fx) {} + MatchesFx(const TFxP &fx) : m_fx(fx) {} - bool operator()(const TFxP &fx) - { - return m_fx.getPointer() == fx.getPointer(); - } + bool operator()(const TFxP &fx) { + return m_fx.getPointer() == fx.getPointer(); + } - TFxP m_fx; + TFxP m_fx; }; //-------------------------------------------------- -void pushParents(const TFxP &root, std::vector &fxs, const std::vector &selectedFxs) -{ - int i, count = root->getInputPortCount(); - if (count == 0) { - std::vector::const_iterator found = std::find_if(fxs.begin(), fxs.end(), MatchesFx(root)); - if (found == fxs.end()) - fxs.push_back(root); - return; - } - for (i = 0; i < count; i++) { - TFxP inutFx = root->getInputPort(i)->getFx(); - std::vector::const_iterator found = std::find_if(selectedFxs.begin(), selectedFxs.end(), MatchesFx(inutFx)); - if (found != selectedFxs.end()) - pushParents(inutFx, fxs, selectedFxs); - } - std::vector::const_iterator found = std::find_if(fxs.begin(), fxs.end(), MatchesFx(root)); - if (found == fxs.end()) - fxs.push_back(root); +void pushParents(const TFxP &root, std::vector &fxs, + const std::vector &selectedFxs) { + int i, count = root->getInputPortCount(); + if (count == 0) { + std::vector::const_iterator found = + std::find_if(fxs.begin(), fxs.end(), MatchesFx(root)); + if (found == fxs.end()) fxs.push_back(root); + return; + } + for (i = 0; i < count; i++) { + TFxP inutFx = root->getInputPort(i)->getFx(); + std::vector::const_iterator found = + std::find_if(selectedFxs.begin(), selectedFxs.end(), MatchesFx(inutFx)); + if (found != selectedFxs.end()) pushParents(inutFx, fxs, selectedFxs); + } + std::vector::const_iterator found = + std::find_if(fxs.begin(), fxs.end(), MatchesFx(root)); + if (found == fxs.end()) fxs.push_back(root); } //-------------------------------------------------- -std::vector sortFxs(const std::vector &fxs) -{ - std::vector app; - std::vector roots; - //find fxs that could be in back of the vector. - int i; - for (i = 0; i < (int)fxs.size(); i++) { - TFxP fx = fxs[i]; - int j, count = (int)fx->getOutputConnectionCount(); - if (count == 0) { - roots.push_back(fx); - continue; - } - for (j = 0; j < count; j++) { - TFxP connectedFx = fx->getOutputConnection(j)->getOwnerFx(); - std::vector::const_iterator found = std::find_if(fxs.begin(), fxs.end(), MatchesFx(connectedFx)); - if (found == fxs.end()) { - roots.push_back(fx); - break; - } - } - } - for (i = 0; i < (int)roots.size(); i++) - pushParents(roots[i], app, fxs); - assert(fxs.size() == app.size()); - return app; +std::vector sortFxs(const std::vector &fxs) { + std::vector app; + std::vector roots; + // find fxs that could be in back of the vector. + int i; + for (i = 0; i < (int)fxs.size(); i++) { + TFxP fx = fxs[i]; + int j, count = (int)fx->getOutputConnectionCount(); + if (count == 0) { + roots.push_back(fx); + continue; + } + for (j = 0; j < count; j++) { + TFxP connectedFx = fx->getOutputConnection(j)->getOwnerFx(); + std::vector::const_iterator found = + std::find_if(fxs.begin(), fxs.end(), MatchesFx(connectedFx)); + if (found == fxs.end()) { + roots.push_back(fx); + break; + } + } + } + for (i = 0; i < (int)roots.size(); i++) pushParents(roots[i], app, fxs); + assert(fxs.size() == app.size()); + return app; } //-------------------------------------------------- // raccoglie tutti i parametri dai vari TFx e li assegna anche alla macro -void collectParams(TMacroFx *macroFx) -{ - int k; - for (k = 0; k < (int)macroFx->m_fxs.size(); k++) { - TFxP fx = macroFx->m_fxs[k]; - int j; - for (j = 0; j < fx->getParams()->getParamCount(); j++) - macroFx->getParams()->add(fx->getParams()->getParamVar(j)->clone()); - } +void collectParams(TMacroFx *macroFx) { + int k; + for (k = 0; k < (int)macroFx->m_fxs.size(); k++) { + TFxP fx = macroFx->m_fxs[k]; + int j; + for (j = 0; j < fx->getParams()->getParamCount(); j++) + macroFx->getParams()->add(fx->getParams()->getParamVar(j)->clone()); + } } -} // anonymous namespace +} // anonymous namespace //-------------------------------------------------- -bool TMacroFx::analyze(const std::vector &fxs, - TFxP &root, - std::vector &roots, - std::vector &leafs) -{ - if (fxs.size() == 1) - return false; - else { - leafs.clear(); - roots.clear(); - std::vector::const_iterator it = fxs.begin(); - for (; it != fxs.end(); ++it) { - TFxP fx = *it; - int inputInternalConnection = 0; - int inputExternalConnection = 0; - int outputInternalConnection = 0; - int outputExternalConnection = 0; - - int i; - - // calcola se ci sono connessioni in input dall'esterno - // verso l'interno e/o internamente a orderedFxs - int inputPortCount = fx->getInputPortCount(); - for (i = 0; i < inputPortCount; ++i) { - TFxPort *inputPort = fx->getInputPort(i); - TFx *inputPortFx = inputPort->getFx(); - if (inputPortFx) { - if (std::find_if(fxs.begin(), fxs.end(), MatchesFx(inputPortFx)) != fxs.end()) - ++inputInternalConnection; - else - ++inputExternalConnection; - } - } - - // calcola se ci sono connessioni in output dall'interno - // verso l'esterno e/o internamente a orderedFxs - int outputPortCount = fx->getOutputConnectionCount(); - for (i = 0; i < outputPortCount; ++i) { - TFxPort *outputPort = fx->getOutputConnection(i); - TFx *outputFx = outputPort->getOwnerFx(); - if (outputFx) { - if (std::find_if(fxs.begin(), fxs.end(), MatchesFx(outputFx)) != fxs.end()) - ++outputInternalConnection; - else - ++outputExternalConnection; - } - } - - // se fx e' una radice - if ((outputExternalConnection > 0) || - (outputExternalConnection == 0 && outputInternalConnection == 0)) { - root = fx; - roots.push_back(fx); - } - - // se fx e' una foglia - if (inputExternalConnection > 0 || fx->getInputPortCount() == 0 || - (inputExternalConnection == 0 && inputInternalConnection < fx->getInputPortCount())) { - leafs.push_back(fx); - } - } - - if (roots.size() != 1) - return false; - else { - if (leafs.size() == 0) - return false; - } - - return true; - } +bool TMacroFx::analyze(const std::vector &fxs, TFxP &root, + std::vector &roots, std::vector &leafs) { + if (fxs.size() == 1) + return false; + else { + leafs.clear(); + roots.clear(); + std::vector::const_iterator it = fxs.begin(); + for (; it != fxs.end(); ++it) { + TFxP fx = *it; + int inputInternalConnection = 0; + int inputExternalConnection = 0; + int outputInternalConnection = 0; + int outputExternalConnection = 0; + + int i; + + // calcola se ci sono connessioni in input dall'esterno + // verso l'interno e/o internamente a orderedFxs + int inputPortCount = fx->getInputPortCount(); + for (i = 0; i < inputPortCount; ++i) { + TFxPort *inputPort = fx->getInputPort(i); + TFx *inputPortFx = inputPort->getFx(); + if (inputPortFx) { + if (std::find_if(fxs.begin(), fxs.end(), MatchesFx(inputPortFx)) != + fxs.end()) + ++inputInternalConnection; + else + ++inputExternalConnection; + } + } + + // calcola se ci sono connessioni in output dall'interno + // verso l'esterno e/o internamente a orderedFxs + int outputPortCount = fx->getOutputConnectionCount(); + for (i = 0; i < outputPortCount; ++i) { + TFxPort *outputPort = fx->getOutputConnection(i); + TFx *outputFx = outputPort->getOwnerFx(); + if (outputFx) { + if (std::find_if(fxs.begin(), fxs.end(), MatchesFx(outputFx)) != + fxs.end()) + ++outputInternalConnection; + else + ++outputExternalConnection; + } + } + + // se fx e' una radice + if ((outputExternalConnection > 0) || + (outputExternalConnection == 0 && outputInternalConnection == 0)) { + root = fx; + roots.push_back(fx); + } + + // se fx e' una foglia + if (inputExternalConnection > 0 || fx->getInputPortCount() == 0 || + (inputExternalConnection == 0 && + inputInternalConnection < fx->getInputPortCount())) { + leafs.push_back(fx); + } + } + + if (roots.size() != 1) + return false; + else { + if (leafs.size() == 0) return false; + } + + return true; + } } //-------------------------------------------------- -bool TMacroFx::analyze(const std::vector &fxs) -{ - TFxP root = 0; - std::vector leafs; - std::vector roots; - return analyze(fxs, root, roots, leafs); +bool TMacroFx::analyze(const std::vector &fxs) { + TFxP root = 0; + std::vector leafs; + std::vector roots; + return analyze(fxs, root, roots, leafs); } //-------------------------------------------------- -bool TMacroFx::isaLeaf(TFx *fx) const -{ - int count = fx->getInputPortCount(); - if (count == 0) - return true; - - for (int i = 0; i < count; ++i) { - TFxPort *port = fx->getInputPort(i); - TFx *inputFx = port->getFx(); - if (inputFx) { - if (std::find_if(m_fxs.begin(), m_fxs.end(), MatchesFx(inputFx)) == m_fxs.end()) { - // il nodo di input non appartiene al macroFx - return true; - } - } else { - // la porta di input non e' connessa - return true; - } - } - - // tutte le porte di input sono connesse verso nodi appartenenti al macroFx - return false; +bool TMacroFx::isaLeaf(TFx *fx) const { + int count = fx->getInputPortCount(); + if (count == 0) return true; + + for (int i = 0; i < count; ++i) { + TFxPort *port = fx->getInputPort(i); + TFx *inputFx = port->getFx(); + if (inputFx) { + if (std::find_if(m_fxs.begin(), m_fxs.end(), MatchesFx(inputFx)) == + m_fxs.end()) { + // il nodo di input non appartiene al macroFx + return true; + } + } else { + // la porta di input non e' connessa + return true; + } + } + + // tutte le porte di input sono connesse verso nodi appartenenti al macroFx + return false; } //-------------------------------------------------- @@ -216,383 +208,362 @@ TMacroFx::~TMacroFx() {} //-------------------------------------------------- -TFx *TMacroFx::clone(bool recursive) const -{ - int n = m_fxs.size(); - std::vector clones(n); - std::map table; - std::map::iterator it; - int i, rootIndex = -1; - // nodi - for (i = 0; i < n; ++i) { - TFx *fx = m_fxs[i].getPointer(); - assert(fx); - clones[i] = fx->clone(false); - assert(table.count(fx) == 0); - table[fx] = i; - if (fx == m_root.getPointer()) - rootIndex = i; - TFx *linkedFx = fx->getLinkedFx(); - if (linkedFx && table.find(linkedFx) != table.end()) - clones[i]->linkParams(clones[table[linkedFx]].getPointer()); - } - assert(rootIndex >= 0); - // connessioni - for (i = 0; i < n; i++) { - TFx *fx = m_fxs[i].getPointer(); - for (int j = 0; j < fx->getInputPortCount(); j++) { - TFxPort *port = fx->getInputPort(j); - TFx *inputFx = port->getFx(); - if (!inputFx) - continue; - it = table.find(inputFx); - if (it == table.end()) { - // il j-esimo input di fx e' esterno alla macro - if (recursive) - clones[i]->connect(fx->getInputPortName(j), inputFx->clone(true)); - } else { - // il j-esimo input di fx e' interno alla macro - clones[i]->connect(fx->getInputPortName(j), clones[it->second].getPointer()); - } - } - } - - //TFx *rootClone = - // const_cast(this)-> - // clone(m_root.getPointer(), recursive, visited, clones); - - TMacroFx *clone = TMacroFx::create(clones); - clone->setName(getName()); - clone->setFxId(getFxId()); - - //Copy the index of the passive cache manager. - clone->getAttributes()->passiveCacheDataIdx() = getAttributes()->passiveCacheDataIdx(); - - assert(clone->getRoot() == clones[rootIndex].getPointer()); - - return clone; +TFx *TMacroFx::clone(bool recursive) const { + int n = m_fxs.size(); + std::vector clones(n); + std::map table; + std::map::iterator it; + int i, rootIndex = -1; + // nodi + for (i = 0; i < n; ++i) { + TFx *fx = m_fxs[i].getPointer(); + assert(fx); + clones[i] = fx->clone(false); + assert(table.count(fx) == 0); + table[fx] = i; + if (fx == m_root.getPointer()) rootIndex = i; + TFx *linkedFx = fx->getLinkedFx(); + if (linkedFx && table.find(linkedFx) != table.end()) + clones[i]->linkParams(clones[table[linkedFx]].getPointer()); + } + assert(rootIndex >= 0); + // connessioni + for (i = 0; i < n; i++) { + TFx *fx = m_fxs[i].getPointer(); + for (int j = 0; j < fx->getInputPortCount(); j++) { + TFxPort *port = fx->getInputPort(j); + TFx *inputFx = port->getFx(); + if (!inputFx) continue; + it = table.find(inputFx); + if (it == table.end()) { + // il j-esimo input di fx e' esterno alla macro + if (recursive) + clones[i]->connect(fx->getInputPortName(j), inputFx->clone(true)); + } else { + // il j-esimo input di fx e' interno alla macro + clones[i]->connect(fx->getInputPortName(j), + clones[it->second].getPointer()); + } + } + } + + // TFx *rootClone = + // const_cast(this)-> + // clone(m_root.getPointer(), recursive, visited, clones); + + TMacroFx *clone = TMacroFx::create(clones); + clone->setName(getName()); + clone->setFxId(getFxId()); + + // Copy the index of the passive cache manager. + clone->getAttributes()->passiveCacheDataIdx() = + getAttributes()->passiveCacheDataIdx(); + + assert(clone->getRoot() == clones[rootIndex].getPointer()); + + return clone; } //-------------------------------------------------- -bool TMacroFx::doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info) -{ - return m_root->doGetBBox(frame, bBox, info); +bool TMacroFx::doGetBBox(double frame, TRectD &bBox, + const TRenderSettings &info) { + return m_root->doGetBBox(frame, bBox, info); } //-------------------------------------------------- -void TMacroFx::doDryCompute(TRectD &rect, - double frame, - const TRenderSettings &info) -{ - assert(m_root); - m_root->dryCompute(rect, frame, info); +void TMacroFx::doDryCompute(TRectD &rect, double frame, + const TRenderSettings &info) { + assert(m_root); + m_root->dryCompute(rect, frame, info); } //-------------------------------------------------- -void TMacroFx::doCompute(TTile &tile, double frame, const TRenderSettings &ri) -{ - assert(m_root); - m_root->compute(tile, frame, ri); +void TMacroFx::doCompute(TTile &tile, double frame, const TRenderSettings &ri) { + assert(m_root); + m_root->compute(tile, frame, ri); } //-------------------------------------------------- -TFxTimeRegion TMacroFx::getTimeRegion() const -{ - return m_root->getTimeRegion(); +TFxTimeRegion TMacroFx::getTimeRegion() const { + return m_root->getTimeRegion(); } //-------------------------------------------------- -std::string TMacroFx::getPluginId() const -{ - return "Base"; -} +std::string TMacroFx::getPluginId() const { return "Base"; } //-------------------------------------------------- -void TMacroFx::setRoot(TFx *root) -{ - m_root = root; - // TFx::m_imp->m_outputPort = root->m_imp->m_outputPort; +void TMacroFx::setRoot(TFx *root) { + m_root = root; + // TFx::m_imp->m_outputPort = root->m_imp->m_outputPort; } //-------------------------------------------------- -TFx *TMacroFx::getRoot() const -{ - return m_root.getPointer(); -} +TFx *TMacroFx::getRoot() const { return m_root.getPointer(); } //-------------------------------------------------- -TFx *TMacroFx::getFxById(const std::wstring &id) const -{ - int i; - for (i = 0; i < (int)m_fxs.size(); i++) { - TFx *fx = m_fxs[i].getPointer(); - if (fx->getFxId() == id) - return fx; - } - return 0; +TFx *TMacroFx::getFxById(const std::wstring &id) const { + int i; + for (i = 0; i < (int)m_fxs.size(); i++) { + TFx *fx = m_fxs[i].getPointer(); + if (fx->getFxId() == id) return fx; + } + return 0; } //-------------------------------------------------- -const std::vector &TMacroFx::getFxs() const -{ - return m_fxs; -} +const std::vector &TMacroFx::getFxs() const { return m_fxs; } //-------------------------------------------------- -std::string TMacroFx::getMacroFxType() const -{ - std::string name = getFxType() + "("; - for (int i = 0; i < (int)m_fxs.size(); i++) { - if (i > 0) - name += ","; - if (TMacroFx *childMacro = dynamic_cast(m_fxs[i].getPointer())) - name += childMacro->getMacroFxType(); - else - name += m_fxs[i]->getFxType(); - } - return name + ")"; +std::string TMacroFx::getMacroFxType() const { + std::string name = getFxType() + "("; + for (int i = 0; i < (int)m_fxs.size(); i++) { + if (i > 0) name += ","; + if (TMacroFx *childMacro = dynamic_cast(m_fxs[i].getPointer())) + name += childMacro->getMacroFxType(); + else + name += m_fxs[i]->getFxType(); + } + return name + ")"; } //-------------------------------------------------- -TMacroFx *TMacroFx::create(const std::vector &fxs) -{ - std::vector leafs; - std::vector roots; - TFxP root = 0; - - std::vector orederedFxs = sortFxs(fxs); - - // verifica che gli effetti selezionati siano idonei ad essere raccolti - // in una macro. Ci deve essere un solo nodo terminale - // (roots.size()==1, roots[0] == root) e uno o piu' nodi di ingresso - // (assert leafs.size()>0) - if (!analyze(orederedFxs, root, roots, leafs)) - return 0; - - // ----------------------------- - - TMacroFx *macroFx = new TMacroFx; - - // tutti i nodi vengono spostati (e non copiati) nella macro stessa - std::vector::const_iterator it = orederedFxs.begin(); - for (; it != orederedFxs.end(); ++it) - macroFx->m_fxs.push_back(*it); - - // i nodi di ingresso vengono messi in collegamento con le - // porte di ingresso della macro - for (int i = 0; i < (int)leafs.size(); i++) { - TFxP fx = leafs[i]; - int k = 0; - int count = fx->getInputPortCount(); - for (; k < count; k++) { - TFxPort *port = fx->getInputPort(k); - std::string portName = fx->getInputPortName(k); - std::string fxId = ::to_string(fx->getFxId()); - portName += "_" + std::to_string(macroFx->getInputPortCount()) + "_" + fxId; - TFx *portFx = port->getFx(); - if (portFx) { - // se la porta k-esima del nodo di ingresso i-esimo e' collegata - // ad un effetto, la porta viene inserita solo se l'effetto non fa - // gia' parte della macro - if (std::find_if(orederedFxs.begin(), orederedFxs.end(), MatchesFx(portFx)) == orederedFxs.end()) - macroFx->addInputPort(portName, *port); - } else - macroFx->addInputPort(portName, *port); - } - } - - // le porte di uscita di root diventano le porte di uscita della macro - int count = root->getOutputConnectionCount(); - int k = count - 1; - for (; k >= 0; --k) { - TFxPort *port = root->getOutputConnection(k); - port->setFx(macroFx); - } - - macroFx->setRoot(root.getPointer()); - - // tutti i parametri delle funzioni figlie diventano parametri della macro - collectParams(macroFx); - return macroFx; +TMacroFx *TMacroFx::create(const std::vector &fxs) { + std::vector leafs; + std::vector roots; + TFxP root = 0; + + std::vector orederedFxs = sortFxs(fxs); + + // verifica che gli effetti selezionati siano idonei ad essere raccolti + // in una macro. Ci deve essere un solo nodo terminale + // (roots.size()==1, roots[0] == root) e uno o piu' nodi di ingresso + // (assert leafs.size()>0) + if (!analyze(orederedFxs, root, roots, leafs)) return 0; + + // ----------------------------- + + TMacroFx *macroFx = new TMacroFx; + + // tutti i nodi vengono spostati (e non copiati) nella macro stessa + std::vector::const_iterator it = orederedFxs.begin(); + for (; it != orederedFxs.end(); ++it) macroFx->m_fxs.push_back(*it); + + // i nodi di ingresso vengono messi in collegamento con le + // porte di ingresso della macro + for (int i = 0; i < (int)leafs.size(); i++) { + TFxP fx = leafs[i]; + int k = 0; + int count = fx->getInputPortCount(); + for (; k < count; k++) { + TFxPort *port = fx->getInputPort(k); + std::string portName = fx->getInputPortName(k); + std::string fxId = ::to_string(fx->getFxId()); + portName += + "_" + std::to_string(macroFx->getInputPortCount()) + "_" + fxId; + TFx *portFx = port->getFx(); + if (portFx) { + // se la porta k-esima del nodo di ingresso i-esimo e' collegata + // ad un effetto, la porta viene inserita solo se l'effetto non fa + // gia' parte della macro + if (std::find_if(orederedFxs.begin(), orederedFxs.end(), + MatchesFx(portFx)) == orederedFxs.end()) + macroFx->addInputPort(portName, *port); + } else + macroFx->addInputPort(portName, *port); + } + } + + // le porte di uscita di root diventano le porte di uscita della macro + int count = root->getOutputConnectionCount(); + int k = count - 1; + for (; k >= 0; --k) { + TFxPort *port = root->getOutputConnection(k); + port->setFx(macroFx); + } + + macroFx->setRoot(root.getPointer()); + + // tutti i parametri delle funzioni figlie diventano parametri della macro + collectParams(macroFx); + return macroFx; } //-------------------------------------------------- -bool TMacroFx::canHandle(const TRenderSettings &info, double frame) -{ - return m_root->canHandle(info, frame); +bool TMacroFx::canHandle(const TRenderSettings &info, double frame) { + return m_root->canHandle(info, frame); } //-------------------------------------------------- -std::string TMacroFx::getAlias(double frame, const TRenderSettings &info) const -{ - std::string alias = getFxType(); - alias += "["; - - // alias degli effetti connessi alle porte di input separati da virgole - // una porta non connessa da luogo a un alias vuoto (stringa vuota) - int i; - for (i = 0; i < getInputPortCount(); i++) { - TFxPort *port = getInputPort(i); - if (port->isConnected()) { - TRasterFxP ifx = port->getFx(); - assert(ifx); - alias += ifx->getAlias(frame, info); - } - alias += ","; - } - - // alias dei valori dei parametri dell'effetto al frame dato - for (int j = 0; j < (int)m_fxs.size(); j++) { - alias += (j == 0) ? "(" : ",("; - for (i = 0; i < m_fxs[j]->getParams()->getParamCount(); i++) { - if (i > 0) - alias += ","; - TParam *param = m_fxs[j]->getParams()->getParam(i); - alias += param->getName() + "=" + param->getValueAlias(frame, 2); - } - alias += ")"; - } - - alias += "]"; - return alias; +std::string TMacroFx::getAlias(double frame, + const TRenderSettings &info) const { + std::string alias = getFxType(); + alias += "["; + + // alias degli effetti connessi alle porte di input separati da virgole + // una porta non connessa da luogo a un alias vuoto (stringa vuota) + int i; + for (i = 0; i < getInputPortCount(); i++) { + TFxPort *port = getInputPort(i); + if (port->isConnected()) { + TRasterFxP ifx = port->getFx(); + assert(ifx); + alias += ifx->getAlias(frame, info); + } + alias += ","; + } + + // alias dei valori dei parametri dell'effetto al frame dato + for (int j = 0; j < (int)m_fxs.size(); j++) { + alias += (j == 0) ? "(" : ",("; + for (i = 0; i < m_fxs[j]->getParams()->getParamCount(); i++) { + if (i > 0) alias += ","; + TParam *param = m_fxs[j]->getParams()->getParam(i); + alias += param->getName() + "=" + param->getValueAlias(frame, 2); + } + alias += ")"; + } + + alias += "]"; + return alias; } //-------------------------------------------------- -void TMacroFx::compatibilityTranslatePort(int major, int minor, std::string &portName) -{ - // Reroute translation to the actual fx associated to the port - const std::string &fxId = portName.substr(portName.find_last_of('_') + 1, - std::string::npos); - - if (TFx *fx = getFxById(::to_wstring(fxId))) { - size_t opnEnd = portName.find_first_of('_'); - - std::string originalPortName = portName.substr(0, opnEnd); - fx->compatibilityTranslatePort(major, minor, originalPortName); - - portName.replace(0, opnEnd, originalPortName); - } - - // Seems that at a certain point, the port name got extended... - if (VersionNumber(major, minor) == VersionNumber(1, 16)) { - for (int i = 0; i < getInputPortCount(); ++i) { - const std::string &name = getInputPortName(i); - if (name.find(portName) != std::string::npos) { - portName = name; - break; - } - } - } +void TMacroFx::compatibilityTranslatePort(int major, int minor, + std::string &portName) { + // Reroute translation to the actual fx associated to the port + const std::string &fxId = + portName.substr(portName.find_last_of('_') + 1, std::string::npos); + + if (TFx *fx = getFxById(::to_wstring(fxId))) { + size_t opnEnd = portName.find_first_of('_'); + + std::string originalPortName = portName.substr(0, opnEnd); + fx->compatibilityTranslatePort(major, minor, originalPortName); + + portName.replace(0, opnEnd, originalPortName); + } + + // Seems that at a certain point, the port name got extended... + if (VersionNumber(major, minor) == VersionNumber(1, 16)) { + for (int i = 0; i < getInputPortCount(); ++i) { + const std::string &name = getInputPortName(i); + if (name.find(portName) != std::string::npos) { + portName = name; + break; + } + } + } } //-------------------------------------------------- -void TMacroFx::loadData(TIStream &is) -{ - VersionNumber tnzVersion = is.getVersion(); - std::string tagName; - while (is.openChild(tagName)) { - if (tagName == "root") { - TPersist *p = 0; - is >> p; - m_root = dynamic_cast(p); - } else if (tagName == "nodes") { - while (!is.eos()) { - TPersist *p = 0; - is >> p; - - // NOTE: In current implementation p is sharedly owned by is - it's automatically - // released upon stream destruction if the below assignment fails - - if (TFx *fx = dynamic_cast(p)) { - m_fxs.push_back(fx); - } - } - } else if (tagName == "ports") { - int i = 0; - while (is.matchTag(tagName)) { - if (tagName == "port") { - std::string name = is.getTagAttribute("name"); - if (tnzVersion < VersionNumber(1, 16) && name != "") { - TRasterFxPort *port = new TRasterFxPort(); - addInputPort(name, *port); - } else { - name = is.getTagAttribute("name_inFx"); - if (tnzVersion < VersionNumber(1, 17) && tnzVersion != VersionNumber(0, 0)) - name.insert(name.find("_"), "_" + std::to_string(i)); - - compatibilityTranslatePort(tnzVersion.first, tnzVersion.second, name); - - std::string inPortName = name; - inPortName.erase(inPortName.find("_"), inPortName.size() - 1); - - std::string inFxId = name; - inFxId.erase(0, inFxId.find_last_of("_") + 1); - - for (int i = 0; i < (int)m_fxs.size(); i++) { - std::wstring fxId = m_fxs[i]->getFxId(); - if (fxId == ::to_wstring(inFxId)) { - if (TFxPort *port = m_fxs[i]->getInputPort(inPortName)) - addInputPort(name, *port); - } - } - } - i++; - } else - throw TException("unexpected tag " + tagName); - } - } else if (tagName == "super") { - TRasterFx::loadData(is); - } else - throw TException("unexpected tag " + tagName); - is.closeChild(); - } - collectParams(this); +void TMacroFx::loadData(TIStream &is) { + VersionNumber tnzVersion = is.getVersion(); + std::string tagName; + while (is.openChild(tagName)) { + if (tagName == "root") { + TPersist *p = 0; + is >> p; + m_root = dynamic_cast(p); + } else if (tagName == "nodes") { + while (!is.eos()) { + TPersist *p = 0; + is >> p; + + // NOTE: In current implementation p is sharedly owned by is - it's + // automatically + // released upon stream destruction if the below assignment fails + + if (TFx *fx = dynamic_cast(p)) { + m_fxs.push_back(fx); + } + } + } else if (tagName == "ports") { + int i = 0; + while (is.matchTag(tagName)) { + if (tagName == "port") { + std::string name = is.getTagAttribute("name"); + if (tnzVersion < VersionNumber(1, 16) && name != "") { + TRasterFxPort *port = new TRasterFxPort(); + addInputPort(name, *port); + } else { + name = is.getTagAttribute("name_inFx"); + if (tnzVersion < VersionNumber(1, 17) && + tnzVersion != VersionNumber(0, 0)) + name.insert(name.find("_"), "_" + std::to_string(i)); + + compatibilityTranslatePort(tnzVersion.first, tnzVersion.second, + name); + + std::string inPortName = name; + inPortName.erase(inPortName.find("_"), inPortName.size() - 1); + + std::string inFxId = name; + inFxId.erase(0, inFxId.find_last_of("_") + 1); + + for (int i = 0; i < (int)m_fxs.size(); i++) { + std::wstring fxId = m_fxs[i]->getFxId(); + if (fxId == ::to_wstring(inFxId)) { + if (TFxPort *port = m_fxs[i]->getInputPort(inPortName)) + addInputPort(name, *port); + } + } + } + i++; + } else + throw TException("unexpected tag " + tagName); + } + } else if (tagName == "super") { + TRasterFx::loadData(is); + } else + throw TException("unexpected tag " + tagName); + is.closeChild(); + } + collectParams(this); } //-------------------------------------------------- -void TMacroFx::saveData(TOStream &os) -{ - int i; - os.openChild("root"); - TPersist *p = m_root.getPointer(); - os << p; - os.closeChild(); - os.openChild("nodes"); - for (i = 0; i < (int)m_fxs.size(); i++) { - TFxP fx = m_fxs[i]; - TPersist *p = fx.getPointer(); - os << p; - } - os.closeChild(); - os.openChild("ports"); - for (i = 0; i < getInputPortCount(); i++) { - std::string portName = getInputPortName(i); - std::map attr; - attr["name_inFx"] = portName; - os.openCloseChild("port", attr); - } - os.closeChild(); - os.openChild("super"); - TRasterFx::saveData(os); - os.closeChild(); +void TMacroFx::saveData(TOStream &os) { + int i; + os.openChild("root"); + TPersist *p = m_root.getPointer(); + os << p; + os.closeChild(); + os.openChild("nodes"); + for (i = 0; i < (int)m_fxs.size(); i++) { + TFxP fx = m_fxs[i]; + TPersist *p = fx.getPointer(); + os << p; + } + os.closeChild(); + os.openChild("ports"); + for (i = 0; i < getInputPortCount(); i++) { + std::string portName = getInputPortName(i); + std::map attr; + attr["name_inFx"] = portName; + os.openCloseChild("port", attr); + } + os.closeChild(); + os.openChild("super"); + TRasterFx::saveData(os); + os.closeChild(); } //-------------------------------------------------- FX_IDENTIFIER(TMacroFx, "macroFx") -//FX_IDENTIFIER_IS_HIDDEN(TMacroFx, "macroFx") +// FX_IDENTIFIER_IS_HIDDEN(TMacroFx, "macroFx") diff --git a/toonz/sources/common/tfx/tpassivecachemanager.cpp b/toonz/sources/common/tfx/tpassivecachemanager.cpp index 805c66e..6659f27 100644 --- a/toonz/sources/common/tfx/tpassivecachemanager.cpp +++ b/toonz/sources/common/tfx/tpassivecachemanager.cpp @@ -12,83 +12,124 @@ /* PRACTICAL EXPLANATION: -The TPassiveCacheManager's purpose is that of storing render results from a specified set of fx nodes. +The TPassiveCacheManager's purpose is that of storing render results from a +specified set of fx nodes. -When an fx is passed to the manager to be cached, a structure of type FxData is generated for the fx. -It is stored inside the manager and ASSOCIATED to the fx through an INDEX key - this one being stored +When an fx is passed to the manager to be cached, a structure of type FxData is +generated for the fx. +It is stored inside the manager and ASSOCIATED to the fx through an INDEX key - +this one being stored inside the fx data. -In particular, the FxData instances contain a PERSISTANT identifier (passiveCacheId) that is saved inside -the scene data, a flag specifying the cache status of the fx node (like, if it's enabled or not), and +In particular, the FxData instances contain a PERSISTANT identifier +(passiveCacheId) that is saved inside +the scene data, a flag specifying the cache status of the fx node (like, if it's +enabled or not), and a description of the schematic dag below the associated fx. -Now, when a resource request is made to the TPassiveCacheManager, it checks the FxData about the generating -fx - if it contains the flag specifying that it must be cached, a resource is allocated (if not already +Now, when a resource request is made to the TPassiveCacheManager, it checks the +FxData about the generating +fx - if it contains the flag specifying that it must be cached, a resource is +allocated (if not already present), a reference to it is stored, and finally the resource is returned. -References to interesting resources are stored in a TABLE container, indexed by "rendering context" and -fx. A rendering context is hereby intended as a SEQUENCE of render processes where the next render of the +References to interesting resources are stored in a TABLE container, indexed by +"rendering context" and +fx. A rendering context is hereby intended as a SEQUENCE of render processes +where the next render of the sequence is assumed to REPLACE the previous one. -We therefore have one context for the swatch viewer, one for File>Preview, one for the Preview Fx of each -fx node, and one context for EACH FRAME of the sceneviewer preview (one frame is not supposed to replace +We therefore have one context for the swatch viewer, one for File>Preview, one +for the Preview Fx of each +fx node, and one context for EACH FRAME of the sceneviewer preview (one frame is +not supposed to replace another in that case). -The table is in practice a map of maps (a kind of 'comb' structure) - where the primary map is associated -by render context and the secondary ones by fx. This mean that we are able to address and iterate contexts +The table is in practice a map of maps (a kind of 'comb' structure) - where the +primary map is associated +by render context and the secondary ones by fx. This mean that we are able to +address and iterate contexts easier than fxs. Values of the table are set of resources. RESOURCES MAINTENANCE POLICY: -As resources use a concrete amount of memory for storage, they should be kept in the resources table only -for the time they are supposedly useful to the user. There are 2 ways of dealing with this issue. +As resources use a concrete amount of memory for storage, they should be kept in +the resources table only +for the time they are supposedly useful to the user. There are 2 ways of dealing +with this issue. -1) First, we can track scene changes and eliminate those resources that will no longer be accessed due to the -applied change. This happens, for example, when a level is being drawn, fxs are inserted, moved or removed. +1) First, we can track scene changes and eliminate those resources that will no +longer be accessed due to the +applied change. This happens, for example, when a level is being drawn, fxs are +inserted, moved or removed. -Level changes are delivered immediately to the ::invalidateLevel(..) method, which removes all resources -whose name contains the level's name. Unfortunately, this cannot be done at frame precision (ie you cannot +Level changes are delivered immediately to the ::invalidateLevel(..) method, +which removes all resources +whose name contains the level's name. Unfortunately, this cannot be done at +frame precision (ie you cannot invalidate a single frame of the level, but ALL the level). -Xsheet (schematic) changes are tracked through the schematic node description stored inside the FxData structure. -Once one such change happens, all resources update their description - if that changes, the associated resources +Xsheet (schematic) changes are tracked through the schematic node description +stored inside the FxData structure. +Once one such change happens, all resources update their description - if that +changes, the associated resources are released. -The same schematic description is used to track and release resources affected by changes on a downstream fx's +The same schematic description is used to track and release resources affected +by changes on a downstream fx's parameters. -There are also scene changes that are inherently hard to track or intercept. For example, pegbar affines changes, -fx nodes expressions referencing data not directly connected to the fx, and possibly others. These are currently +There are also scene changes that are inherently hard to track or intercept. For +example, pegbar affines changes, +fx nodes expressions referencing data not directly connected to the fx, and +possibly others. These are currently NOT handled by direct tracking. -2) As there may be resources which escape the resource control by point (1), we need some extra control +2) As there may be resources which escape the resource control by point (1), we +need some extra control policies. Here they are: -We assume that the pool of resources accessed by render processes of a same render context should be CONSTANT -IF NO SCENE CHANGE HAPPENS. In other words, we are guessing that only those resources used in the last -rendering will be used in the next. Resources accessed in a render but NOT in the next (of the same context) +We assume that the pool of resources accessed by render processes of a same +render context should be CONSTANT +IF NO SCENE CHANGE HAPPENS. In other words, we are guessing that only those +resources used in the last +rendering will be used in the next. Resources accessed in a render but NOT in +the next (of the same context) are released. -However, it could be that the sequence of render processes from a context is halted from a certain moment on. -In that case, it is a waste to keep the resources accessed by its last render if no new render will ever take -place. We then assume further that a rendering context can be ENABLED or DISABLED - when a render context is -enabled, it will most likely have a next render - and therefore can keep its resources in memory. +However, it could be that the sequence of render processes from a context is +halted from a certain moment on. +In that case, it is a waste to keep the resources accessed by its last render if +no new render will ever take +place. We then assume further that a rendering context can be ENABLED or +DISABLED - when a render context is +enabled, it will most likely have a next render - and therefore can keep its +resources in memory. Once a context is DISABLED, it moves the resources to a TEMPORARY context. -Resources in the temporary context are those 'on their way for release'. They will be KEPT only if the -next rendering - INDEPENDENTLY FROM THE RENDER CONTEXT - requires them (in this case, they will be adopted -by the new context). This is necessary since context disables typically happen when a preview window closes. -It is not unfrequent that users close the preview window, modify the scene, and then restore the preview. +Resources in the temporary context are those 'on their way for release'. They +will be KEPT only if the +next rendering - INDEPENDENTLY FROM THE RENDER CONTEXT - requires them (in this +case, they will be adopted +by the new context). This is necessary since context disables typically happen +when a preview window closes. +It is not unfrequent that users close the preview window, modify the scene, and +then restore the preview. CONSIDERATIONS: -* The File>Render generates NO CONTEXT - and therefore does NOT PASSIVELY CACHE RESOURCES, since it cannot be - stated whether it is in the 'enabled' or 'disabled' state. It could be considered coherent with what tcomposer +* The File>Render generates NO CONTEXT - and therefore does NOT PASSIVELY CACHE +RESOURCES, since it cannot be + stated whether it is in the 'enabled' or 'disabled' state. It could be +considered coherent with what tcomposer does, by the way... -* Our resources maintenance policy ensures that the memory usage should be stable over time - that is, no +* Our resources maintenance policy ensures that the memory usage should be +stable over time - that is, no useless resource is kept in memory. - Of course, it is possibly more restrictive than what the user may desire. For example, closing 2 preview - windows marks their resources for deletion, but only one of the two restored previews will keep its + Of course, it is possibly more restrictive than what the user may desire. For +example, closing 2 preview + windows marks their resources for deletion, but only one of the two restored +previews will keep its resources intact... */ @@ -98,47 +139,46 @@ CONSIDERATIONS: //***************************************************************************************** // Local stuff - inlines -namespace -{ -inline QRect toQRect(const TRect &r) { return QRect(r.x0, r.y0, r.getLx(), r.getLy()); } -inline TRect toTRect(const QRect &r) { return TRect(r.left(), r.top(), r.right(), r.bottom()); } +namespace { +inline QRect toQRect(const TRect &r) { + return QRect(r.x0, r.y0, r.getLx(), r.getLy()); +} +inline TRect toTRect(const QRect &r) { + return TRect(r.left(), r.top(), r.right(), r.bottom()); +} } //--------------------------------------------------------------------------- -TFx *TPassiveCacheManager::getNotAllowingAncestor(TFx *fx) +TFx *TPassiveCacheManager::getNotAllowingAncestor(TFx *fx) { + // Trace all output ports + int outputPortsCount = fx->getOutputConnectionCount(); + /*if(!outputPortsCount) //We have no access to TApp here!! { - //Trace all output ports - int outputPortsCount = fx->getOutputConnectionCount(); - /*if(!outputPortsCount) //We have no access to TApp here!! - { - //It could be a terminal fx. In that case, pass to the xsheet fx - FxDag* dag = TApp::instance()->getCurrentXsheet()->getXsheet()->getFxDag(); - if(dag->getTerminalFxs()->containsFx(fx)) - return getNotAllowingAncestor(dag->getXsheetFx()); - }*/ - - //Now, for common ports - for (int i = 0; i < outputPortsCount; ++i) { - //Find the output Fx and the port connected to our fx - TFxPort *port = fx->getOutputConnection(i); - TRasterFx *outFx = static_cast(port->getOwnerFx()); - - int portIdx, portsCount = outFx->getInputPortCount(); - for (portIdx = 0; portIdx < portsCount; ++portIdx) - if (outFx->getInputPort(portIdx) == port) - break; - assert(portIdx < portsCount); - - if (!outFx->allowUserCacheOnPort(portIdx)) - return outFx; - - TFx *naAncestor = getNotAllowingAncestor(outFx); - if (naAncestor) - return naAncestor; - } - - return 0; +//It could be a terminal fx. In that case, pass to the xsheet fx +FxDag* dag = TApp::instance()->getCurrentXsheet()->getXsheet()->getFxDag(); +if(dag->getTerminalFxs()->containsFx(fx)) +return getNotAllowingAncestor(dag->getXsheetFx()); +}*/ + + // Now, for common ports + for (int i = 0; i < outputPortsCount; ++i) { + // Find the output Fx and the port connected to our fx + TFxPort *port = fx->getOutputConnection(i); + TRasterFx *outFx = static_cast(port->getOwnerFx()); + + int portIdx, portsCount = outFx->getInputPortCount(); + for (portIdx = 0; portIdx < portsCount; ++portIdx) + if (outFx->getInputPort(portIdx) == port) break; + assert(portIdx < portsCount); + + if (!outFx->allowUserCacheOnPort(portIdx)) return outFx; + + TFx *naAncestor = getNotAllowingAncestor(outFx); + if (naAncestor) return naAncestor; + } + + return 0; } //***************************************************************************************** @@ -146,258 +186,222 @@ TFx *TPassiveCacheManager::getNotAllowingAncestor(TFx *fx) //***************************************************************************************** template -class Table -{ +class Table { public: - typedef typename std::map Row; + typedef typename std::map Row; private: - std::map m_table; + std::map m_table; - friend class Iterator; - friend class ColIterator; + friend class Iterator; + friend class ColIterator; public: - typedef typename std::map::iterator RowsIterator; - - class Iterator - { - protected: - Table *m_table; - RowsIterator m_rowIt; - typename Row::iterator m_it; - - friend class Table; - Iterator(Table *table) : m_table(table) {} - - virtual void makeConsistent() - { - if (m_it == m_rowIt->second.end()) { - if (++m_rowIt == m_table->m_table.end()) - return; - m_it = m_rowIt->second.begin(); - } - } - - public: - const RowKey &row() { return m_rowIt->first; } - const ColKey &col() { return m_it->first; } - - virtual void operator++() - { - ++m_it; - makeConsistent(); - } - - virtual operator bool() { return m_rowIt != m_table->m_table.end(); } - - Val &operator*() { return m_it->second; } - Val *operator->() { return &m_it->second; } - - bool operator==(const Iterator &it) - { - return m_it == it.m_it; - } - - bool operator!=(const Iterator &it) - { - return !operator==(it); - } - }; - - class ColIterator : public Iterator - { - ColKey m_colKey; - - friend class Table; - ColIterator(Table *table, const ColKey &c) : Iterator(table), m_colKey(c) {} - - void makeConsistent() - { - Iterator::m_rowIt = Iterator::m_rowIt; - while (Iterator::m_rowIt != Iterator::m_table->m_table.end()) { - Iterator::m_it = Iterator::m_rowIt->second.find(m_colKey); - if (Iterator::m_it != Iterator::m_rowIt->second.end()) - break; - ++Iterator::m_rowIt; - } - } - - public: - void operator++() - { - ++Iterator::m_rowIt; - makeConsistent(); - } - }; - - class RowIterator : public Iterator - { - friend class Table; - RowIterator(Table *table) : Iterator(table) {} - - void makeConsistent() {} - - public: - RowIterator(const RowsIterator rowIt) : Iterator(0) - { - Iterator::m_rowIt = rowIt; - Iterator::m_it = rowIt->second.begin(); - } - - void operator++() { ++Iterator::m_it; } - operator bool() { return Iterator::m_it != Iterator::m_rowIt->second.end(); } - }; + typedef typename std::map::iterator RowsIterator; + + class Iterator { + protected: + Table *m_table; + RowsIterator m_rowIt; + typename Row::iterator m_it; + + friend class Table; + Iterator(Table *table) : m_table(table) {} + + virtual void makeConsistent() { + if (m_it == m_rowIt->second.end()) { + if (++m_rowIt == m_table->m_table.end()) return; + m_it = m_rowIt->second.begin(); + } + } + + public: + const RowKey &row() { return m_rowIt->first; } + const ColKey &col() { return m_it->first; } + + virtual void operator++() { + ++m_it; + makeConsistent(); + } + + virtual operator bool() { return m_rowIt != m_table->m_table.end(); } + + Val &operator*() { return m_it->second; } + Val *operator->() { return &m_it->second; } + + bool operator==(const Iterator &it) { return m_it == it.m_it; } + + bool operator!=(const Iterator &it) { return !operator==(it); } + }; + + class ColIterator : public Iterator { + ColKey m_colKey; + + friend class Table; + ColIterator(Table *table, const ColKey &c) : Iterator(table), m_colKey(c) {} + + void makeConsistent() { + Iterator::m_rowIt = Iterator::m_rowIt; + while (Iterator::m_rowIt != Iterator::m_table->m_table.end()) { + Iterator::m_it = Iterator::m_rowIt->second.find(m_colKey); + if (Iterator::m_it != Iterator::m_rowIt->second.end()) break; + ++Iterator::m_rowIt; + } + } + + public: + void operator++() { + ++Iterator::m_rowIt; + makeConsistent(); + } + }; + + class RowIterator : public Iterator { + friend class Table; + RowIterator(Table *table) : Iterator(table) {} + + void makeConsistent() {} + + public: + RowIterator(const RowsIterator rowIt) : Iterator(0) { + Iterator::m_rowIt = rowIt; + Iterator::m_it = rowIt->second.begin(); + } + + void operator++() { ++Iterator::m_it; } + operator bool() { + return Iterator::m_it != Iterator::m_rowIt->second.end(); + } + }; public: - Table() {} - ~Table() {} - - std::map &rows() { return m_table; } - - Iterator begin() - { - Iterator result(this); - result.m_rowIt = m_table.begin(); - if (result.m_rowIt != m_table.end()) - result.m_it = result.m_rowIt->second.begin(); - return result; - } - - RowIterator rowBegin(const RowKey &row) - { - RowIterator result(this); - result.m_rowIt = m_table.find(row); - if (result.m_rowIt != m_table.end()) - result.m_it = result.m_rowIt->second.begin(); - return result; - } - - ColIterator colBegin(const ColKey &col) - { - ColIterator result(this, col); - result.m_rowIt = m_table.begin(); - result.makeConsistent(); - return result; - } - - Val &value(const RowKey &r, const ColKey &c) - { - return m_table[r][c]; - } - - Iterator insert(const RowKey &r, const ColKey &c, const Val &val) - { - Iterator result(this); - result.m_rowIt = m_table.insert(std::make_pair(r, Row())).first; - result.m_it = result.m_rowIt->second.insert(std::make_pair(c, val)).first; - return result; - } - - Iterator find(const RowKey &r, const ColKey &c) - { - Iterator result(this); - result.m_rowIt = m_table.find(r); - if (result.m_rowIt == m_table.end()) - return; - result.m_it = result.m_rowIt->second.find(c); - if (result.m_it == result.m_rowIt->second.end()) - result.m_rowIt = m_table.end(); - return result; - } - - Iterator erase(const RowKey &r, const ColKey &c) - { - Iterator it(find(r, c)); - return erase(it); - } - - Iterator erase(const Iterator &it) - { - Iterator result(it); - Row &row = it.m_rowIt->second; - ++result.m_it; - row.erase(it.m_it); - if (result.m_it == row.end() && row.empty()) { - result.makeConsistent(); - m_table.erase(it.m_rowIt); - return result; - } - - result.makeConsistent(); - return result; - } - - void erase(const ColKey &c) - { - ColIterator it(colBegin(c)); - while (it) { - RowsIterator rowIt = it.m_rowIt; - rowIt->second.erase(it.m_it); - ++it; - if (rowIt->second.empty()) - m_table.erase(rowIt); - } - } - - void erase(const RowKey &r) - { - m_table.erase(r); - } - - void clear() { m_table.clear(); } + Table() {} + ~Table() {} + + std::map &rows() { return m_table; } + + Iterator begin() { + Iterator result(this); + result.m_rowIt = m_table.begin(); + if (result.m_rowIt != m_table.end()) + result.m_it = result.m_rowIt->second.begin(); + return result; + } + + RowIterator rowBegin(const RowKey &row) { + RowIterator result(this); + result.m_rowIt = m_table.find(row); + if (result.m_rowIt != m_table.end()) + result.m_it = result.m_rowIt->second.begin(); + return result; + } + + ColIterator colBegin(const ColKey &col) { + ColIterator result(this, col); + result.m_rowIt = m_table.begin(); + result.makeConsistent(); + return result; + } + + Val &value(const RowKey &r, const ColKey &c) { return m_table[r][c]; } + + Iterator insert(const RowKey &r, const ColKey &c, const Val &val) { + Iterator result(this); + result.m_rowIt = m_table.insert(std::make_pair(r, Row())).first; + result.m_it = result.m_rowIt->second.insert(std::make_pair(c, val)).first; + return result; + } + + Iterator find(const RowKey &r, const ColKey &c) { + Iterator result(this); + result.m_rowIt = m_table.find(r); + if (result.m_rowIt == m_table.end()) return; + result.m_it = result.m_rowIt->second.find(c); + if (result.m_it == result.m_rowIt->second.end()) + result.m_rowIt = m_table.end(); + return result; + } + + Iterator erase(const RowKey &r, const ColKey &c) { + Iterator it(find(r, c)); + return erase(it); + } + + Iterator erase(const Iterator &it) { + Iterator result(it); + Row &row = it.m_rowIt->second; + ++result.m_it; + row.erase(it.m_it); + if (result.m_it == row.end() && row.empty()) { + result.makeConsistent(); + m_table.erase(it.m_rowIt); + return result; + } + + result.makeConsistent(); + return result; + } + + void erase(const ColKey &c) { + ColIterator it(colBegin(c)); + while (it) { + RowsIterator rowIt = it.m_rowIt; + rowIt->second.erase(it.m_it); + ++it; + if (rowIt->second.empty()) m_table.erase(rowIt); + } + } + + void erase(const RowKey &r) { m_table.erase(r); } + + void clear() { m_table.clear(); } }; //-------------------------------------------------------------------------- struct LockedResourceP { - TCacheResourceP m_resource; - - LockedResourceP(const TCacheResourceP &resource) : m_resource(resource) - { - m_resource->addLock(); - } - - LockedResourceP(const LockedResourceP &resource) : m_resource(resource.m_resource) - { - m_resource->addLock(); - } - - ~LockedResourceP() - { - m_resource->releaseLock(); - } - - LockedResourceP &operator=(const LockedResourceP &src) - { - src.m_resource->addLock(); - if (m_resource) - m_resource->releaseLock(); - m_resource = src.m_resource; - return *this; - } - - operator bool() const { return m_resource; } - - bool operator<(const LockedResourceP &resource) const { return m_resource < resource.m_resource; } - - TCacheResource *operator->() const { return m_resource.getPointer(); } - TCacheResource &operator*() const { return *m_resource.getPointer(); } + TCacheResourceP m_resource; + + LockedResourceP(const TCacheResourceP &resource) : m_resource(resource) { + m_resource->addLock(); + } + + LockedResourceP(const LockedResourceP &resource) + : m_resource(resource.m_resource) { + m_resource->addLock(); + } + + ~LockedResourceP() { m_resource->releaseLock(); } + + LockedResourceP &operator=(const LockedResourceP &src) { + src.m_resource->addLock(); + if (m_resource) m_resource->releaseLock(); + m_resource = src.m_resource; + return *this; + } + + operator bool() const { return m_resource; } + + bool operator<(const LockedResourceP &resource) const { + return m_resource < resource.m_resource; + } + + TCacheResource *operator->() const { return m_resource.getPointer(); } + TCacheResource &operator*() const { return *m_resource.getPointer(); } }; typedef Table> ResourcesTable; //-------------------------------------------------------------------------- -class TPassiveCacheManager::ResourcesContainer -{ - ResourcesTable m_resources; +class TPassiveCacheManager::ResourcesContainer { + ResourcesTable m_resources; public: - ResourcesContainer() {} - ~ResourcesContainer() {} + ResourcesContainer() {} + ~ResourcesContainer() {} - ResourcesTable &getTable() { return m_resources; } + ResourcesTable &getTable() { return m_resources; } }; //***************************************************************************************** @@ -405,15 +409,11 @@ public: //***************************************************************************************** TPassiveCacheManager::FxData::FxData() - : m_storageFlag(0), m_passiveCacheId(0) -{ -} + : m_storageFlag(0), m_passiveCacheId(0) {} //------------------------------------------------------------------------- -TPassiveCacheManager::FxData::~FxData() -{ -} +TPassiveCacheManager::FxData::~FxData() {} //***************************************************************************************** // Manager generator @@ -423,19 +423,16 @@ TPassiveCacheManager::FxData::~FxData() // TPassiveCacheManagerGenerator //--------------------------------------- -class TPassiveCacheManagerGenerator : public TRenderResourceManagerGenerator -{ - TRenderResourceManager *operator()(void) - { - //return new TPassiveCacheManager; - return TPassiveCacheManager::instance(); - } +class TPassiveCacheManagerGenerator : public TRenderResourceManagerGenerator { + TRenderResourceManager *operator()(void) { + // return new TPassiveCacheManager; + return TPassiveCacheManager::instance(); + } }; -MANAGER_FILESCOPE_DECLARATION_DEP( - TPassiveCacheManager, - TPassiveCacheManagerGenerator, - TFxCacheManager::deps()) +MANAGER_FILESCOPE_DECLARATION_DEP(TPassiveCacheManager, + TPassiveCacheManagerGenerator, + TFxCacheManager::deps()) //***************************************************************************************** // Implementation @@ -443,589 +440,559 @@ MANAGER_FILESCOPE_DECLARATION_DEP( TPassiveCacheManager::TPassiveCacheManager() #ifdef USE_SQLITE_HDPOOL - : m_currStorageFlag(ON_DISK) + : m_currStorageFlag(ON_DISK) #else - : m_currStorageFlag(IN_MEMORY) + : m_currStorageFlag(IN_MEMORY) #endif - , - m_enabled(true), m_descriptorCallback(0), m_mutex(QMutex::Recursive), m_resources(new ResourcesContainer) -{ - reset(); + , m_enabled(true) + , m_descriptorCallback(0) + , m_mutex(QMutex::Recursive) + , m_resources(new ResourcesContainer) { + reset(); } //------------------------------------------------------------------------- -TPassiveCacheManager::~TPassiveCacheManager() -{ - delete m_resources; -} +TPassiveCacheManager::~TPassiveCacheManager() { delete m_resources; } //------------------------------------------------------------------------- -TPassiveCacheManager *TPassiveCacheManager::instance() -{ - static TPassiveCacheManager theInstance; - return &theInstance; +TPassiveCacheManager *TPassiveCacheManager::instance() { + static TPassiveCacheManager theInstance; + return &theInstance; } //------------------------------------------------------------------------- -void TPassiveCacheManager::setContextName(unsigned long renderId, const std::string &name) -{ - QMutexLocker locker(&m_mutex); +void TPassiveCacheManager::setContextName(unsigned long renderId, + const std::string &name) { + QMutexLocker locker(&m_mutex); - //Retrieve the context data if already present - std::map::iterator it = m_contextNames.find(name); - if (it == m_contextNames.end()) - it = m_contextNames.insert(std::make_pair(name, 0)).first; + // Retrieve the context data if already present + std::map::iterator it = m_contextNames.find(name); + if (it == m_contextNames.end()) + it = m_contextNames.insert(std::make_pair(name, 0)).first; - it->second = !it->second; - m_contextNamesByRenderId.insert(std::make_pair(renderId, name + "%" + std::to_string(it->second))); + it->second = !it->second; + m_contextNamesByRenderId.insert( + std::make_pair(renderId, name + "%" + std::to_string(it->second))); } //------------------------------------------------------------------------- -std::string TPassiveCacheManager::getContextName() -{ - QMutexLocker locker(&m_mutex); +std::string TPassiveCacheManager::getContextName() { + QMutexLocker locker(&m_mutex); - //First, search the context name - std::map::iterator it = - m_contextNamesByRenderId.find(TRenderer::renderId()); + // First, search the context name + std::map::iterator it = + m_contextNamesByRenderId.find(TRenderer::renderId()); - if (it == m_contextNamesByRenderId.end()) - return ""; + if (it == m_contextNamesByRenderId.end()) return ""; - return it->second; + return it->second; } //------------------------------------------------------------------------- -void TPassiveCacheManager::setEnabled(bool enabled) -{ - m_enabled = enabled; -} +void TPassiveCacheManager::setEnabled(bool enabled) { m_enabled = enabled; } //------------------------------------------------------------------------- -bool TPassiveCacheManager::isEnabled() const -{ - return m_enabled; -} +bool TPassiveCacheManager::isEnabled() const { return m_enabled; } //------------------------------------------------------------------------- -void TPassiveCacheManager::setStorageMode(StorageFlag mode) -{ - m_currStorageFlag = mode; +void TPassiveCacheManager::setStorageMode(StorageFlag mode) { + m_currStorageFlag = mode; } //------------------------------------------------------------------------- -TPassiveCacheManager::StorageFlag TPassiveCacheManager::getStorageMode() const -{ - return m_currStorageFlag; +TPassiveCacheManager::StorageFlag TPassiveCacheManager::getStorageMode() const { + return m_currStorageFlag; } //----------------------------------------------------------------------------------- -void TPassiveCacheManager::setTreeDescriptor(TreeDescriptor callback) -{ - m_descriptorCallback = callback; +void TPassiveCacheManager::setTreeDescriptor(TreeDescriptor callback) { + m_descriptorCallback = callback; } //----------------------------------------------------------------------------------- -int TPassiveCacheManager::getNewPassiveCacheId() -{ - return ++m_currentPassiveCacheId; +int TPassiveCacheManager::getNewPassiveCacheId() { + return ++m_currentPassiveCacheId; } //----------------------------------------------------------------------------------- -int TPassiveCacheManager::updatePassiveCacheId(int id) -{ - if (m_updatingPassiveCacheIds) - m_currentPassiveCacheId = std::max(m_currentPassiveCacheId, id); - else - id = getNewPassiveCacheId(); +int TPassiveCacheManager::updatePassiveCacheId(int id) { + if (m_updatingPassiveCacheIds) + m_currentPassiveCacheId = std::max(m_currentPassiveCacheId, id); + else + id = getNewPassiveCacheId(); - return id; + return id; } //----------------------------------------------------------------------------------- -void TPassiveCacheManager::onSceneLoaded() -{ - m_updatingPassiveCacheIds = false; +void TPassiveCacheManager::onSceneLoaded() { + m_updatingPassiveCacheIds = false; -//Initialize the fxs tree description. This was not possible before, as the -//scene was yet incomplete (in loading state). +// Initialize the fxs tree description. This was not possible before, as the +// scene was yet incomplete (in loading state). #ifndef USE_SQLITE_HDPOOL - unsigned int count = m_fxDataVector.size(); - for (unsigned int i = 0; i < count; ++i) { - FxData &data = m_fxDataVector[i]; - (*m_descriptorCallback)(data.m_treeDescription, data.m_fx); - } + unsigned int count = m_fxDataVector.size(); + for (unsigned int i = 0; i < count; ++i) { + FxData &data = m_fxDataVector[i]; + (*m_descriptorCallback)(data.m_treeDescription, data.m_fx); + } #endif } //----------------------------------------------------------------------------------- -void TPassiveCacheManager::touchFxData(int &idx) -{ - if (idx >= 0) - return; +void TPassiveCacheManager::touchFxData(int &idx) { + if (idx >= 0) return; - QMutexLocker locker(&m_mutex); + QMutexLocker locker(&m_mutex); - m_fxDataVector.push_back(FxData()); - idx = m_fxDataVector.size() - 1; + m_fxDataVector.push_back(FxData()); + idx = m_fxDataVector.size() - 1; } //----------------------------------------------------------------------------------- -int TPassiveCacheManager::declareCached(TFx *fx, int passiveCacheId) -{ - int &idx = fx->getAttributes()->passiveCacheDataIdx(); - touchFxData(idx); +int TPassiveCacheManager::declareCached(TFx *fx, int passiveCacheId) { + int &idx = fx->getAttributes()->passiveCacheDataIdx(); + touchFxData(idx); - FxData &data = m_fxDataVector[idx]; - data.m_fx = fx; - data.m_storageFlag = m_currStorageFlag; - data.m_passiveCacheId = updatePassiveCacheId(passiveCacheId); + FxData &data = m_fxDataVector[idx]; + data.m_fx = fx; + data.m_storageFlag = m_currStorageFlag; + data.m_passiveCacheId = updatePassiveCacheId(passiveCacheId); - return idx; + return idx; } //------------------------------------------------------------------------- -void TPassiveCacheManager::reset() -{ - m_updatingPassiveCacheIds = true; - m_currentPassiveCacheId = 0; - m_fxDataVector.clear(); - m_resources->getTable().clear(); +void TPassiveCacheManager::reset() { + m_updatingPassiveCacheIds = true; + m_currentPassiveCacheId = 0; + m_fxDataVector.clear(); + m_resources->getTable().clear(); } //------------------------------------------------------------------------- -bool TPassiveCacheManager::cacheEnabled(TFx *fx) -{ - int idx = fx->getAttributes()->passiveCacheDataIdx(); - if (idx < 0) - return false; +bool TPassiveCacheManager::cacheEnabled(TFx *fx) { + int idx = fx->getAttributes()->passiveCacheDataIdx(); + if (idx < 0) return false; - assert(idx < (int)m_fxDataVector.size()); + assert(idx < (int)m_fxDataVector.size()); - QMutexLocker locker(&m_mutex); + QMutexLocker locker(&m_mutex); - return m_fxDataVector[idx].m_storageFlag > 0; + return m_fxDataVector[idx].m_storageFlag > 0; } //------------------------------------------------------------------------- -int TPassiveCacheManager::getPassiveCacheId(TFx *fx) -{ - int idx = fx->getAttributes()->passiveCacheDataIdx(); - if (idx < 0) - return 0; +int TPassiveCacheManager::getPassiveCacheId(TFx *fx) { + int idx = fx->getAttributes()->passiveCacheDataIdx(); + if (idx < 0) return 0; - //This needs not be mutex locked + // This needs not be mutex locked - assert(idx < (int)m_fxDataVector.size()); - return m_fxDataVector[idx].m_passiveCacheId; + assert(idx < (int)m_fxDataVector.size()); + return m_fxDataVector[idx].m_passiveCacheId; } //------------------------------------------------------------------------- -TPassiveCacheManager::StorageFlag TPassiveCacheManager::getStorageMode(TFx *fx) -{ - int idx = fx->getAttributes()->passiveCacheDataIdx(); - if (idx < 0) - return NONE; +TPassiveCacheManager::StorageFlag TPassiveCacheManager::getStorageMode( + TFx *fx) { + int idx = fx->getAttributes()->passiveCacheDataIdx(); + if (idx < 0) return NONE; - QMutexLocker locker(&m_mutex); + QMutexLocker locker(&m_mutex); - return (StorageFlag)m_fxDataVector[idx].m_storageFlag; + return (StorageFlag)m_fxDataVector[idx].m_storageFlag; } //------------------------------------------------------------------------- -void TPassiveCacheManager::enableCache(TFx *fx) -{ - int &idx = fx->getAttributes()->passiveCacheDataIdx(); - touchFxData(idx); +void TPassiveCacheManager::enableCache(TFx *fx) { + int &idx = fx->getAttributes()->passiveCacheDataIdx(); + touchFxData(idx); - FxData &data = m_fxDataVector[idx]; + FxData &data = m_fxDataVector[idx]; - QMutexLocker locker(&m_mutex); + QMutexLocker locker(&m_mutex); #ifdef DIAGNOSTICS - DIAGNOSTICS_STR("#activity.txt | " + QTime::currentTime().toString() + " " + - QString("Enable Cache")); + DIAGNOSTICS_STR("#activity.txt | " + QTime::currentTime().toString() + " " + + QString("Enable Cache")); #endif - StorageFlag flag = getStorageMode(); - if (flag) { - UCHAR &storedFlag = data.m_storageFlag; - UCHAR oldFlag = storedFlag; + StorageFlag flag = getStorageMode(); + if (flag) { + UCHAR &storedFlag = data.m_storageFlag; + UCHAR oldFlag = storedFlag; - storedFlag |= flag; + storedFlag |= flag; - if (data.m_passiveCacheId == 0) - data.m_passiveCacheId = getNewPassiveCacheId(); + if (data.m_passiveCacheId == 0) + data.m_passiveCacheId = getNewPassiveCacheId(); - if ((storedFlag & ON_DISK) && !(oldFlag & ON_DISK)) { - ResourcesTable::ColIterator it = m_resources->getTable().colBegin(data.m_passiveCacheId); - for (; it; ++it) { - std::set &resources = *it; + if ((storedFlag & ON_DISK) && !(oldFlag & ON_DISK)) { + ResourcesTable::ColIterator it = + m_resources->getTable().colBegin(data.m_passiveCacheId); + for (; it; ++it) { + std::set &resources = *it; - std::set::iterator jt; - for (jt = resources.begin(); jt != resources.end(); ++jt) - (*jt)->enableBackup(); - } - } + std::set::iterator jt; + for (jt = resources.begin(); jt != resources.end(); ++jt) + (*jt)->enableBackup(); + } + } #ifndef USE_SQLITE_HDPOOL - if ((storedFlag & IN_MEMORY) && !(oldFlag & IN_MEMORY)) { - data.m_fx = fx; - (*m_descriptorCallback)(data.m_treeDescription, data.m_fx); - } + if ((storedFlag & IN_MEMORY) && !(oldFlag & IN_MEMORY)) { + data.m_fx = fx; + (*m_descriptorCallback)(data.m_treeDescription, data.m_fx); + } #endif - } + } } //------------------------------------------------------------------------- -void TPassiveCacheManager::disableCache(TFx *fx) -{ - int idx = fx->getAttributes()->passiveCacheDataIdx(); - if (idx < 0) - return; +void TPassiveCacheManager::disableCache(TFx *fx) { + int idx = fx->getAttributes()->passiveCacheDataIdx(); + if (idx < 0) return; - FxData &data = m_fxDataVector[idx]; + FxData &data = m_fxDataVector[idx]; - QMutexLocker locker(&m_mutex); + QMutexLocker locker(&m_mutex); #ifdef DIAGNOSTICS - DIAGNOSTICS_STR("#activity.txt | " + QTime::currentTime().toString() + " " + - QString("Disable Cache")); + DIAGNOSTICS_STR("#activity.txt | " + QTime::currentTime().toString() + " " + + QString("Disable Cache")); #endif - StorageFlag flag = getStorageMode(); - if (flag) { - UCHAR &storedFlag = data.m_storageFlag; - UCHAR oldFlag = storedFlag; + StorageFlag flag = getStorageMode(); + if (flag) { + UCHAR &storedFlag = data.m_storageFlag; + UCHAR oldFlag = storedFlag; - storedFlag &= ~flag; + storedFlag &= ~flag; - if ((oldFlag & IN_MEMORY) && !(storedFlag & IN_MEMORY)) { - m_resources->getTable().erase(data.m_passiveCacheId); + if ((oldFlag & IN_MEMORY) && !(storedFlag & IN_MEMORY)) { + m_resources->getTable().erase(data.m_passiveCacheId); - data.m_fx = TFxP(); - data.m_treeDescription = ""; - } + data.m_fx = TFxP(); + data.m_treeDescription = ""; + } #ifdef USE_SQLITE_HDPOOL - if ((oldFlag & ON_DISK) && !(storedFlag & ON_DISK)) - TCacheResourcePool::instance()->releaseReferences("P" + QString::number(data.m_passiveCacheId)); + if ((oldFlag & ON_DISK) && !(storedFlag & ON_DISK)) + TCacheResourcePool::instance()->releaseReferences( + "P" + QString::number(data.m_passiveCacheId)); #endif - } + } } //------------------------------------------------------------------------- -void TPassiveCacheManager::toggleCache(TFx *fx) -{ - int &idx = fx->getAttributes()->passiveCacheDataIdx(); - touchFxData(idx); +void TPassiveCacheManager::toggleCache(TFx *fx) { + int &idx = fx->getAttributes()->passiveCacheDataIdx(); + touchFxData(idx); - FxData &data = m_fxDataVector[idx]; + FxData &data = m_fxDataVector[idx]; - QMutexLocker locker(&m_mutex); + QMutexLocker locker(&m_mutex); - StorageFlag flag = getStorageMode(); - if (flag) { - UCHAR &storedFlag = data.m_storageFlag; - UCHAR oldFlag = storedFlag; + StorageFlag flag = getStorageMode(); + if (flag) { + UCHAR &storedFlag = data.m_storageFlag; + UCHAR oldFlag = storedFlag; - storedFlag ^= flag; + storedFlag ^= flag; #ifdef DIAGNOSTICS - DIAGNOSTICS_STR("#activity.txt | " + QTime::currentTime().toString() + " " + - QString("Toggle Cache (now ") + ((storedFlag & IN_MEMORY) ? "enabled)" : "disabled)")); + DIAGNOSTICS_STR("#activity.txt | " + QTime::currentTime().toString() + " " + + QString("Toggle Cache (now ") + + ((storedFlag & IN_MEMORY) ? "enabled)" : "disabled)")); #endif - if (data.m_passiveCacheId == 0) - data.m_passiveCacheId = getNewPassiveCacheId(); + if (data.m_passiveCacheId == 0) + data.m_passiveCacheId = getNewPassiveCacheId(); - if ((storedFlag & ON_DISK) && !(oldFlag & ON_DISK)) { - ResourcesTable::ColIterator it = m_resources->getTable().colBegin(data.m_passiveCacheId); - for (; it; ++it) { - std::set &resources = *it; + if ((storedFlag & ON_DISK) && !(oldFlag & ON_DISK)) { + ResourcesTable::ColIterator it = + m_resources->getTable().colBegin(data.m_passiveCacheId); + for (; it; ++it) { + std::set &resources = *it; - std::set::iterator jt; - for (jt = resources.begin(); jt != resources.end(); ++jt) - (*jt)->enableBackup(); - } - } + std::set::iterator jt; + for (jt = resources.begin(); jt != resources.end(); ++jt) + (*jt)->enableBackup(); + } + } - //Implementa la versione contraria - eliminazione dell'fx nell'hdPool... - //Metti anche questo in versione ritardata con flush... Il flush e' da unificare... - //e magari da spostare direttamente nell'hdPool + // Implementa la versione contraria - eliminazione dell'fx nell'hdPool... + // Metti anche questo in versione ritardata con flush... Il flush e' da + // unificare... + // e magari da spostare direttamente nell'hdPool - if ((oldFlag & IN_MEMORY) && !(storedFlag & IN_MEMORY)) { - m_resources->getTable().erase(data.m_passiveCacheId); + if ((oldFlag & IN_MEMORY) && !(storedFlag & IN_MEMORY)) { + m_resources->getTable().erase(data.m_passiveCacheId); - data.m_fx = TFxP(); - data.m_treeDescription = ""; - } + data.m_fx = TFxP(); + data.m_treeDescription = ""; + } #ifndef USE_SQLITE_HDPOOL - if ((storedFlag & IN_MEMORY) && !(oldFlag & IN_MEMORY)) { - data.m_fx = fx; - (*m_descriptorCallback)(data.m_treeDescription, data.m_fx); - } + if ((storedFlag & IN_MEMORY) && !(oldFlag & IN_MEMORY)) { + data.m_fx = fx; + (*m_descriptorCallback)(data.m_treeDescription, data.m_fx); + } #endif #ifdef USE_SQLITE_HDPOOL - if ((oldFlag & ON_DISK) && !(storedFlag & ON_DISK)) - TCacheResourcePool::instance()->releaseReferences("P" + QString::number(data.m_passiveCacheId)); + if ((oldFlag & ON_DISK) && !(storedFlag & ON_DISK)) + TCacheResourcePool::instance()->releaseReferences( + "P" + QString::number(data.m_passiveCacheId)); #endif - } + } } //------------------------------------------------------------------------- -void TPassiveCacheManager::invalidateLevel(const std::string &levelName) -{ - QMutexLocker locker(&m_mutex); - - //Traverse the managed resources for passed levelName. - ResourcesTable &table = m_resources->getTable(); - ResourcesTable::Iterator it = table.begin(); - while (it) { - std::set &resources = *it; - std::set::iterator jt, kt; - for (jt = resources.begin(); jt != resources.end();) { - if ((*jt)->getName().find(levelName) != std::string::npos) { - kt = jt++; - it->erase(kt); - } else - ++jt; - } - - if (resources.empty()) - it = table.erase(it); - else - ++it; - } +void TPassiveCacheManager::invalidateLevel(const std::string &levelName) { + QMutexLocker locker(&m_mutex); + + // Traverse the managed resources for passed levelName. + ResourcesTable &table = m_resources->getTable(); + ResourcesTable::Iterator it = table.begin(); + while (it) { + std::set &resources = *it; + std::set::iterator jt, kt; + for (jt = resources.begin(); jt != resources.end();) { + if ((*jt)->getName().find(levelName) != std::string::npos) { + kt = jt++; + it->erase(kt); + } else + ++jt; + } + + if (resources.empty()) + it = table.erase(it); + else + ++it; + } #ifdef USE_SQLITE_HDPOOL - //Store the level name until the invalidation is forced - m_invalidatedLevels.insert(levelName); + // Store the level name until the invalidation is forced + m_invalidatedLevels.insert(levelName); #endif } //------------------------------------------------------------------------- -void TPassiveCacheManager::forceInvalidate() -{ +void TPassiveCacheManager::forceInvalidate() { #ifdef USE_SQLITE_HDPOOL - TCacheResourcePool *pool = TCacheResourcePool::instance(); + TCacheResourcePool *pool = TCacheResourcePool::instance(); - //Clear all invalidated levels from the resource pool - std::set::iterator it; - for (it = m_invalidatedLevels.begin(); it != m_invalidatedLevels.end(); ++it) - pool->clearKeyword(*it); + // Clear all invalidated levels from the resource pool + std::set::iterator it; + for (it = m_invalidatedLevels.begin(); it != m_invalidatedLevels.end(); ++it) + pool->clearKeyword(*it); - m_invalidatedLevels.clear(); + m_invalidatedLevels.clear(); #endif } //------------------------------------------------------------------------- -//Generate the fx's tree description. If it is contained in one of those -//stored with cached fxs, release their associated resources. -void TPassiveCacheManager::onFxChanged(const TFxP &fx) -{ +// Generate the fx's tree description. If it is contained in one of those +// stored with cached fxs, release their associated resources. +void TPassiveCacheManager::onFxChanged(const TFxP &fx) { #ifndef USE_SQLITE_HDPOOL - std::string fxTreeDescription; - (*m_descriptorCallback)(fxTreeDescription, fx); + std::string fxTreeDescription; + (*m_descriptorCallback)(fxTreeDescription, fx); - unsigned int count = m_fxDataVector.size(); - for (unsigned int i = 0; i < count; ++i) { - FxData &data = m_fxDataVector[i]; + unsigned int count = m_fxDataVector.size(); + for (unsigned int i = 0; i < count; ++i) { + FxData &data = m_fxDataVector[i]; - if (!data.m_fx) - continue; + if (!data.m_fx) continue; - if (data.m_treeDescription.find(fxTreeDescription) != std::string::npos) - m_resources->getTable().erase(data.m_passiveCacheId); - } + if (data.m_treeDescription.find(fxTreeDescription) != std::string::npos) + m_resources->getTable().erase(data.m_passiveCacheId); + } #endif } //------------------------------------------------------------------------- -//Regenerate the tree descriptions of cached fxs. If the new description does -//not match the previous one, release the associated resources. -void TPassiveCacheManager::onXsheetChanged() -{ +// Regenerate the tree descriptions of cached fxs. If the new description does +// not match the previous one, release the associated resources. +void TPassiveCacheManager::onXsheetChanged() { #ifndef USE_SQLITE_HDPOOL #ifdef DIAGNOSTICS - DIAGNOSTICS_STR("#activity.txt | " + QTime::currentTime().toString() + " XSheet changed"); + DIAGNOSTICS_STR("#activity.txt | " + QTime::currentTime().toString() + + " XSheet changed"); #endif - unsigned int count = m_fxDataVector.size(); - for (unsigned int i = 0; i < count; ++i) { - FxData &data = m_fxDataVector[i]; + unsigned int count = m_fxDataVector.size(); + for (unsigned int i = 0; i < count; ++i) { + FxData &data = m_fxDataVector[i]; - if (!data.m_fx) - continue; + if (!data.m_fx) continue; - std::string newTreeDescription; - (*m_descriptorCallback)(newTreeDescription, data.m_fx); + std::string newTreeDescription; + (*m_descriptorCallback)(newTreeDescription, data.m_fx); - if (data.m_treeDescription != newTreeDescription) { - m_resources->getTable().erase(data.m_passiveCacheId); - data.m_treeDescription = newTreeDescription; - } - } + if (data.m_treeDescription != newTreeDescription) { + m_resources->getTable().erase(data.m_passiveCacheId); + data.m_treeDescription = newTreeDescription; + } + } #endif } //------------------------------------------------------------------------- -void TPassiveCacheManager::getResource( - TCacheResourceP &resource, const std::string &alias, - const TFxP &fx, double frame, const TRenderSettings &rs, - ResourceDeclaration *resData) -{ - if (!(m_enabled && fx && rs.m_userCachable)) - return; +void TPassiveCacheManager::getResource(TCacheResourceP &resource, + const std::string &alias, const TFxP &fx, + double frame, const TRenderSettings &rs, + ResourceDeclaration *resData) { + if (!(m_enabled && fx && rs.m_userCachable)) return; - StorageFlag flag = getStorageMode(fx.getPointer()); - if (flag == NONE) - return; + StorageFlag flag = getStorageMode(fx.getPointer()); + if (flag == NONE) return; - std::string contextName(getContextName()); - if (contextName.empty()) - return; + std::string contextName(getContextName()); + if (contextName.empty()) return; - //Build a resource if none was passed. - if (!resource) - resource = TCacheResourceP(alias, true); + // Build a resource if none was passed. + if (!resource) resource = TCacheResourceP(alias, true); #ifdef USE_SQLITE_HDPOOL - if (flag & ON_DISK) { - resource->enableBackup(); - - int passiveCacheId = m_fxDataVector[fx->getAttributes()->passiveCacheDataIdx()].m_passiveCacheId; - TCacheResourcePool::instance()->addReference(resource, "P" + QString::number(passiveCacheId)); - } + if (flag & ON_DISK) { + resource->enableBackup(); + + int passiveCacheId = + m_fxDataVector[fx->getAttributes()->passiveCacheDataIdx()] + .m_passiveCacheId; + TCacheResourcePool::instance()->addReference( + resource, "P" + QString::number(passiveCacheId)); + } #endif - if (flag & IN_MEMORY) { - QMutexLocker locker(&m_mutex); + if (flag & IN_MEMORY) { + QMutexLocker locker(&m_mutex); - int passiveCacheId = m_fxDataVector[fx->getAttributes()->passiveCacheDataIdx()].m_passiveCacheId; - m_resources->getTable().value(contextName, passiveCacheId).insert(resource); - } + int passiveCacheId = + m_fxDataVector[fx->getAttributes()->passiveCacheDataIdx()] + .m_passiveCacheId; + m_resources->getTable().value(contextName, passiveCacheId).insert(resource); + } } //------------------------------------------------------------------------- -void TPassiveCacheManager::releaseContextNamesWithPrefix(const std::string &prefix) -{ - QMutexLocker locker(&m_mutex); +void TPassiveCacheManager::releaseContextNamesWithPrefix( + const std::string &prefix) { + QMutexLocker locker(&m_mutex); #ifdef DIAGNOSTICS - DIAGNOSTICS_STR("#activity.txt | " + QTime::currentTime().toString() + - " Release Context Name (" + QString::fromStdString(prefix) + ")"); + DIAGNOSTICS_STR("#activity.txt | " + QTime::currentTime().toString() + + " Release Context Name (" + QString::fromStdString(prefix) + + ")"); #endif - //Retrieve the context range - std::string prefixPlus1 = prefix; - prefixPlus1[prefix.size() - 1]++; - - { - std::map::iterator it, jt; - it = m_contextNames.lower_bound(prefix); - jt = m_contextNames.lower_bound(prefixPlus1); - m_contextNames.erase(it, jt); - } - - //Transfer to temporary - ResourcesTable &table = m_resources->getTable(); - std::map &rows = m_resources->getTable().rows(); - - std::map::iterator it, jt, kt; - it = rows.lower_bound(prefix); - jt = rows.lower_bound(prefixPlus1); - - std::string temporaryName("T"); - for (kt = it; kt != jt; ++kt) { - ResourcesTable::RowIterator lt(kt); - for (; lt; ++lt) - table.value(temporaryName, lt.col()).insert(lt->begin(), lt->end()); - } - rows.erase(it, jt == rows.end() ? rows.lower_bound(prefixPlus1) : jt); + // Retrieve the context range + std::string prefixPlus1 = prefix; + prefixPlus1[prefix.size() - 1]++; + + { + std::map::iterator it, jt; + it = m_contextNames.lower_bound(prefix); + jt = m_contextNames.lower_bound(prefixPlus1); + m_contextNames.erase(it, jt); + } + + // Transfer to temporary + ResourcesTable &table = m_resources->getTable(); + std::map &rows = + m_resources->getTable().rows(); + + std::map::iterator it, jt, kt; + it = rows.lower_bound(prefix); + jt = rows.lower_bound(prefixPlus1); + + std::string temporaryName("T"); + for (kt = it; kt != jt; ++kt) { + ResourcesTable::RowIterator lt(kt); + for (; lt; ++lt) + table.value(temporaryName, lt.col()).insert(lt->begin(), lt->end()); + } + rows.erase(it, jt == rows.end() ? rows.lower_bound(prefixPlus1) : jt); } //------------------------------------------------------------------------- -void TPassiveCacheManager::releaseOldResources() -{ - QMutexLocker locker(&m_mutex); - - //Release all the resources that were stored in the old render instance of the - //context, PLUS those of the temporary container. - //Resources that were held by the TPassiveCacheManager::getResource() procedure - //are now duplicated in a proper row of the table - and will not be freed. - std::string contextName(getContextName()); - if (contextName.empty()) - return; - - char &lastChar = contextName[contextName.size() - 1]; - lastChar = '0' + !(lastChar - '0'); - - ResourcesTable &table = m_resources->getTable(); - table.erase(contextName); - table.erase("T"); +void TPassiveCacheManager::releaseOldResources() { + QMutexLocker locker(&m_mutex); + + // Release all the resources that were stored in the old render instance of + // the + // context, PLUS those of the temporary container. + // Resources that were held by the TPassiveCacheManager::getResource() + // procedure + // are now duplicated in a proper row of the table - and will not be freed. + std::string contextName(getContextName()); + if (contextName.empty()) return; + + char &lastChar = contextName[contextName.size() - 1]; + lastChar = '0' + !(lastChar - '0'); + + ResourcesTable &table = m_resources->getTable(); + table.erase(contextName); + table.erase("T"); } //------------------------------------------------------------------------- -void TPassiveCacheManager::onRenderInstanceStart(unsigned long renderId) -{ - TFxCacheManagerDelegate::onRenderInstanceStart(renderId); +void TPassiveCacheManager::onRenderInstanceStart(unsigned long renderId) { + TFxCacheManagerDelegate::onRenderInstanceStart(renderId); #ifdef USE_SQLITE_HDPOOL - //Force invalidation of levels before the render starts - forceInvalidate(); + // Force invalidation of levels before the render starts + forceInvalidate(); #endif } //------------------------------------------------------------------------- -void TPassiveCacheManager::onRenderInstanceEnd(unsigned long renderId) -{ - QMutexLocker locker(&m_mutex); +void TPassiveCacheManager::onRenderInstanceEnd(unsigned long renderId) { + QMutexLocker locker(&m_mutex); - releaseOldResources(); - m_contextNamesByRenderId.erase(renderId); + releaseOldResources(); + m_contextNamesByRenderId.erase(renderId); } //------------------------------------------------------------------------- -void TPassiveCacheManager::onRenderStatusEnd(int renderStatus) -{ - if (renderStatus == TRenderer::TESTRUN) - releaseOldResources(); +void TPassiveCacheManager::onRenderStatusEnd(int renderStatus) { + if (renderStatus == TRenderer::TESTRUN) releaseOldResources(); } diff --git a/toonz/sources/common/tfx/tpredictivecachemanager.cpp b/toonz/sources/common/tfx/tpredictivecachemanager.cpp index 3be1eb0..89bba9f 100644 --- a/toonz/sources/common/tfx/tpredictivecachemanager.cpp +++ b/toonz/sources/common/tfx/tpredictivecachemanager.cpp @@ -11,29 +11,26 @@ // Preliminaries //************************************************************************************************ -class TPredictiveCacheManagerGenerator : public TRenderResourceManagerGenerator -{ +class TPredictiveCacheManagerGenerator + : public TRenderResourceManagerGenerator { public: - TPredictiveCacheManagerGenerator() : TRenderResourceManagerGenerator(true) {} + TPredictiveCacheManagerGenerator() : TRenderResourceManagerGenerator(true) {} - TRenderResourceManager *operator()(void) - { - return new TPredictiveCacheManager; - } + TRenderResourceManager *operator()(void) { + return new TPredictiveCacheManager; + } }; -MANAGER_FILESCOPE_DECLARATION_DEP( - TPredictiveCacheManager, - TPredictiveCacheManagerGenerator, - TFxCacheManager::deps()) +MANAGER_FILESCOPE_DECLARATION_DEP(TPredictiveCacheManager, + TPredictiveCacheManagerGenerator, + TFxCacheManager::deps()) //------------------------------------------------------------------------- -TPredictiveCacheManager *TPredictiveCacheManager::instance() -{ - return static_cast( - //TPredictiveCacheManager::gen()->getManager(TRenderer::instance()) - TPredictiveCacheManager::gen()->getManager(TRenderer::renderId())); +TPredictiveCacheManager *TPredictiveCacheManager::instance() { + return static_cast( + // TPredictiveCacheManager::gen()->getManager(TRenderer::instance()) + TPredictiveCacheManager::gen()->getManager(TRenderer::renderId())); } //************************************************************************************************ @@ -45,11 +42,11 @@ TPredictiveCacheManager *TPredictiveCacheManager::instance() //----------------------- struct PredictionData { - const ResourceDeclaration *m_decl; - int m_usageCount; + const ResourceDeclaration *m_decl; + int m_usageCount; - PredictionData(const ResourceDeclaration *declaration) - : m_decl(declaration), m_usageCount(1) {} + PredictionData(const ResourceDeclaration *declaration) + : m_decl(declaration), m_usageCount(1) {} }; //============================================================================================ @@ -58,47 +55,43 @@ struct PredictionData { // TPredictiveCacheManager::Imp //------------------------------------- -class TPredictiveCacheManager::Imp -{ +class TPredictiveCacheManager::Imp { public: - int m_renderStatus; - bool m_enabled; + int m_renderStatus; + bool m_enabled; - std::map m_resources; - QMutex m_mutex; + std::map m_resources; + QMutex m_mutex; public: - Imp() - : m_renderStatus(TRenderer::IDLE) - , m_enabled(TRenderer::instance().isPrecomputingEnabled()) - { - } - - void run(TCacheResourceP &resource, const std::string &alias, - const TFxP &fx, double frame, const TRenderSettings &rs, - ResourceDeclaration *resData) - { - switch (m_renderStatus) { - case TRenderer::IDLE: - case TRenderer::COMPUTING: - getResourceComputing(resource, alias, fx, frame, rs, resData); - break; - case TRenderer::TESTRUN: - getResourceTestRun(resource, alias, fx, frame, rs, resData); - break; - } - } + Imp() + : m_renderStatus(TRenderer::IDLE) + , m_enabled(TRenderer::instance().isPrecomputingEnabled()) {} + + void run(TCacheResourceP &resource, const std::string &alias, const TFxP &fx, + double frame, const TRenderSettings &rs, + ResourceDeclaration *resData) { + switch (m_renderStatus) { + case TRenderer::IDLE: + case TRenderer::COMPUTING: + getResourceComputing(resource, alias, fx, frame, rs, resData); + break; + case TRenderer::TESTRUN: + getResourceTestRun(resource, alias, fx, frame, rs, resData); + break; + } + } private: - void getResourceTestRun( - TCacheResourceP &resource, const std::string &alias, - const TFxP &fx, double frame, const TRenderSettings &rs, - ResourceDeclaration *resData); - - void getResourceComputing( - TCacheResourceP &resource, const std::string &alias, - const TFxP &fx, double frame, const TRenderSettings &rs, - ResourceDeclaration *resData); + void getResourceTestRun(TCacheResourceP &resource, const std::string &alias, + const TFxP &fx, double frame, + const TRenderSettings &rs, + ResourceDeclaration *resData); + + void getResourceComputing(TCacheResourceP &resource, const std::string &alias, + const TFxP &fx, double frame, + const TRenderSettings &rs, + ResourceDeclaration *resData); }; //************************************************************************************************ @@ -106,39 +99,30 @@ private: //************************************************************************************************ TPredictiveCacheManager::TPredictiveCacheManager() - : m_imp(new TPredictiveCacheManager::Imp()) -{ -} + : m_imp(new TPredictiveCacheManager::Imp()) {} //--------------------------------------------------------------------------- -TPredictiveCacheManager::~TPredictiveCacheManager() -{ -} +TPredictiveCacheManager::~TPredictiveCacheManager() {} //--------------------------------------------------------------------------- -void TPredictiveCacheManager::setMaxTileSize(int maxTileSize) -{ -} +void TPredictiveCacheManager::setMaxTileSize(int maxTileSize) {} //--------------------------------------------------------------------------- -void TPredictiveCacheManager::setBPP(int bpp) -{ -} +void TPredictiveCacheManager::setBPP(int bpp) {} //--------------------------------------------------------------------------- -void TPredictiveCacheManager::getResource( - TCacheResourceP &resource, const std::string &alias, - const TFxP &fx, double frame, const TRenderSettings &rs, - ResourceDeclaration *resData) -{ - if (!m_imp->m_enabled) - return; +void TPredictiveCacheManager::getResource(TCacheResourceP &resource, + const std::string &alias, + const TFxP &fx, double frame, + const TRenderSettings &rs, + ResourceDeclaration *resData) { + if (!m_imp->m_enabled) return; - m_imp->run(resource, alias, fx, frame, rs, resData); + m_imp->run(resource, alias, fx, frame, rs, resData); } //************************************************************************************************ @@ -146,98 +130,91 @@ void TPredictiveCacheManager::getResource( //************************************************************************************************ void TPredictiveCacheManager::Imp::getResourceTestRun( - TCacheResourceP &resource, const std::string &alias, - const TFxP &fx, double frame, const TRenderSettings &rs, - ResourceDeclaration *resData) -{ - assert(resData && resData->m_rawData); - if (!(resData && resData->m_rawData)) - //This is a very rare case. I've seen it happen once in a 'pathologic' case - //which involved affines truncation while building aliases. - //The rendering system didn't expect the truncated part 'resurface' in a - //downstream fx with a slightly different affine alias. - - //TODO: Affines should be coded completely in the aliases... in a compact way though. - return; - - if (!resource) - resource = TCacheResourceP(alias, true); - - //Lock against concurrent threads - //QMutexLocker locker(&m_mutex); //preComputing is currently single-threaded - - std::map::iterator it = - m_resources.find(resource); - - if (it != m_resources.end()) - it->second.m_usageCount++; - else { - //Already initializes usageCount at 1 - m_resources.insert(std::make_pair(resource, PredictionData(resData))).first; - } + TCacheResourceP &resource, const std::string &alias, const TFxP &fx, + double frame, const TRenderSettings &rs, ResourceDeclaration *resData) { + assert(resData && resData->m_rawData); + if (!(resData && resData->m_rawData)) + // This is a very rare case. I've seen it happen once in a 'pathologic' case + // which involved affines truncation while building aliases. + // The rendering system didn't expect the truncated part 'resurface' in a + // downstream fx with a slightly different affine alias. + + // TODO: Affines should be coded completely in the aliases... in a compact + // way though. + return; + + if (!resource) resource = TCacheResourceP(alias, true); + + // Lock against concurrent threads + // QMutexLocker locker(&m_mutex); //preComputing is currently + // single-threaded + + std::map::iterator it = + m_resources.find(resource); + + if (it != m_resources.end()) + it->second.m_usageCount++; + else { + // Already initializes usageCount at 1 + m_resources.insert(std::make_pair(resource, PredictionData(resData))).first; + } } //--------------------------------------------------------------------------- void TPredictiveCacheManager::Imp::getResourceComputing( - TCacheResourceP &resource, const std::string &alias, - const TFxP &fx, double frame, const TRenderSettings &rs, - ResourceDeclaration *resData) -{ - //If there is no declaration data, either the request can be resolved in one - //computation code (therefore it is uninteresting for us), or it was never declared. - //Anyway, return. - if (!resData) - return; + TCacheResourceP &resource, const std::string &alias, const TFxP &fx, + double frame, const TRenderSettings &rs, ResourceDeclaration *resData) { + // If there is no declaration data, either the request can be resolved in one + // computation code (therefore it is uninteresting for us), or it was never + // declared. + // Anyway, return. + if (!resData) return; - //NO! The refCount is dynamically depleted - could become 0 from n... - //assert(!(resData->m_tiles.size() == 1 && resData->m_tiles[0].m_refCount == 1)); + // NO! The refCount is dynamically depleted - could become 0 from n... + // assert(!(resData->m_tiles.size() == 1 && resData->m_tiles[0].m_refCount == + // 1)); - if (!resource) - resource = TCacheResourceP(alias); + if (!resource) resource = TCacheResourceP(alias); - if (!resource) - return; + if (!resource) return; - //Lock against concurrent threads - QMutexLocker locker(&m_mutex); + // Lock against concurrent threads + QMutexLocker locker(&m_mutex); - std::map::iterator it = - m_resources.find(resource); + std::map::iterator it = + m_resources.find(resource); - if (it == m_resources.end()) - return; + if (it == m_resources.end()) return; - if (--it->second.m_usageCount <= 0) - m_resources.erase(it); + if (--it->second.m_usageCount <= 0) m_resources.erase(it); } //--------------------------------------------------------------------------- -void TPredictiveCacheManager::onRenderStatusStart(int renderStatus) -{ - m_imp->m_renderStatus = renderStatus; +void TPredictiveCacheManager::onRenderStatusStart(int renderStatus) { + m_imp->m_renderStatus = renderStatus; } //--------------------------------------------------------------------------- -void TPredictiveCacheManager::onRenderStatusEnd(int renderStatus) -{ - switch (renderStatus) { - case TRenderer::TESTRUN: - - //All resources which have just 1 computation tile, which is also referenced - //only once, are released. - - std::map::iterator it; - for (it = m_imp->m_resources.begin(); it != m_imp->m_resources.end();) { - const ResourceDeclaration *decl = it->second.m_decl; - - if (decl->m_tiles.size() == 1 && decl->m_tiles[0].m_refCount == 1) { - std::map::iterator jt = it++; - m_imp->m_resources.erase(jt); - } else - it++; - } - } +void TPredictiveCacheManager::onRenderStatusEnd(int renderStatus) { + switch (renderStatus) { + case TRenderer::TESTRUN: + + // All resources which have just 1 computation tile, which is also + // referenced + // only once, are released. + + std::map::iterator it; + for (it = m_imp->m_resources.begin(); it != m_imp->m_resources.end();) { + const ResourceDeclaration *decl = it->second.m_decl; + + if (decl->m_tiles.size() == 1 && decl->m_tiles[0].m_refCount == 1) { + std::map::iterator jt = it++; + m_imp->m_resources.erase(jt); + } else + it++; + } + } } diff --git a/toonz/sources/common/tfx/trenderer.cpp b/toonz/sources/common/tfx/trenderer.cpp index 255d01d..19c77fd 100644 --- a/toonz/sources/common/tfx/trenderer.cpp +++ b/toonz/sources/common/tfx/trenderer.cpp @@ -29,7 +29,7 @@ // tcg includes #include "tcg/tcg_deleter_types.h" -//Debug +// Debug //#define DIAGNOSTICS //#include "diagnostics.h" @@ -44,50 +44,47 @@ std::vector calculateSortedFxs(TRasterFxP rootFx); // Preliminaries - Anonymous namespace //================================================================================ -namespace -{ -//TRenderer-thread association storage. It provides TRenderers the per-thread -//singleton status from inside a rendering process. +namespace { +// TRenderer-thread association storage. It provides TRenderers the per-thread +// singleton status from inside a rendering process. QThreadStorage rendererStorage; -//Same for render process ids. +// Same for render process ids. QThreadStorage renderIdsStorage; //------------------------------------------------------------------------------- -//Interlacing functions for field-based rendering -inline void interlace(TRasterP f0, const TRasterP &f1, int field) -{ - if (f0->getPixelSize() != f1->getPixelSize()) - throw TException("interlace: invalid raster combination"); - - assert(f0->getBounds() == f1->getBounds()); - - int outWrapBytes = f0->getWrap() * f0->getPixelSize(); - int inWrapBytes = f1->getWrap() * f1->getPixelSize(); - int outWrapBytes2 = outWrapBytes * 2; - int inWrapBytes2 = inWrapBytes * 2; - int rowSize = f0->getLx() * f0->getPixelSize(); - - f1->lock(); - f0->lock(); - UCHAR *rowIn = f1->getRawData(); - UCHAR *rowOut = f0->getRawData(); - - if (field) - rowIn += inWrapBytes; - - int count = f0->getLy() / 2; - while (--count) { - memcpy(rowOut, rowIn, rowSize); - rowIn += inWrapBytes2; - rowOut += outWrapBytes2; - } - - f1->unlock(); - f0->unlock(); +// Interlacing functions for field-based rendering +inline void interlace(TRasterP f0, const TRasterP &f1, int field) { + if (f0->getPixelSize() != f1->getPixelSize()) + throw TException("interlace: invalid raster combination"); + + assert(f0->getBounds() == f1->getBounds()); + + int outWrapBytes = f0->getWrap() * f0->getPixelSize(); + int inWrapBytes = f1->getWrap() * f1->getPixelSize(); + int outWrapBytes2 = outWrapBytes * 2; + int inWrapBytes2 = inWrapBytes * 2; + int rowSize = f0->getLx() * f0->getPixelSize(); + + f1->lock(); + f0->lock(); + UCHAR *rowIn = f1->getRawData(); + UCHAR *rowOut = f0->getRawData(); + + if (field) rowIn += inWrapBytes; + + int count = f0->getLy() / 2; + while (--count) { + memcpy(rowOut, rowIn, rowSize); + rowIn += inWrapBytes2; + rowOut += outWrapBytes2; + } + + f1->unlock(); + f0->unlock(); } -} // anonymous namespace +} // anonymous namespace //================================================================================ // Preliminaries - output rasters management @@ -97,60 +94,60 @@ inline void interlace(TRasterP f0, const TRasterP &f1, int field) // RasterItem //------------------- -//! The RasterItem class represents a reusable output raster for rendering purposes. -//! RasterItems are used as TRenderer's output rasters in order to avoid the overhead +//! The RasterItem class represents a reusable output raster for rendering +//! purposes. +//! RasterItems are used as TRenderer's output rasters in order to avoid the +//! overhead //! of allocating one raster for each rendered frame. -//! Each frame-rendering task will lock a RasterItem as preallocated output before starting the +//! Each frame-rendering task will lock a RasterItem as preallocated output +//! before starting the //! render, therefore changing the \b RasterItem::m_busy attribute accordingly. -//! As each frame is rendered on a separate thread, the number of RasterItems that -//! TRenderer will allocate depends on the number of rendering threads specified to it. +//! As each frame is rendered on a separate thread, the number of RasterItems +//! that +//! TRenderer will allocate depends on the number of rendering threads specified +//! to it. //! \sa RasterPool, TRenderer classes -class RasterItem -{ - std::string m_rasterId; +class RasterItem { + std::string m_rasterId; public: - int m_bpp; - bool m_busy; + int m_bpp; + bool m_busy; - //--------------------------------------------------------- + //--------------------------------------------------------- - RasterItem(const TDimension &size, int bpp, bool busyFlag) - : m_rasterId(""), m_bpp(bpp), m_busy(busyFlag) - { - TRasterP raster; - if (bpp == 32) - raster = TRaster32P(size); - else if (bpp == 64) - raster = TRaster64P(size); - else - assert(false); + RasterItem(const TDimension &size, int bpp, bool busyFlag) + : m_rasterId(""), m_bpp(bpp), m_busy(busyFlag) { + TRasterP raster; + if (bpp == 32) + raster = TRaster32P(size); + else if (bpp == 64) + raster = TRaster64P(size); + else + assert(false); - m_rasterId = TImageCache::instance()->getUniqueId(); - TImageCache::instance()->add(m_rasterId, TRasterImageP(raster)); - } + m_rasterId = TImageCache::instance()->getUniqueId(); + TImageCache::instance()->add(m_rasterId, TRasterImageP(raster)); + } - //--------------------------------------------------------- + //--------------------------------------------------------- - ~RasterItem() - { - TImageCache::instance()->remove(m_rasterId); - } + ~RasterItem() { TImageCache::instance()->remove(m_rasterId); } - //--------------------------------------------------------- + //--------------------------------------------------------- - TRasterP getRaster() const - { - TRasterImageP rimg = (TRasterImageP)TImageCache::instance()->get(m_rasterId, true); - return rimg ? rimg->getRaster() : TRasterP(); - } + TRasterP getRaster() const { + TRasterImageP rimg = + (TRasterImageP)TImageCache::instance()->get(m_rasterId, true); + return rimg ? rimg->getRaster() : TRasterP(); + } private: - //not implemented - RasterItem(); - RasterItem(const TRaster &RasterItem); + // not implemented + RasterItem(); + RasterItem(const TRaster &RasterItem); }; //================================================================================ @@ -160,125 +157,117 @@ private: //------------------- //! Stores a list of RasterItems under TRenderer's requests. -class RasterPool -{ - TDimension m_size; - int m_bpp; +class RasterPool { + TDimension m_size; + int m_bpp; - typedef std::list RasterRepository; - RasterRepository m_rasterRepository; + typedef std::list RasterRepository; + RasterRepository m_rasterRepository; - TThread::Mutex m_repositoryLock; + TThread::Mutex m_repositoryLock; public: - RasterPool() : m_size(-1, -1) {} - ~RasterPool(); + RasterPool() : m_size(-1, -1) {} + ~RasterPool(); - void setRasterSpecs(const TDimension &size, int bpp); - void getRasterSpecs(TDimension &size, int &bpp) - { - size = m_size; - bpp = m_bpp; - } + void setRasterSpecs(const TDimension &size, int bpp); + void getRasterSpecs(TDimension &size, int &bpp) { + size = m_size; + bpp = m_bpp; + } - TRasterP getRaster(); - TRasterP getRaster(const TDimension &size, int bpp); + TRasterP getRaster(); + TRasterP getRaster(const TDimension &size, int bpp); - void releaseRaster(const TRasterP &r); + void releaseRaster(const TRasterP &r); - void clear(); + void clear(); }; //--------------------------------------------------------- -void RasterPool::clear() -{ - QMutexLocker sl(&m_repositoryLock); - clearPointerContainer(m_rasterRepository); +void RasterPool::clear() { + QMutexLocker sl(&m_repositoryLock); + clearPointerContainer(m_rasterRepository); } //--------------------------------------------------------- -void RasterPool::setRasterSpecs(const TDimension &size, int bpp) -{ - if (size != m_size || bpp != m_bpp) { - m_size = size; - m_bpp = bpp; - clear(); - } +void RasterPool::setRasterSpecs(const TDimension &size, int bpp) { + if (size != m_size || bpp != m_bpp) { + m_size = size; + m_bpp = bpp; + clear(); + } } //--------------------------------------------------------- -TRasterP RasterPool::getRaster(const TDimension &size, int bpp) -{ - assert(size == m_size && bpp == m_bpp); - return getRaster(); +TRasterP RasterPool::getRaster(const TDimension &size, int bpp) { + assert(size == m_size && bpp == m_bpp); + return getRaster(); } //--------------------------------------------------------- -//!Returns for the first not-busy raster -TRasterP RasterPool::getRaster() -{ - QMutexLocker sl(&m_repositoryLock); +//! Returns for the first not-busy raster +TRasterP RasterPool::getRaster() { + QMutexLocker sl(&m_repositoryLock); - RasterRepository::iterator it = m_rasterRepository.begin(); - while (it != m_rasterRepository.end()) { - RasterItem *rasItem = *it; - if (rasItem->m_busy == false) { - TRasterP raster = rasItem->getRaster(); + RasterRepository::iterator it = m_rasterRepository.begin(); + while (it != m_rasterRepository.end()) { + RasterItem *rasItem = *it; + if (rasItem->m_busy == false) { + TRasterP raster = rasItem->getRaster(); - if (!raster) { - delete rasItem; - m_rasterRepository.erase(it++); - continue; - } + if (!raster) { + delete rasItem; + m_rasterRepository.erase(it++); + continue; + } - rasItem->m_busy = true; - raster->clear(); - return raster; - } + rasItem->m_busy = true; + raster->clear(); + return raster; + } - ++it; - } + ++it; + } - RasterItem *rasItem = new RasterItem(m_size, m_bpp, true); - m_rasterRepository.push_back(rasItem); + RasterItem *rasItem = new RasterItem(m_size, m_bpp, true); + m_rasterRepository.push_back(rasItem); - return rasItem->getRaster(); + return rasItem->getRaster(); } //--------------------------------------------------------- -//!Cerca il raster \b r in m_rasterRepository; se lo trova setta a \b false il campo \b m_busy. -void RasterPool::releaseRaster(const TRasterP &r) -{ - if (!r) - return; - - QMutexLocker sl(&m_repositoryLock); - for (RasterRepository::iterator it = m_rasterRepository.begin(); - it != m_rasterRepository.end(); - ++it) { - RasterItem *rasItem = *it; - if (rasItem->getRaster()->getRawData() == r->getRawData()) { - assert(rasItem->m_busy); - rasItem->m_busy = false; - return; - } - } +//! Cerca il raster \b r in m_rasterRepository; se lo trova setta a \b false il +//! campo \b m_busy. +void RasterPool::releaseRaster(const TRasterP &r) { + if (!r) return; + + QMutexLocker sl(&m_repositoryLock); + for (RasterRepository::iterator it = m_rasterRepository.begin(); + it != m_rasterRepository.end(); ++it) { + RasterItem *rasItem = *it; + if (rasItem->getRaster()->getRawData() == r->getRawData()) { + assert(rasItem->m_busy); + rasItem->m_busy = false; + return; + } + } } //--------------------------------------------------------- -RasterPool::~RasterPool() -{ - /*if (m_rasterRepository.size()) - TSystem::outputDebug("~RasterPool: itemCount = " + toString ((int)m_rasterRepository.size())+" (should be 0)\n");*/ +RasterPool::~RasterPool() { + /*if (m_rasterRepository.size()) +TSystem::outputDebug("~RasterPool: itemCount = " + toString +((int)m_rasterRepository.size())+" (should be 0)\n");*/ - //Release all raster items - clear(); + // Release all raster items + clear(); } //================================================================================ @@ -289,84 +278,85 @@ RasterPool::~RasterPool() // TRendererImp //--------------------- -class TRendererImp : public TSmartObject -{ +class TRendererImp : public TSmartObject { public: - struct RenderInstanceInfos { - int m_canceled; - int m_activeTasks; - int m_status; + struct RenderInstanceInfos { + int m_canceled; + int m_activeTasks; + int m_status; - RenderInstanceInfos() - : m_canceled(false), m_activeTasks(0), m_status(TRenderer::IDLE) {} - }; + RenderInstanceInfos() + : m_canceled(false), m_activeTasks(0), m_status(TRenderer::IDLE) {} + }; public: - typedef std::vector PortContainer; - typedef PortContainer::iterator PortContainerIterator; + typedef std::vector PortContainer; + typedef PortContainer::iterator PortContainerIterator; - QReadWriteLock m_portsLock; - PortContainer m_ports; + QReadWriteLock m_portsLock; + PortContainer m_ports; - QMutex m_renderInstancesMutex; - std::map m_activeInstances; + QMutex m_renderInstancesMutex; + std::map m_activeInstances; - //! The renderer Id is a number uniquely associated with a TRenderer instance. - static unsigned long m_rendererIdCounter; + //! The renderer Id is a number uniquely associated with a TRenderer instance. + static unsigned long m_rendererIdCounter; - //! The render Id is a number uniquely associated with a render process started - //! with the startRendering() method. - static unsigned long m_renderIdCounter; + //! The render Id is a number uniquely associated with a render process + //! started + //! with the startRendering() method. + static unsigned long m_renderIdCounter; - unsigned long m_rendererId; + unsigned long m_rendererId; - Executor m_executor; + Executor m_executor; - bool m_precomputingEnabled; - RasterPool m_rasterPool; + bool m_precomputingEnabled; + RasterPool m_rasterPool; - std::vector m_managers; + std::vector m_managers; - TAtomicVar m_undoneTasks; - //std::vector m_waitingLoops; - std::vector m_waitingLoops; + TAtomicVar m_undoneTasks; + // std::vector m_waitingLoops; + std::vector m_waitingLoops; - TRasterFxP rootFx; + TRasterFxP rootFx; - //------------------------------------------------------------- + //------------------------------------------------------------- - TRendererImp(int nThreads); - ~TRendererImp(); + TRendererImp(int nThreads); + ~TRendererImp(); - void startRendering(unsigned long renderId, const std::vector &renderDatas); + void startRendering(unsigned long renderId, + const std::vector &renderDatas); - void notifyRasterStarted(const TRenderPort::RenderData &rd); - void notifyRasterCompleted(const TRenderPort::RenderData &rd); - void notifyRasterFailure(const TRenderPort::RenderData &rd, TException &e); - void notifyRenderFinished(bool isCanceled = false); + void notifyRasterStarted(const TRenderPort::RenderData &rd); + void notifyRasterCompleted(const TRenderPort::RenderData &rd); + void notifyRasterFailure(const TRenderPort::RenderData &rd, TException &e); + void notifyRenderFinished(bool isCanceled = false); - void addPort(TRenderPort *port); - void removePort(TRenderPort *port); + void addPort(TRenderPort *port); + void removePort(TRenderPort *port); - void abortRendering(unsigned long renderId); - void stopRendering(bool waitForCompleteStop); + void abortRendering(unsigned long renderId); + void stopRendering(bool waitForCompleteStop); - bool hasToDie(unsigned long renderId); - int getRenderStatus(unsigned long renderId); + bool hasToDie(unsigned long renderId); + int getRenderStatus(unsigned long renderId); - void enablePrecomputing(bool on) { m_precomputingEnabled = on; } - bool isPrecomputingEnabled() const { return m_precomputingEnabled; } + void enablePrecomputing(bool on) { m_precomputingEnabled = on; } + bool isPrecomputingEnabled() const { return m_precomputingEnabled; } - void setThreadsCount(int nThreads) { m_executor.setMaxActiveTasks(nThreads); } + void setThreadsCount(int nThreads) { m_executor.setMaxActiveTasks(nThreads); } - inline void declareRenderStart(unsigned long renderId); - inline void declareRenderEnd(unsigned long renderId); - inline void declareFrameStart(double frame); - inline void declareFrameEnd(double frame); - inline void declareStatusStart(int renderStatus); - inline void declareStatusEnd(int renderStatus); + inline void declareRenderStart(unsigned long renderId); + inline void declareRenderEnd(unsigned long renderId); + inline void declareFrameStart(double frame); + inline void declareFrameEnd(double frame); + inline void declareStatusStart(int renderStatus); + inline void declareStatusEnd(int renderStatus); - void quitWaitingLoops(); + void quitWaitingLoops(); }; #ifdef _WIN32 @@ -376,7 +366,7 @@ template class DVAPI TSmartPointerT; typedef TSmartPointerT TRendererImpP; unsigned long TRendererImp::m_rendererIdCounter = 0; -unsigned long TRendererImp::m_renderIdCounter = 0; +unsigned long TRendererImp::m_renderIdCounter = 0; //================================================================================ @@ -384,49 +374,50 @@ unsigned long TRendererImp::m_renderIdCounter = 0; // RenderTask //------------------- -class RenderTask : public TThread::Runnable -{ - std::vector m_frames; +class RenderTask : public TThread::Runnable { + std::vector m_frames; - unsigned long m_taskId; - unsigned long m_renderId; + unsigned long m_taskId; + unsigned long m_renderId; - TRendererImpP m_rendererImp; + TRendererImpP m_rendererImp; - TFxPair m_fx; - TPointD m_framePos; - TDimension m_frameSize; - TRenderSettings m_info; + TFxPair m_fx; + TPointD m_framePos; + TDimension m_frameSize; + TRenderSettings m_info; - bool m_fieldRender, m_stereoscopic; + bool m_fieldRender, m_stereoscopic; - Mutex m_rasterGuard; - TTile m_tileA; //in normal and field rendering, Rendered at given frame; in stereoscopic, rendered left frame - TTile m_tileB; //in field rendering, rendered at frame + 0.5; in stereoscopic, rendered right frame + Mutex m_rasterGuard; + TTile m_tileA; // in normal and field rendering, Rendered at given frame; in + // stereoscopic, rendered left frame + TTile m_tileB; // in field rendering, rendered at frame + 0.5; in + // stereoscopic, rendered right frame public: - RenderTask(unsigned long renderId, unsigned long taskId, - double frame, const TRenderSettings &ri, const TFxPair &fx, - const TPointD &framePos, const TDimension &frameSize, - const TRendererImpP &rendererImp); + RenderTask(unsigned long renderId, unsigned long taskId, double frame, + const TRenderSettings &ri, const TFxPair &fx, + const TPointD &framePos, const TDimension &frameSize, + const TRendererImpP &rendererImp); - ~RenderTask() {} + ~RenderTask() {} - void addFrame(double frame) { m_frames.push_back(frame); } + void addFrame(double frame) { m_frames.push_back(frame); } - void buildTile(TTile &tile); - void releaseTiles(); + void buildTile(TTile &tile); + void releaseTiles(); - void onFrameStarted(); - void onFrameCompleted(); - void onFrameFailed(TException &e); + void onFrameStarted(); + void onFrameCompleted(); + void onFrameFailed(TException &e); - void preRun(); - void run(); + void preRun(); + void run(); - int taskLoad() { return 100; } + int taskLoad() { return 100; } - void onFinished(TThread::RunnableP); + void onFinished(TThread::RunnableP); }; //================================================================================ @@ -437,84 +428,67 @@ public: // TRenderer //------------------ -TRenderer::TRenderer(int nThread) -{ - m_imp = new TRendererImp(nThread); //Already adds a ref +TRenderer::TRenderer(int nThread) { + m_imp = new TRendererImp(nThread); // Already adds a ref } //--------------------------------------------------------- -TRenderer::TRenderer(TRendererImp *imp) - : m_imp(imp) -{ - if (m_imp) - m_imp->addRef(); +TRenderer::TRenderer(TRendererImp *imp) : m_imp(imp) { + if (m_imp) m_imp->addRef(); } //--------------------------------------------------------- -TRenderer::TRenderer(const TRenderer &r) - : m_imp(r.m_imp) -{ - if (m_imp) - m_imp->addRef(); +TRenderer::TRenderer(const TRenderer &r) : m_imp(r.m_imp) { + if (m_imp) m_imp->addRef(); } //--------------------------------------------------------- -void TRenderer::operator=(const TRenderer &r) -{ - m_imp = r.m_imp; - if (m_imp) - m_imp->addRef(); +void TRenderer::operator=(const TRenderer &r) { + m_imp = r.m_imp; + if (m_imp) m_imp->addRef(); } //--------------------------------------------------------- -TRenderer::~TRenderer() -{ - if (m_imp) - m_imp->release(); +TRenderer::~TRenderer() { + if (m_imp) m_imp->release(); } //--------------------------------------------------------- -//! The static method is intended for use inside a rendering thread only. It returns +//! The static method is intended for use inside a rendering thread only. It +//! returns //! a copy of the eventual TRenderer interface installed on the thread - //! or an empty TRenderer if none happened to be. It can be set using the //! install() and uninstall() methods. -TRenderer TRenderer::instance() -{ - TRendererImp **lData = rendererStorage.localData(); - if (lData) - return TRenderer(*lData); - return 0; +TRenderer TRenderer::instance() { + TRendererImp **lData = rendererStorage.localData(); + if (lData) return TRenderer(*lData); + return 0; } //--------------------------------------------------------- //! Returns the renderer id. -unsigned long TRenderer::rendererId() -{ - return m_imp->m_rendererId; -} +unsigned long TRenderer::rendererId() { return m_imp->m_rendererId; } //--------------------------------------------------------- //! Returns the rendering process id currently running on the invoking //! thread. -unsigned long TRenderer::renderId() -{ - unsigned long *lData = renderIdsStorage.localData(); - return lData ? *lData : -1; +unsigned long TRenderer::renderId() { + unsigned long *lData = renderIdsStorage.localData(); + return lData ? *lData : -1; } //--------------------------------------------------------- //! Builds and returns an id for starting a new rendering process. -unsigned long TRenderer::buildRenderId() -{ - return TRendererImp::m_renderIdCounter++; +unsigned long TRenderer::buildRenderId() { + return TRendererImp::m_renderIdCounter++; } //--------------------------------------------------------- @@ -523,214 +497,181 @@ unsigned long TRenderer::buildRenderId() //! This method can be used to retrieve the renderId of a rendering instance //! before it is actually started - provided that no other render instance //! is launched inbetween. -unsigned long TRenderer::nextRenderId() -{ - return TRendererImp::m_renderIdCounter; +unsigned long TRenderer::nextRenderId() { + return TRendererImp::m_renderIdCounter; } //--------------------------------------------------------- -inline void TRendererImp::declareRenderStart(unsigned long renderId) -{ - //Inform the resource managers - for (unsigned int i = 0; i < m_managers.size(); ++i) - m_managers[i]->onRenderInstanceStart(renderId); +inline void TRendererImp::declareRenderStart(unsigned long renderId) { + // Inform the resource managers + for (unsigned int i = 0; i < m_managers.size(); ++i) + m_managers[i]->onRenderInstanceStart(renderId); } //! Declares that the render process of passed renderId is about to start. -void TRenderer::declareRenderStart(unsigned long renderId) -{ - m_imp->declareRenderStart(renderId); +void TRenderer::declareRenderStart(unsigned long renderId) { + m_imp->declareRenderStart(renderId); } //--------------------------------------------------------- -inline void TRendererImp::declareRenderEnd(unsigned long renderId) -{ - //Inform the resource managers - for (int i = m_managers.size() - 1; i >= 0; --i) - m_managers[i]->onRenderInstanceEnd(renderId); +inline void TRendererImp::declareRenderEnd(unsigned long renderId) { + // Inform the resource managers + for (int i = m_managers.size() - 1; i >= 0; --i) + m_managers[i]->onRenderInstanceEnd(renderId); } //! Declares that the render process of passed renderId has ended. -void TRenderer::declareRenderEnd(unsigned long renderId) -{ - m_imp->declareRenderEnd(renderId); +void TRenderer::declareRenderEnd(unsigned long renderId) { + m_imp->declareRenderEnd(renderId); } //--------------------------------------------------------- -inline void TRendererImp::declareFrameStart(double frame) -{ - //Inform the resource managers - for (unsigned int i = 0; i < m_managers.size(); ++i) - m_managers[i]->onRenderFrameStart(frame); +inline void TRendererImp::declareFrameStart(double frame) { + // Inform the resource managers + for (unsigned int i = 0; i < m_managers.size(); ++i) + m_managers[i]->onRenderFrameStart(frame); } //! Declares that render of passed frame is about to start. -void TRenderer::declareFrameStart(double frame) -{ - m_imp->declareFrameStart(frame); +void TRenderer::declareFrameStart(double frame) { + m_imp->declareFrameStart(frame); } //--------------------------------------------------------- -inline void TRendererImp::declareFrameEnd(double frame) -{ - //Inform the resource managers - for (int i = m_managers.size() - 1; i >= 0; --i) - m_managers[i]->onRenderFrameEnd(frame); +inline void TRendererImp::declareFrameEnd(double frame) { + // Inform the resource managers + for (int i = m_managers.size() - 1; i >= 0; --i) + m_managers[i]->onRenderFrameEnd(frame); } //! Declares that render of passed has ended. -void TRenderer::declareFrameEnd(double frame) -{ - m_imp->declareFrameEnd(frame); -} +void TRenderer::declareFrameEnd(double frame) { m_imp->declareFrameEnd(frame); } //--------------------------------------------------------- -inline void TRendererImp::declareStatusStart(int renderStatus) -{ - //Inform the resource managers - for (unsigned int i = 0; i < m_managers.size(); ++i) - m_managers[i]->onRenderStatusStart(renderStatus); +inline void TRendererImp::declareStatusStart(int renderStatus) { + // Inform the resource managers + for (unsigned int i = 0; i < m_managers.size(); ++i) + m_managers[i]->onRenderStatusStart(renderStatus); } //--------------------------------------------------------- -inline void TRendererImp::declareStatusEnd(int renderStatus) -{ - //Inform the resource managers - for (int i = m_managers.size() - 1; i >= 0; --i) - m_managers[i]->onRenderStatusEnd(renderStatus); +inline void TRendererImp::declareStatusEnd(int renderStatus) { + // Inform the resource managers + for (int i = m_managers.size() - 1; i >= 0; --i) + m_managers[i]->onRenderStatusEnd(renderStatus); } //--------------------------------------------------------- //! Installs the specified render process on the invoking thread. -void TRenderer::install(unsigned long renderId) -{ - m_imp->addRef(); - rendererStorage.setLocalData(new (TRendererImp *)(m_imp)); - renderIdsStorage.setLocalData(new unsigned long(renderId)); +void TRenderer::install(unsigned long renderId) { + m_imp->addRef(); + rendererStorage.setLocalData(new (TRendererImp *)(m_imp)); + renderIdsStorage.setLocalData(new unsigned long(renderId)); } //--------------------------------------------------------- //! Uninstalls any rendering process active on the invoking thread. -void TRenderer::uninstall() -{ - rendererStorage.setLocalData(0); - renderIdsStorage.setLocalData(0); - m_imp->release(); +void TRenderer::uninstall() { + rendererStorage.setLocalData(0); + renderIdsStorage.setLocalData(0); + m_imp->release(); } //--------------------------------------------------------- -TRenderResourceManager *TRenderer::getManager(unsigned int id) const -{ - return m_imp->m_managers[id]; +TRenderResourceManager *TRenderer::getManager(unsigned int id) const { + return m_imp->m_managers[id]; } //--------------------------------------------------------- -void TRenderer::enablePrecomputing(bool on) -{ - m_imp->enablePrecomputing(on); -} +void TRenderer::enablePrecomputing(bool on) { m_imp->enablePrecomputing(on); } //--------------------------------------------------------- -bool TRenderer::isPrecomputingEnabled() const -{ - return m_imp->isPrecomputingEnabled(); +bool TRenderer::isPrecomputingEnabled() const { + return m_imp->isPrecomputingEnabled(); } //--------------------------------------------------------- -void TRenderer::setThreadsCount(int nThreads) -{ - m_imp->setThreadsCount(nThreads); +void TRenderer::setThreadsCount(int nThreads) { + m_imp->setThreadsCount(nThreads); } //--------------------------------------------------------- -void TRenderer::addPort(TRenderPort *port) -{ - m_imp->addPort(port); -} +void TRenderer::addPort(TRenderPort *port) { m_imp->addPort(port); } //--------------------------------------------------------- -void TRenderer::removePort(TRenderPort *port) -{ - m_imp->removePort(port); -} +void TRenderer::removePort(TRenderPort *port) { m_imp->removePort(port); } //--------------------------------------------------------- -unsigned long TRenderer::startRendering( - double f, - const TRenderSettings &info, - const TFxPair &actualRoot) -{ - assert(f >= 0); - - std::vector *rds = new std::vector; - rds->push_back(RenderData(f, info, actualRoot)); - return startRendering(rds); +unsigned long TRenderer::startRendering(double f, const TRenderSettings &info, + const TFxPair &actualRoot) { + assert(f >= 0); + + std::vector *rds = new std::vector; + rds->push_back(RenderData(f, info, actualRoot)); + return startRendering(rds); } //--------------------------------------------------------- //! Queues a rendering event in the main event loop. -//! NOTE: The passed pointer is owned by the TRenderer after it is submitted for rendering - +//! NOTE: The passed pointer is owned by the TRenderer after it is submitted for +//! rendering - //! do not delete it later. -unsigned long TRenderer::startRendering(const std::vector *renderDatas) -{ - if (renderDatas->empty()) { - delete renderDatas; - return -1; - } - - //Build a new render Id - unsigned long renderId = m_imp->m_renderIdCounter++; - - TRendererStartInvoker::StartInvokerRenderData srd; - srd.m_renderId = renderId; - srd.m_renderDataVector = renderDatas; - TRendererStartInvoker::instance()->emitStartRender(m_imp, srd); - - return renderId; +unsigned long TRenderer::startRendering( + const std::vector *renderDatas) { + if (renderDatas->empty()) { + delete renderDatas; + return -1; + } + + // Build a new render Id + unsigned long renderId = m_imp->m_renderIdCounter++; + + TRendererStartInvoker::StartInvokerRenderData srd; + srd.m_renderId = renderId; + srd.m_renderDataVector = renderDatas; + TRendererStartInvoker::instance()->emitStartRender(m_imp, srd); + + return renderId; } //--------------------------------------------------------- -void TRenderer::abortRendering(unsigned long renderId) -{ - m_imp->abortRendering(renderId); +void TRenderer::abortRendering(unsigned long renderId) { + m_imp->abortRendering(renderId); } //--------------------------------------------------------- -void TRenderer::stopRendering(bool waitForCompleteStop) -{ - m_imp->stopRendering(waitForCompleteStop); +void TRenderer::stopRendering(bool waitForCompleteStop) { + m_imp->stopRendering(waitForCompleteStop); } //--------------------------------------------------------- -bool TRenderer::isAborted(unsigned long renderId) const -{ - return m_imp->hasToDie(renderId); +bool TRenderer::isAborted(unsigned long renderId) const { + return m_imp->hasToDie(renderId); } //--------------------------------------------------------- -int TRenderer::getRenderStatus(unsigned long renderId) const -{ - return m_imp->getRenderStatus(renderId); +int TRenderer::getRenderStatus(unsigned long renderId) const { + return m_imp->getRenderStatus(renderId); } //================================================================================ @@ -740,206 +681,204 @@ int TRenderer::getRenderStatus(unsigned long renderId) const //--------------------- TRendererImp::TRendererImp(int nThreads) - : m_executor(), m_undoneTasks(), m_rendererId(m_rendererIdCounter++), m_precomputingEnabled(true) -{ - m_executor.setMaxActiveTasks(nThreads); + : m_executor() + , m_undoneTasks() + , m_rendererId(m_rendererIdCounter++) + , m_precomputingEnabled(true) { + m_executor.setMaxActiveTasks(nThreads); - std::vector &generators = - TRenderResourceManagerGenerator::generators(false); + std::vector &generators = + TRenderResourceManagerGenerator::generators(false); - //May be adopted by other TRenderers from now on. - addRef(); + // May be adopted by other TRenderers from now on. + addRef(); - rendererStorage.setLocalData(new (TRendererImp *)(this)); + rendererStorage.setLocalData(new (TRendererImp *)(this)); - unsigned int i; - for (i = 0; i < generators.size(); ++i) { - TRenderResourceManager *manager = (*generators[i])(); - if (manager) - m_managers.push_back(manager); - } + unsigned int i; + for (i = 0; i < generators.size(); ++i) { + TRenderResourceManager *manager = (*generators[i])(); + if (manager) m_managers.push_back(manager); + } - rendererStorage.setLocalData(0); + rendererStorage.setLocalData(0); } //--------------------------------------------------------- -TRendererImp::~TRendererImp() -{ - rendererStorage.setLocalData(new (TRendererImp *)(this)); +TRendererImp::~TRendererImp() { + rendererStorage.setLocalData(new (TRendererImp *)(this)); - int i; - for (i = m_managers.size() - 1; i >= 0; --i) - if (m_managers[i]->renderHasOwnership()) - delete m_managers[i]; + int i; + for (i = m_managers.size() - 1; i >= 0; --i) + if (m_managers[i]->renderHasOwnership()) delete m_managers[i]; - rendererStorage.setLocalData(0); + rendererStorage.setLocalData(0); } //--------------------------------------------------------- -void TRendererImp::addPort(TRenderPort *port) -{ - QWriteLocker sl(&m_portsLock); +void TRendererImp::addPort(TRenderPort *port) { + QWriteLocker sl(&m_portsLock); - PortContainerIterator it = std::find(m_ports.begin(), m_ports.end(), port); - if (it == m_ports.end()) - m_ports.push_back(port); + PortContainerIterator it = std::find(m_ports.begin(), m_ports.end(), port); + if (it == m_ports.end()) m_ports.push_back(port); } //--------------------------------------------------------- -void TRendererImp::removePort(TRenderPort *port) -{ - QWriteLocker sl(&m_portsLock); +void TRendererImp::removePort(TRenderPort *port) { + QWriteLocker sl(&m_portsLock); - PortContainerIterator it = std::find(m_ports.begin(), m_ports.end(), port); - if (it != m_ports.end()) - m_ports.erase(it); + PortContainerIterator it = std::find(m_ports.begin(), m_ports.end(), port); + if (it != m_ports.end()) m_ports.erase(it); } //--------------------------------------------------------- -bool TRendererImp::hasToDie(unsigned long renderId) -{ - QMutexLocker sl(&m_renderInstancesMutex); +bool TRendererImp::hasToDie(unsigned long renderId) { + QMutexLocker sl(&m_renderInstancesMutex); - std::map::iterator it = m_activeInstances.find(renderId); - assert(it != m_activeInstances.end()); - return it == m_activeInstances.end() ? true : it->second.m_canceled; + std::map::iterator it = + m_activeInstances.find(renderId); + assert(it != m_activeInstances.end()); + return it == m_activeInstances.end() ? true : it->second.m_canceled; } //--------------------------------------------------------- -int TRendererImp::getRenderStatus(unsigned long renderId) -{ - QMutexLocker sl(&m_renderInstancesMutex); +int TRendererImp::getRenderStatus(unsigned long renderId) { + QMutexLocker sl(&m_renderInstancesMutex); - std::map::iterator it = m_activeInstances.find(renderId); - assert(it != m_activeInstances.end()); - return it == m_activeInstances.end() ? true : it->second.m_status; + std::map::iterator it = + m_activeInstances.find(renderId); + assert(it != m_activeInstances.end()); + return it == m_activeInstances.end() ? true : it->second.m_status; } //--------------------------------------------------------- -void TRendererImp::abortRendering(unsigned long renderId) -{ - QMutexLocker sl(&m_renderInstancesMutex); +void TRendererImp::abortRendering(unsigned long renderId) { + QMutexLocker sl(&m_renderInstancesMutex); - std::map::iterator it = m_activeInstances.find(renderId); - if (it != m_activeInstances.end()) - it->second.m_canceled = true; + std::map::iterator it = + m_activeInstances.find(renderId); + if (it != m_activeInstances.end()) it->second.m_canceled = true; } //--------------------------------------------------------- -void TRendererImp::stopRendering(bool waitForCompleteStop) -{ - QMutexLocker sl(&m_renderInstancesMutex); +void TRendererImp::stopRendering(bool waitForCompleteStop) { + QMutexLocker sl(&m_renderInstancesMutex); - { - //Tasks already stop rendering on their own when they don't find their render ids here. - std::map::iterator it; - for (it = m_activeInstances.begin(); it != m_activeInstances.end(); ++it) - it->second.m_canceled = true; - } + { + // Tasks already stop rendering on their own when they don't find their + // render ids here. + std::map::iterator it; + for (it = m_activeInstances.begin(); it != m_activeInstances.end(); ++it) + it->second.m_canceled = true; + } - if (waitForCompleteStop && m_undoneTasks > 0) { - //Sometimes, QEventLoop suddenly stops processing slots (especially those notifications - //from active rendering instances) - therefore resulting in a block of the application. - //I've not figured out why (#QTBUG-11649?) - but substituting with a plain while - //seems to do the trick... + if (waitForCompleteStop && m_undoneTasks > 0) { + // Sometimes, QEventLoop suddenly stops processing slots (especially those + // notifications + // from active rendering instances) - therefore resulting in a block of the + // application. + // I've not figured out why (#QTBUG-11649?) - but substituting with a plain + // while + // seems to do the trick... - /*QEventLoop eventLoop; - m_waitingLoops.push_back(&eventLoop); - eventLoop.exec();*/ + /*QEventLoop eventLoop; +m_waitingLoops.push_back(&eventLoop); +eventLoop.exec();*/ - bool loopQuit = false; - m_waitingLoops.push_back(&loopQuit); + bool loopQuit = false; + m_waitingLoops.push_back(&loopQuit); - sl.unlock(); + sl.unlock(); - while (!loopQuit) - QCoreApplication::processEvents(QEventLoop::AllEvents | QEventLoop::WaitForMoreEvents); - } + while (!loopQuit) + QCoreApplication::processEvents(QEventLoop::AllEvents | + QEventLoop::WaitForMoreEvents); + } } //--------------------------------------------------------- -void TRendererImp::quitWaitingLoops() -{ - //Make the stopRendering waiting loops quit - while (!m_waitingLoops.empty()) { - //rendererImp->m_waitingLoops.back()->quit(); - *m_waitingLoops.back() = true; - m_waitingLoops.pop_back(); - } +void TRendererImp::quitWaitingLoops() { + // Make the stopRendering waiting loops quit + while (!m_waitingLoops.empty()) { + // rendererImp->m_waitingLoops.back()->quit(); + *m_waitingLoops.back() = true; + m_waitingLoops.pop_back(); + } } //--------------------------------------------------------- -void TRendererImp::notifyRasterStarted(const TRenderPort::RenderData &rd) -{ - //Since notifications may trigger port removals, we always work on a copy of the ports - //vector. - TRendererImp::PortContainer portsCopy; - { - QReadLocker sl(&m_portsLock); - portsCopy = m_ports; - } - - for (PortContainerIterator it = portsCopy.begin(); it != portsCopy.end(); ++it) - (*it)->onRenderRasterStarted(rd); +void TRendererImp::notifyRasterStarted(const TRenderPort::RenderData &rd) { + // Since notifications may trigger port removals, we always work on a copy of + // the ports + // vector. + TRendererImp::PortContainer portsCopy; + { + QReadLocker sl(&m_portsLock); + portsCopy = m_ports; + } + + for (PortContainerIterator it = portsCopy.begin(); it != portsCopy.end(); + ++it) + (*it)->onRenderRasterStarted(rd); } //--------------------------------------------------------- -void TRendererImp::notifyRasterCompleted(const TRenderPort::RenderData &rd) -{ - TRendererImp::PortContainer portsCopy; - { - QReadLocker sl(&m_portsLock); - portsCopy = m_ports; - } +void TRendererImp::notifyRasterCompleted(const TRenderPort::RenderData &rd) { + TRendererImp::PortContainer portsCopy; + { + QReadLocker sl(&m_portsLock); + portsCopy = m_ports; + } - assert(rd.m_rasA); + assert(rd.m_rasA); - for (PortContainerIterator it = portsCopy.begin(); it != portsCopy.end(); ++it) - (*it)->onRenderRasterCompleted(rd); + for (PortContainerIterator it = portsCopy.begin(); it != portsCopy.end(); + ++it) + (*it)->onRenderRasterCompleted(rd); } //--------------------------------------------------------- -void TRendererImp::notifyRasterFailure(const TRenderPort::RenderData &rd, TException &e) -{ - TRendererImp::PortContainer portsCopy; - { - QReadLocker sl(&m_portsLock); - portsCopy = m_ports; - } +void TRendererImp::notifyRasterFailure(const TRenderPort::RenderData &rd, + TException &e) { + TRendererImp::PortContainer portsCopy; + { + QReadLocker sl(&m_portsLock); + portsCopy = m_ports; + } - for (PortContainerIterator it = portsCopy.begin(); it != portsCopy.end(); ++it) - (*it)->onRenderFailure(rd, e); + for (PortContainerIterator it = portsCopy.begin(); it != portsCopy.end(); + ++it) + (*it)->onRenderFailure(rd, e); } //--------------------------------------------------------- -void TRendererImp::notifyRenderFinished(bool isCanceled) -{ - TRendererImp::PortContainer portsCopy; - { - QReadLocker sl(&m_portsLock); - portsCopy = m_ports; - } - - auto sortedFxs = calculateSortedFxs(rootFx); - for (auto fx : sortedFxs) { - if (fx) - const_cast(fx)->callEndRenderHandler(); - } - - for (PortContainerIterator it = portsCopy.begin(); it != portsCopy.end(); ++it) - (*it)->onRenderFinished(); +void TRendererImp::notifyRenderFinished(bool isCanceled) { + TRendererImp::PortContainer portsCopy; + { + QReadLocker sl(&m_portsLock); + portsCopy = m_ports; + } + + auto sortedFxs = calculateSortedFxs(rootFx); + for (auto fx : sortedFxs) { + if (fx) const_cast(fx)->callEndRenderHandler(); + } + + for (PortContainerIterator it = portsCopy.begin(); it != portsCopy.end(); + ++it) + (*it)->onRenderFinished(); } //================================================================================ @@ -948,31 +887,22 @@ void TRendererImp::notifyRenderFinished(bool isCanceled) // TRenderPort //-------------------- -TRenderPort::TRenderPort() -{ -} +TRenderPort::TRenderPort() {} //--------------------------------------------------------- -TRenderPort::~TRenderPort() -{ -} +TRenderPort::~TRenderPort() {} //--------------------------------------------------------- -//!Setta \b m_renderArea a \b area e pulisce l'istanza corrente di \b RasterPool. -void TRenderPort::setRenderArea(const TRectD &area) -{ - m_renderArea = area; -} +//! Setta \b m_renderArea a \b area e pulisce l'istanza corrente di \b +//! RasterPool. +void TRenderPort::setRenderArea(const TRectD &area) { m_renderArea = area; } //--------------------------------------------------------- -//!Ritorna \b m_renderArea. -TRectD &TRenderPort::getRenderArea() -{ - return m_renderArea; -} +//! Ritorna \b m_renderArea. +TRectD &TRenderPort::getRenderArea() { return m_renderArea; } //================================================================================ @@ -981,615 +911,603 @@ TRectD &TRenderPort::getRenderArea() //------------------- RenderTask::RenderTask(unsigned long renderId, unsigned long taskId, - double frame, const TRenderSettings &ri, const TFxPair &fx, - const TPointD &framePos, const TDimension &frameSize, - const TRendererImpP &rendererImp) - : m_renderId(renderId), m_taskId(taskId), m_info(ri), m_fx(fx), m_frameSize(frameSize), m_framePos(framePos), m_rendererImp(rendererImp), m_fieldRender(ri.m_fieldPrevalence != TRenderSettings::NoField), m_stereoscopic(ri.m_stereoscopic) -{ - m_frames.push_back(frame); - - //Connect the onFinished slot - connect(this, SIGNAL(finished(TThread::RunnableP)), this, SLOT(onFinished(TThread::RunnableP))); - connect(this, SIGNAL(exception(TThread::RunnableP)), this, SLOT(onFinished(TThread::RunnableP))); - - //The shrink info is currently reversed to the settings'affine. Shrink info in the TRenderSettings - //is no longer supported. - m_info.m_shrinkX = m_info.m_shrinkY = 1; + double frame, const TRenderSettings &ri, + const TFxPair &fx, const TPointD &framePos, + const TDimension &frameSize, + const TRendererImpP &rendererImp) + : m_renderId(renderId) + , m_taskId(taskId) + , m_info(ri) + , m_fx(fx) + , m_frameSize(frameSize) + , m_framePos(framePos) + , m_rendererImp(rendererImp) + , m_fieldRender(ri.m_fieldPrevalence != TRenderSettings::NoField) + , m_stereoscopic(ri.m_stereoscopic) { + m_frames.push_back(frame); + + // Connect the onFinished slot + connect(this, SIGNAL(finished(TThread::RunnableP)), this, + SLOT(onFinished(TThread::RunnableP))); + connect(this, SIGNAL(exception(TThread::RunnableP)), this, + SLOT(onFinished(TThread::RunnableP))); + + // The shrink info is currently reversed to the settings'affine. Shrink info + // in the TRenderSettings + // is no longer supported. + m_info.m_shrinkX = m_info.m_shrinkY = 1; } //--------------------------------------------------------- -void RenderTask::preRun() -{ - TRectD geom(m_framePos, TDimensionD(m_frameSize.lx, m_frameSize.ly)); +void RenderTask::preRun() { + TRectD geom(m_framePos, TDimensionD(m_frameSize.lx, m_frameSize.ly)); - if (m_fx.m_frameA) - m_fx.m_frameA->dryCompute(geom, m_frames[0], m_info); + if (m_fx.m_frameA) m_fx.m_frameA->dryCompute(geom, m_frames[0], m_info); - if (m_fx.m_frameB) - m_fx.m_frameB->dryCompute(geom, m_fieldRender ? m_frames[0] + 0.5 : m_frames[0], m_info); + if (m_fx.m_frameB) + m_fx.m_frameB->dryCompute( + geom, m_fieldRender ? m_frames[0] + 0.5 : m_frames[0], m_info); } //--------------------------------------------------------- -void RenderTask::run() -{ - //Retrieve the task's frame - assert(!m_frames.empty()); - double t = m_frames[0]; - - if (m_rendererImp->hasToDie(m_renderId)) { - TException e("Render task aborted"); - onFrameFailed(e); - return; - } - - //Install the renderer in current thread - rendererStorage.setLocalData(new (TRendererImp *)(m_rendererImp.getPointer())); - renderIdsStorage.setLocalData(new unsigned long(m_renderId)); - - //Inform the managers of frame start - m_rendererImp->declareFrameStart(t); - - auto sortedFxs = calculateSortedFxs(m_fx.m_frameA); - for (auto fx : sortedFxs) { - if (fx) - const_cast(fx)->callStartRenderFrameHandler(&m_info, t); - } - - try { - onFrameStarted(); - - TStopWatch::global(8).start(); - - if (!m_fieldRender && !m_stereoscopic) { - //Common case - just build the first tile - buildTile(m_tileA); - /*-- 通常はここがFxのレンダリング処理 --*/ - m_fx.m_frameA->compute(m_tileA, t, m_info); - } else { - assert(!(m_stereoscopic && m_fieldRender)); - //Field rendering or stereoscopic case - if (m_stereoscopic) { - buildTile(m_tileA); - m_fx.m_frameA->compute(m_tileA, t, m_info); - - buildTile(m_tileB); - m_fx.m_frameB->compute(m_tileB, t, m_info); - } - //if fieldPrevalence, Decide the rendering frames depending on field prevalence - else if (m_info.m_fieldPrevalence == TRenderSettings::EvenField) { - buildTile(m_tileA); - m_fx.m_frameA->compute(m_tileA, t, m_info); - - buildTile(m_tileB); - m_fx.m_frameB->compute(m_tileB, t + 0.5, m_info); - } else { - buildTile(m_tileB); - m_fx.m_frameA->compute(m_tileB, t, m_info); - - buildTile(m_tileA); - m_fx.m_frameB->compute(m_tileA, t + 0.5, m_info); - } - } - - TStopWatch::global(8).stop(); - - onFrameCompleted(); - } catch (TException &e) { - onFrameFailed(e); - } catch (...) { - TException ex("Unknown render exception"); - onFrameFailed(ex); - } - - //Inform the managers of frame end - m_rendererImp->declareFrameEnd(t); - - //Uninstall the renderer from current thread - rendererStorage.setLocalData(0); - renderIdsStorage.setLocalData(0); - - for (auto fx : sortedFxs) { - if (fx) - const_cast(fx)->callEndRenderFrameHandler(&m_info, t); - } +void RenderTask::run() { + // Retrieve the task's frame + assert(!m_frames.empty()); + double t = m_frames[0]; + + if (m_rendererImp->hasToDie(m_renderId)) { + TException e("Render task aborted"); + onFrameFailed(e); + return; + } + + // Install the renderer in current thread + rendererStorage.setLocalData( + new (TRendererImp *)(m_rendererImp.getPointer())); + renderIdsStorage.setLocalData(new unsigned long(m_renderId)); + + // Inform the managers of frame start + m_rendererImp->declareFrameStart(t); + + auto sortedFxs = calculateSortedFxs(m_fx.m_frameA); + for (auto fx : sortedFxs) { + if (fx) const_cast(fx)->callStartRenderFrameHandler(&m_info, t); + } + + try { + onFrameStarted(); + + TStopWatch::global(8).start(); + + if (!m_fieldRender && !m_stereoscopic) { + // Common case - just build the first tile + buildTile(m_tileA); + /*-- 通常はここがFxのレンダリング処理 --*/ + m_fx.m_frameA->compute(m_tileA, t, m_info); + } else { + assert(!(m_stereoscopic && m_fieldRender)); + // Field rendering or stereoscopic case + if (m_stereoscopic) { + buildTile(m_tileA); + m_fx.m_frameA->compute(m_tileA, t, m_info); + + buildTile(m_tileB); + m_fx.m_frameB->compute(m_tileB, t, m_info); + } + // if fieldPrevalence, Decide the rendering frames depending on field + // prevalence + else if (m_info.m_fieldPrevalence == TRenderSettings::EvenField) { + buildTile(m_tileA); + m_fx.m_frameA->compute(m_tileA, t, m_info); + + buildTile(m_tileB); + m_fx.m_frameB->compute(m_tileB, t + 0.5, m_info); + } else { + buildTile(m_tileB); + m_fx.m_frameA->compute(m_tileB, t, m_info); + + buildTile(m_tileA); + m_fx.m_frameB->compute(m_tileA, t + 0.5, m_info); + } + } + + TStopWatch::global(8).stop(); + + onFrameCompleted(); + } catch (TException &e) { + onFrameFailed(e); + } catch (...) { + TException ex("Unknown render exception"); + onFrameFailed(ex); + } + + // Inform the managers of frame end + m_rendererImp->declareFrameEnd(t); + + // Uninstall the renderer from current thread + rendererStorage.setLocalData(0); + renderIdsStorage.setLocalData(0); + + for (auto fx : sortedFxs) { + if (fx) const_cast(fx)->callEndRenderFrameHandler(&m_info, t); + } } //--------------------------------------------------------- -void RenderTask::buildTile(TTile &tile) -{ - tile.m_pos = m_framePos; - tile.setRaster(m_rendererImp->m_rasterPool.getRaster(m_frameSize, m_info.m_bpp)); +void RenderTask::buildTile(TTile &tile) { + tile.m_pos = m_framePos; + tile.setRaster( + m_rendererImp->m_rasterPool.getRaster(m_frameSize, m_info.m_bpp)); } //--------------------------------------------------------- -void RenderTask::releaseTiles() -{ - m_rendererImp->m_rasterPool.releaseRaster(m_tileA.getRaster()); - m_tileA.setRaster(TRasterP()); - if (m_fieldRender || m_stereoscopic) { - m_rendererImp->m_rasterPool.releaseRaster(m_tileB.getRaster()); - m_tileB.setRaster(TRasterP()); - } +void RenderTask::releaseTiles() { + m_rendererImp->m_rasterPool.releaseRaster(m_tileA.getRaster()); + m_tileA.setRaster(TRasterP()); + if (m_fieldRender || m_stereoscopic) { + m_rendererImp->m_rasterPool.releaseRaster(m_tileB.getRaster()); + m_tileB.setRaster(TRasterP()); + } } //--------------------------------------------------------- -void RenderTask::onFrameStarted() -{ - TRenderPort::RenderData rd(m_frames, m_info, 0, 0, m_renderId, m_taskId); - m_rendererImp->notifyRasterStarted(rd); +void RenderTask::onFrameStarted() { + TRenderPort::RenderData rd(m_frames, m_info, 0, 0, m_renderId, m_taskId); + m_rendererImp->notifyRasterStarted(rd); } //--------------------------------------------------------- -void RenderTask::onFrameCompleted() -{ - TRasterP rasA(m_tileA.getRaster()); - TRasterP rasB(m_tileB.getRaster()); +void RenderTask::onFrameCompleted() { + TRasterP rasA(m_tileA.getRaster()); + TRasterP rasB(m_tileB.getRaster()); - if (m_fieldRender) { - assert(rasB); + if (m_fieldRender) { + assert(rasB); - double t = m_frames[0]; + double t = m_frames[0]; - int f = (m_info.m_fieldPrevalence == TRenderSettings::EvenField) ? 0 : 1; - interlace(rasA, rasB, f); - rasB = TRasterP(); - } + int f = (m_info.m_fieldPrevalence == TRenderSettings::EvenField) ? 0 : 1; + interlace(rasA, rasB, f); + rasB = TRasterP(); + } - TRenderPort::RenderData rd(m_frames, m_info, rasA, rasB, m_renderId, m_taskId); - m_rendererImp->notifyRasterCompleted(rd); + TRenderPort::RenderData rd(m_frames, m_info, rasA, rasB, m_renderId, + m_taskId); + m_rendererImp->notifyRasterCompleted(rd); } //--------------------------------------------------------- -void RenderTask::onFrameFailed(TException &e) -{ - //TRasterP evenRas(m_evenTile.getRaster()); +void RenderTask::onFrameFailed(TException &e) { + // TRasterP evenRas(m_evenTile.getRaster()); - TRenderPort::RenderData rd(m_frames, m_info, m_tileA.getRaster(), m_tileB.getRaster(), m_renderId, m_taskId); - m_rendererImp->notifyRasterFailure(rd, e); + TRenderPort::RenderData rd(m_frames, m_info, m_tileA.getRaster(), + m_tileB.getRaster(), m_renderId, m_taskId); + m_rendererImp->notifyRasterFailure(rd, e); } //--------------------------------------------------------- -void RenderTask::onFinished(TThread::RunnableP) -{ - TRendererImp *rendererImp = m_rendererImp.getPointer(); - --rendererImp->m_undoneTasks; - - //Tiles release back to the Raster Pool happens in the main thread, after all possible - //signals emitted in the onFrameCompleted/Failed notifications have been resolved, thus - //ensuring that no other rendering thread owns the rasters before them. - releaseTiles(); - - //Update the render instance status - bool instanceExpires = false; - { - QMutexLocker sl(&rendererImp->m_renderInstancesMutex); - std::map::iterator it = - rendererImp->m_activeInstances.find(m_renderId); - - if (it != rendererImp->m_activeInstances.end() && (--it->second.m_activeTasks) <= 0) { - instanceExpires = true; - rendererImp->m_activeInstances.erase(m_renderId); - } - } - - //If the render instance has just expired - if (instanceExpires) { - /*-- キャンセルされた場合はm_overallRenderedRegionの更新をしない --*/ - bool isCanceled = (m_info.m_isCanceled && *m_info.m_isCanceled); - - //Inform the render ports - rendererImp->notifyRenderFinished(isCanceled); - - //NOTE: This slot is currently invoked on the main thread. It could eventually be - //invoked directly on rendering threads, specifying the Qt::DirectConnection option - - //but probably there would be no real advantage in doing so... - - //Temporarily install the renderer in current thread - rendererStorage.setLocalData(new (TRendererImp *)(rendererImp)); - renderIdsStorage.setLocalData(new unsigned long(m_renderId)); - - //Inform the resource managers - rendererImp->declareRenderEnd(m_renderId); - - //Uninstall the temporary - rendererStorage.setLocalData(0); - renderIdsStorage.setLocalData(0); - - rendererImp->m_rasterPool.clear(); // Isn't this misplaced? Should be in the block - } // below... - - //If no rendering task (of this or other render instances) is found... - if (rendererImp->m_undoneTasks == 0) { - QMutexLocker sl(&rendererImp->m_renderInstancesMutex); - rendererImp->quitWaitingLoops(); - } +void RenderTask::onFinished(TThread::RunnableP) { + TRendererImp *rendererImp = m_rendererImp.getPointer(); + --rendererImp->m_undoneTasks; + + // Tiles release back to the Raster Pool happens in the main thread, after all + // possible + // signals emitted in the onFrameCompleted/Failed notifications have been + // resolved, thus + // ensuring that no other rendering thread owns the rasters before them. + releaseTiles(); + + // Update the render instance status + bool instanceExpires = false; + { + QMutexLocker sl(&rendererImp->m_renderInstancesMutex); + std::map::iterator it = + rendererImp->m_activeInstances.find(m_renderId); + + if (it != rendererImp->m_activeInstances.end() && + (--it->second.m_activeTasks) <= 0) { + instanceExpires = true; + rendererImp->m_activeInstances.erase(m_renderId); + } + } + + // If the render instance has just expired + if (instanceExpires) { + /*-- キャンセルされた場合はm_overallRenderedRegionの更新をしない --*/ + bool isCanceled = (m_info.m_isCanceled && *m_info.m_isCanceled); + + // Inform the render ports + rendererImp->notifyRenderFinished(isCanceled); + + // NOTE: This slot is currently invoked on the main thread. It could + // eventually be + // invoked directly on rendering threads, specifying the + // Qt::DirectConnection option - + // but probably there would be no real advantage in doing so... + + // Temporarily install the renderer in current thread + rendererStorage.setLocalData(new (TRendererImp *)(rendererImp)); + renderIdsStorage.setLocalData(new unsigned long(m_renderId)); + + // Inform the resource managers + rendererImp->declareRenderEnd(m_renderId); + + // Uninstall the temporary + rendererStorage.setLocalData(0); + renderIdsStorage.setLocalData(0); + + rendererImp->m_rasterPool + .clear(); // Isn't this misplaced? Should be in the block + } // below... + + // If no rendering task (of this or other render instances) is found... + if (rendererImp->m_undoneTasks == 0) { + QMutexLocker sl(&rendererImp->m_renderInstancesMutex); + rendererImp->quitWaitingLoops(); + } } //================================================================================ // Tough Stuff //================================================================================ -void TRendererStartInvoker::emitStartRender( - TRendererImp *renderer, StartInvokerRenderData rd) -{ - renderer->addRef(); - Q_EMIT startRender(renderer, rd); +void TRendererStartInvoker::emitStartRender(TRendererImp *renderer, + StartInvokerRenderData rd) { + renderer->addRef(); + Q_EMIT startRender(renderer, rd); } //--------------------------------------------------------- -void TRendererStartInvoker::doStartRender( - TRendererImp *renderer, StartInvokerRenderData rd) -{ - renderer->startRendering(rd.m_renderId, *rd.m_renderDataVector); - renderer->release(); - delete rd.m_renderDataVector; -} - -std::vector calculateSortedFxs(TRasterFxP rootFx) -{ - std::map> E; /* 辺の情報 */ - std::set Sources; /* 入次数0のノード群 */ - - std::queue Q; - Q.push(rootFx.getPointer()); - - E[rootFx.getPointer()] = std::set(); - - while (!Q.empty()) { - const TFx *vptr = Q.front(); - Q.pop(); - if (!vptr) { - continue; - } - - /* 繋がっている入力ポートの先の Fx を訪問する - 入力ポートが無ければ終了 */ - int portCount = vptr->getInputPortCount(); - if (portCount < 1) { - Sources.insert(vptr); - continue; - } - for (int i = 0; i < portCount; i++) { - TFxPort *port = vptr->getInputPort(i); - if (!port) { - continue; - } - TFxP u = port->getFx(); - const TFx *uptr = u.getPointer(); - if (E.count(uptr) == 0) { - E[uptr] = std::set(); - } - if (E[uptr].count(vptr) == 0) { - E[uptr].insert(vptr); - } - Q.push(uptr); - } - } - - /* トポロジカルソート */ - std::set visited; - std::vector L; - std::function visit = [&visit, &visited, &E, &L](const TFx *fx) { - if (visited.count(fx)) - return; - visited.insert(fx); - auto edge = E[fx]; - for (auto i = edge.cbegin(); i != edge.cend(); i++) { - visit(*i); - } - L.insert(L.begin(), fx); - }; - for (auto i = E.cbegin(); i != E.cend(); i++) { - visit(i->first); - } - return L; +void TRendererStartInvoker::doStartRender(TRendererImp *renderer, + StartInvokerRenderData rd) { + renderer->startRendering(rd.m_renderId, *rd.m_renderDataVector); + renderer->release(); + delete rd.m_renderDataVector; +} + +std::vector calculateSortedFxs(TRasterFxP rootFx) { + std::map> E; /* 辺の情報 */ + std::set Sources; /* 入次数0のノード群 */ + + std::queue Q; + Q.push(rootFx.getPointer()); + + E[rootFx.getPointer()] = std::set(); + + while (!Q.empty()) { + const TFx *vptr = Q.front(); + Q.pop(); + if (!vptr) { + continue; + } + + /* 繋がっている入力ポートの先の Fx を訪問する +入力ポートが無ければ終了 */ + int portCount = vptr->getInputPortCount(); + if (portCount < 1) { + Sources.insert(vptr); + continue; + } + for (int i = 0; i < portCount; i++) { + TFxPort *port = vptr->getInputPort(i); + if (!port) { + continue; + } + TFxP u = port->getFx(); + const TFx *uptr = u.getPointer(); + if (E.count(uptr) == 0) { + E[uptr] = std::set(); + } + if (E[uptr].count(vptr) == 0) { + E[uptr].insert(vptr); + } + Q.push(uptr); + } + } + + /* トポロジカルソート */ + std::set visited; + std::vector L; + std::function visit = [&visit, &visited, &E, + &L](const TFx *fx) { + if (visited.count(fx)) return; + visited.insert(fx); + auto edge = E[fx]; + for (auto i = edge.cbegin(); i != edge.cend(); i++) { + visit(*i); + } + L.insert(L.begin(), fx); + }; + for (auto i = E.cbegin(); i != E.cend(); i++) { + visit(i->first); + } + return L; } //--------------------------------------------------------- -void TRendererImp::startRendering(unsigned long renderId, const std::vector &renderDatas) -{ - rootFx = renderDatas.front().m_fxRoot.m_frameA; - int T = renderDatas.size(); - for (int z = 0; z < T; z++) { - auto sortedFxs = calculateSortedFxs(renderDatas[z].m_fxRoot.m_frameA); - if (z == 0) { - for (auto fx : sortedFxs) { - if (fx) - const_cast(fx)->callStartRenderHandler(); - } - } - } - - struct locals { - - static inline void setStorage(TRendererImp *imp, unsigned long renderId) - { - rendererStorage.setLocalData(new (TRendererImp *)(imp)); - renderIdsStorage.setLocalData(new unsigned long(renderId)); - } - - static inline void clearStorage() - { - rendererStorage.setLocalData(0); - renderIdsStorage.setLocalData(0); - } - - static inline void declareStatusStart( - TRendererImp *imp, TRenderer::RenderStatus status, - RenderInstanceInfos *renderInfos) - { - renderInfos->m_status = status; - imp->declareStatusStart(status); - } - - //----------------------------------------------------------------------- - - struct InstanceDeclaration { - TRendererImp *m_imp; - unsigned long m_renderId; - bool m_rollback; - - InstanceDeclaration(TRendererImp *imp, unsigned long renderId) - : m_imp(imp), m_renderId(renderId), m_rollback(true) {} - - ~InstanceDeclaration() - { - if (m_rollback) { - QMutexLocker locker(&m_imp->m_renderInstancesMutex); - - m_imp->m_activeInstances.erase(m_renderId); - if (m_imp->m_undoneTasks == 0) - m_imp->quitWaitingLoops(); - } - } - - void commit() { m_rollback = false; } - }; - - struct StorageDeclaration { - StorageDeclaration(TRendererImp *imp, unsigned long renderId) - { - setStorage(imp, renderId); - } - - ~StorageDeclaration() - { - clearStorage(); - } - }; - - struct RenderDeclaration { - TRendererImp *m_imp; - unsigned long m_renderId; - bool m_rollback; - - RenderDeclaration(TRendererImp *imp, unsigned long renderId) - : m_imp(imp), m_renderId(renderId), m_rollback(true) - { - imp->declareRenderStart(renderId); - } - - ~RenderDeclaration() - { - if (m_rollback) - m_imp->declareRenderEnd(m_renderId); - } - - void commit() { m_rollback = false; } - }; - - struct StatusDeclaration { - TRendererImp *m_imp; - TRenderer::RenderStatus m_status; - - StatusDeclaration(TRendererImp *imp, TRenderer::RenderStatus status, - RenderInstanceInfos *renderInfos) - : m_imp(imp), m_status(status) - { - declareStatusStart(imp, status, renderInfos); - } - - ~StatusDeclaration() - { - m_imp->declareStatusEnd(m_status); - } - }; - }; // locals - - //DIAGNOSTICS_CLEAR; - - //---------------------------------------------------------------------- - // Preliminary initializations - //---------------------------------------------------------------------- - - // Calculate the overall render area - sum of all render ports' areas - TRectD renderArea; - { - QReadLocker sl(&m_portsLock); - - for (PortContainerIterator it = m_ports.begin(); it != m_ports.end(); ++it) - renderArea += (*it)->getRenderArea(); - } - - const TRenderSettings &info(renderDatas[0].m_info); - - //Extract the render geometry - TPointD pos(renderArea.getP00()); - TDimension frameSize(tceil(renderArea.getLx()), tceil(renderArea.getLy())); - - TRectD camBox(TPointD(pos.x / info.m_shrinkX, pos.y / info.m_shrinkY), - TDimensionD(frameSize.lx, frameSize.ly)); - - //Refresh the raster pool specs - m_rasterPool.setRasterSpecs(frameSize, info.m_bpp); - - //Set a temporary active instance count - so that hasToDie(renderId) returns false - RenderInstanceInfos *renderInfos; - { - QMutexLocker locker(&m_renderInstancesMutex); - renderInfos = &m_activeInstances[renderId]; - renderInfos->m_activeTasks = 1; - } - - locals::InstanceDeclaration instanceDecl(this, renderId); - - //---------------------------------------------------------------------- - // Clustering - Render Tasks creation - //---------------------------------------------------------------------- - - std::vector tasksVector; - - struct TasksCleaner { - std::vector &m_tasksVector; - ~TasksCleaner() - { - std::for_each(m_tasksVector.begin(), m_tasksVector.end(), - tcg::deleter()); - } - } tasksCleaner = {tasksVector}; - - unsigned long tasksIdCounter = 0; - - std::map clusters; - std::vector::const_iterator it; - std::map::iterator jt; - - for (it = renderDatas.begin(); it != renderDatas.end(); ++it) { - // Check for user cancels - if (hasToDie(renderId)) - return; - - // Build the frame's description alias - const TRenderer::RenderData &renderData = *it; - - /*--- カメラサイズ (LevelAutoやノイズで使用する) ---*/ - TRenderSettings rs = renderData.m_info; - rs.m_cameraBox = camBox; - /*--- 途中でPreview計算がキャンセルされたときのフラグ ---*/ - rs.m_isCanceled = &renderInfos->m_canceled; - - TRasterFxP fx = renderData.m_fxRoot.m_frameA; - assert(fx); - - double frame = renderData.m_frame; - - std::string alias = fx->getAlias(frame, renderData.m_info); - if (renderData.m_fxRoot.m_frameB) - alias = alias + renderData.m_fxRoot.m_frameB->getAlias(frame, renderData.m_info); - - // Search the alias among stored clusters - and store the frame - jt = clusters.find(alias); - - if (jt == clusters.end()) { - RenderTask *newTask = new RenderTask( - renderId, tasksIdCounter++, - renderData.m_frame, rs, renderData.m_fxRoot, - pos, frameSize, this); - - tasksVector.push_back(newTask); - clusters.insert(std::make_pair(alias, newTask)); - } else - jt->second->addFrame(renderData.m_frame); - - // Call processEvents to make the GUI reactive. - QCoreApplication::instance()->processEvents(); - } +void TRendererImp::startRendering( + unsigned long renderId, + const std::vector &renderDatas) { + rootFx = renderDatas.front().m_fxRoot.m_frameA; + int T = renderDatas.size(); + for (int z = 0; z < T; z++) { + auto sortedFxs = calculateSortedFxs(renderDatas[z].m_fxRoot.m_frameA); + if (z == 0) { + for (auto fx : sortedFxs) { + if (fx) const_cast(fx)->callStartRenderHandler(); + } + } + } + + struct locals { + static inline void setStorage(TRendererImp *imp, unsigned long renderId) { + rendererStorage.setLocalData(new (TRendererImp *)(imp)); + renderIdsStorage.setLocalData(new unsigned long(renderId)); + } + + static inline void clearStorage() { + rendererStorage.setLocalData(0); + renderIdsStorage.setLocalData(0); + } + + static inline void declareStatusStart(TRendererImp *imp, + TRenderer::RenderStatus status, + RenderInstanceInfos *renderInfos) { + renderInfos->m_status = status; + imp->declareStatusStart(status); + } + + //----------------------------------------------------------------------- + + struct InstanceDeclaration { + TRendererImp *m_imp; + unsigned long m_renderId; + bool m_rollback; + + InstanceDeclaration(TRendererImp *imp, unsigned long renderId) + : m_imp(imp), m_renderId(renderId), m_rollback(true) {} + + ~InstanceDeclaration() { + if (m_rollback) { + QMutexLocker locker(&m_imp->m_renderInstancesMutex); + + m_imp->m_activeInstances.erase(m_renderId); + if (m_imp->m_undoneTasks == 0) m_imp->quitWaitingLoops(); + } + } + + void commit() { m_rollback = false; } + }; + + struct StorageDeclaration { + StorageDeclaration(TRendererImp *imp, unsigned long renderId) { + setStorage(imp, renderId); + } + + ~StorageDeclaration() { clearStorage(); } + }; + + struct RenderDeclaration { + TRendererImp *m_imp; + unsigned long m_renderId; + bool m_rollback; + + RenderDeclaration(TRendererImp *imp, unsigned long renderId) + : m_imp(imp), m_renderId(renderId), m_rollback(true) { + imp->declareRenderStart(renderId); + } + + ~RenderDeclaration() { + if (m_rollback) m_imp->declareRenderEnd(m_renderId); + } + + void commit() { m_rollback = false; } + }; + + struct StatusDeclaration { + TRendererImp *m_imp; + TRenderer::RenderStatus m_status; + + StatusDeclaration(TRendererImp *imp, TRenderer::RenderStatus status, + RenderInstanceInfos *renderInfos) + : m_imp(imp), m_status(status) { + declareStatusStart(imp, status, renderInfos); + } + + ~StatusDeclaration() { m_imp->declareStatusEnd(m_status); } + }; + }; // locals + + // DIAGNOSTICS_CLEAR; + + //---------------------------------------------------------------------- + // Preliminary initializations + //---------------------------------------------------------------------- + + // Calculate the overall render area - sum of all render ports' areas + TRectD renderArea; + { + QReadLocker sl(&m_portsLock); + + for (PortContainerIterator it = m_ports.begin(); it != m_ports.end(); ++it) + renderArea += (*it)->getRenderArea(); + } + + const TRenderSettings &info(renderDatas[0].m_info); + + // Extract the render geometry + TPointD pos(renderArea.getP00()); + TDimension frameSize(tceil(renderArea.getLx()), tceil(renderArea.getLy())); + + TRectD camBox(TPointD(pos.x / info.m_shrinkX, pos.y / info.m_shrinkY), + TDimensionD(frameSize.lx, frameSize.ly)); + + // Refresh the raster pool specs + m_rasterPool.setRasterSpecs(frameSize, info.m_bpp); - // Release the clusters - we'll just need the tasks vector from now on - clusters.clear(); - - std::vector::iterator kt, kEnd = tasksVector.end(); - { - // Install TRenderer on current thread before proceeding - locals::StorageDeclaration storageDecl(this, renderId); - - // Inform the resource managers - locals::RenderDeclaration renderDecl(this, renderId); - - //---------------------------------------------------------------------- - // Precomputing - //---------------------------------------------------------------------- - - if (m_precomputingEnabled) { - //Set current maxTileSize for cache manager precomputation - const TRenderSettings &rs = renderDatas[0].m_info; - TPredictiveCacheManager::instance()->setMaxTileSize(rs.m_maxTileSize); - TPredictiveCacheManager::instance()->setBPP(rs.m_bpp); - - //Perform the first precomputing run - fx usages declaration - { - locals::StatusDeclaration firstrunDecl(this, TRenderer::FIRSTRUN, renderInfos); - - for (kt = tasksVector.begin(); kt != kEnd; ++kt) { - if (hasToDie(renderId)) - return; - - (*kt)->preRun(); - - //NOTE: Thread-specific data must be temporarily uninstalled before - //processing events (which may redefine the thread data). - locals::clearStorage(); - QCoreApplication::instance()->processEvents(); - locals::setStorage(this, renderId); - } - } - - //Pass to the TESTRUN status - this one should faithfully reproduce - //the actual COMPUTING status - { - locals::StatusDeclaration testrunDecl(this, TRenderer::TESTRUN, renderInfos); - - for (kt = tasksVector.begin(); kt != kEnd; ++kt) { - if (hasToDie(renderId)) - return; - - (*kt)->preRun(); - - //NOTE: Thread-specific data must be temporarily uninstalled before - //processing events (which may redefine the thread data). - locals::clearStorage(); - QCoreApplication::instance()->processEvents(); - locals::setStorage(this, renderId); - } - } - } - - //---------------------------------------------------------------------- - // Render - //---------------------------------------------------------------------- - - locals::declareStatusStart(this, TRenderer::COMPUTING, renderInfos); - - // Update the tasks counts - m_undoneTasks += tasksVector.size(); - { - QMutexLocker locker(&m_renderInstancesMutex); - renderInfos->m_activeTasks = tasksVector.size(); - } + // Set a temporary active instance count - so that hasToDie(renderId) returns + // false + RenderInstanceInfos *renderInfos; + { + QMutexLocker locker(&m_renderInstancesMutex); + renderInfos = &m_activeInstances[renderId]; + renderInfos->m_activeTasks = 1; + } + + locals::InstanceDeclaration instanceDecl(this, renderId); - renderDecl.commit(); // Declarations are taken over by render tasks - } - - instanceDecl.commit(); // Same here - - // Launch the render - for (kt = tasksVector.begin(); kt != tasksVector.end(); ++kt) - m_executor.addTask(*kt); - - tasksVector.clear(); // Prevent tasks destruction by TasksCleaner -} + //---------------------------------------------------------------------- + // Clustering - Render Tasks creation + //---------------------------------------------------------------------- + + std::vector tasksVector; + + struct TasksCleaner { + std::vector &m_tasksVector; + ~TasksCleaner() { + std::for_each(m_tasksVector.begin(), m_tasksVector.end(), + tcg::deleter()); + } + } tasksCleaner = {tasksVector}; + + unsigned long tasksIdCounter = 0; + + std::map clusters; + std::vector::const_iterator it; + std::map::iterator jt; + + for (it = renderDatas.begin(); it != renderDatas.end(); ++it) { + // Check for user cancels + if (hasToDie(renderId)) return; + + // Build the frame's description alias + const TRenderer::RenderData &renderData = *it; + + /*--- カメラサイズ (LevelAutoやノイズで使用する) ---*/ + TRenderSettings rs = renderData.m_info; + rs.m_cameraBox = camBox; + /*--- 途中でPreview計算がキャンセルされたときのフラグ ---*/ + rs.m_isCanceled = &renderInfos->m_canceled; + + TRasterFxP fx = renderData.m_fxRoot.m_frameA; + assert(fx); + + double frame = renderData.m_frame; + + std::string alias = fx->getAlias(frame, renderData.m_info); + if (renderData.m_fxRoot.m_frameB) + alias = alias + + renderData.m_fxRoot.m_frameB->getAlias(frame, renderData.m_info); + + // Search the alias among stored clusters - and store the frame + jt = clusters.find(alias); + + if (jt == clusters.end()) { + RenderTask *newTask = + new RenderTask(renderId, tasksIdCounter++, renderData.m_frame, rs, + renderData.m_fxRoot, pos, frameSize, this); + + tasksVector.push_back(newTask); + clusters.insert(std::make_pair(alias, newTask)); + } else + jt->second->addFrame(renderData.m_frame); + + // Call processEvents to make the GUI reactive. + QCoreApplication::instance()->processEvents(); + } + + // Release the clusters - we'll just need the tasks vector from now on + clusters.clear(); + + std::vector::iterator kt, kEnd = tasksVector.end(); + { + // Install TRenderer on current thread before proceeding + locals::StorageDeclaration storageDecl(this, renderId); + + // Inform the resource managers + locals::RenderDeclaration renderDecl(this, renderId); + + //---------------------------------------------------------------------- + // Precomputing + //---------------------------------------------------------------------- + + if (m_precomputingEnabled) { + // Set current maxTileSize for cache manager precomputation + const TRenderSettings &rs = renderDatas[0].m_info; + TPredictiveCacheManager::instance()->setMaxTileSize(rs.m_maxTileSize); + TPredictiveCacheManager::instance()->setBPP(rs.m_bpp); + + // Perform the first precomputing run - fx usages declaration + { + locals::StatusDeclaration firstrunDecl(this, TRenderer::FIRSTRUN, + renderInfos); + + for (kt = tasksVector.begin(); kt != kEnd; ++kt) { + if (hasToDie(renderId)) return; -void TRenderer::initialize() -{ - TRendererStartInvoker::instance(); + (*kt)->preRun(); + + // NOTE: Thread-specific data must be temporarily uninstalled before + // processing events (which may redefine the thread data). + locals::clearStorage(); + QCoreApplication::instance()->processEvents(); + locals::setStorage(this, renderId); + } + } + + // Pass to the TESTRUN status - this one should faithfully reproduce + // the actual COMPUTING status + { + locals::StatusDeclaration testrunDecl(this, TRenderer::TESTRUN, + renderInfos); + + for (kt = tasksVector.begin(); kt != kEnd; ++kt) { + if (hasToDie(renderId)) return; + + (*kt)->preRun(); + + // NOTE: Thread-specific data must be temporarily uninstalled before + // processing events (which may redefine the thread data). + locals::clearStorage(); + QCoreApplication::instance()->processEvents(); + locals::setStorage(this, renderId); + } + } + } + + //---------------------------------------------------------------------- + // Render + //---------------------------------------------------------------------- + + locals::declareStatusStart(this, TRenderer::COMPUTING, renderInfos); + + // Update the tasks counts + m_undoneTasks += tasksVector.size(); + { + QMutexLocker locker(&m_renderInstancesMutex); + renderInfos->m_activeTasks = tasksVector.size(); + } + + renderDecl.commit(); // Declarations are taken over by render tasks + } + + instanceDecl.commit(); // Same here + + // Launch the render + for (kt = tasksVector.begin(); kt != tasksVector.end(); ++kt) + m_executor.addTask(*kt); + + tasksVector.clear(); // Prevent tasks destruction by TasksCleaner } + +void TRenderer::initialize() { TRendererStartInvoker::instance(); } diff --git a/toonz/sources/common/tfx/trendererP.h b/toonz/sources/common/tfx/trendererP.h index dd7a95a..a8491d2 100644 --- a/toonz/sources/common/tfx/trendererP.h +++ b/toonz/sources/common/tfx/trendererP.h @@ -11,52 +11,53 @@ //============================================================================================= //! This is a private class used to convey the TRenderer::startRendering -//! methods into Qt queued slots. This is necessary since these methods implicitly -//! perform event processing, which could cause trouble in case they are invoked from +//! methods into Qt queued slots. This is necessary since these methods +//! implicitly +//! perform event processing, which could cause trouble in case they are invoked +//! from //! events which must respect a strict ordering. //! \n \n //! For example, suppose that a render must be invoked upon a mousePressEvent, -//! and that such event must have been completely processed before the corrispondant -//! mouseReleaseEvent is invoked - calling the startRendering method *directly* by -//! the mousePressEvent may cause the mouseReleaseEvent to be processed before the +//! and that such event must have been completely processed before the +//! corrispondant +//! mouseReleaseEvent is invoked - calling the startRendering method *directly* +//! by +//! the mousePressEvent may cause the mouseReleaseEvent to be processed before +//! the //! former's end. -class TRendererStartInvoker : public QObject -{ - Q_OBJECT +class TRendererStartInvoker : public QObject { + Q_OBJECT public: - struct StartInvokerRenderData { - unsigned long m_renderId; - const RenderDataVector *m_renderDataVector; - }; + struct StartInvokerRenderData { + unsigned long m_renderId; + const RenderDataVector *m_renderDataVector; + }; public: - TRendererStartInvoker() - { - qRegisterMetaType("StartInvokerRenderData"); + TRendererStartInvoker() { + qRegisterMetaType("StartInvokerRenderData"); - connect(this, SIGNAL(startRender(TRendererImp *, StartInvokerRenderData)), - this, SLOT(doStartRender(TRendererImp *, StartInvokerRenderData)), - Qt::QueuedConnection); - } - ~TRendererStartInvoker() {} + connect(this, SIGNAL(startRender(TRendererImp *, StartInvokerRenderData)), + this, SLOT(doStartRender(TRendererImp *, StartInvokerRenderData)), + Qt::QueuedConnection); + } + ~TRendererStartInvoker() {} - static TRendererStartInvoker *instance() - { - static TRendererStartInvoker theInstance; - return &theInstance; - } + static TRendererStartInvoker *instance() { + static TRendererStartInvoker theInstance; + return &theInstance; + } - void emitStartRender(TRendererImp *renderer, StartInvokerRenderData rd); + void emitStartRender(TRendererImp *renderer, StartInvokerRenderData rd); - Q_SIGNALS : +Q_SIGNALS: - void - startRender(TRendererImp *, StartInvokerRenderData); + void startRender(TRendererImp *, StartInvokerRenderData); public Q_SLOTS: - void doStartRender(TRendererImp *, StartInvokerRenderData rd); + void doStartRender(TRendererImp *, StartInvokerRenderData rd); }; -#endif //TRENDERERP_INCLUDE +#endif // TRENDERERP_INCLUDE diff --git a/toonz/sources/common/tfx/trenderresourcemanager.cpp b/toonz/sources/common/tfx/trenderresourcemanager.cpp index 0f341ad..5678627 100644 --- a/toonz/sources/common/tfx/trenderresourcemanager.cpp +++ b/toonz/sources/common/tfx/trenderresourcemanager.cpp @@ -8,256 +8,241 @@ //*********************************************************************************************** /* -This manager class is used to create and destroy instance-scope managers through the -renderStart/renderEnd notifications. Observe that this involves maintenance of a container +This manager class is used to create and destroy instance-scope managers through +the +renderStart/renderEnd notifications. Observe that this involves maintenance of a +container structure of the active renderIds against resource managers. */ -class RenderInstanceManagersBuilder : public TRenderResourceManager -{ - T_RENDER_RESOURCE_MANAGER +class RenderInstanceManagersBuilder : public TRenderResourceManager { + T_RENDER_RESOURCE_MANAGER - typedef std::vector ManagersVector; - std::map m_managersMap; + typedef std::vector ManagersVector; + std::map m_managersMap; public: - RenderInstanceManagersBuilder() {} - ~RenderInstanceManagersBuilder() {} + RenderInstanceManagersBuilder() {} + ~RenderInstanceManagersBuilder() {} - static RenderInstanceManagersBuilder *instance(); + static RenderInstanceManagersBuilder *instance(); - TRenderResourceManager *getManager(unsigned long renderId, unsigned int idx) const; + TRenderResourceManager *getManager(unsigned long renderId, + unsigned int idx) const; - void onRenderInstanceStart(unsigned long id); - void onRenderInstanceEnd(unsigned long id); + void onRenderInstanceStart(unsigned long id); + void onRenderInstanceEnd(unsigned long id); - bool renderHasOwnership() { return false; } + bool renderHasOwnership() { return false; } }; //=============================================================================================== -class RenderInstanceManagersBuilderGenerator : public TRenderResourceManagerGenerator -{ +class RenderInstanceManagersBuilderGenerator + : public TRenderResourceManagerGenerator { public: - TRenderResourceManager *operator()(void) - { - return RenderInstanceManagersBuilder::instance(); - } + TRenderResourceManager *operator()(void) { + return RenderInstanceManagersBuilder::instance(); + } }; -MANAGER_FILESCOPE_DECLARATION(RenderInstanceManagersBuilder, RenderInstanceManagersBuilderGenerator); +MANAGER_FILESCOPE_DECLARATION(RenderInstanceManagersBuilder, + RenderInstanceManagersBuilderGenerator); //*********************************************************************************************** // Stub managers and generators //*********************************************************************************************** /* -These manager-generator stubs are substitutes used to maintain dependency order about managers -which have render instance scope. They retrieve ordered event calls that are passed to the +These manager-generator stubs are substitutes used to maintain dependency order +about managers +which have render instance scope. They retrieve ordered event calls that are +passed to the dedicated instanceScope handler. */ -class InstanceResourceManagerStub : public TRenderResourceManager -{ - TRenderResourceManagerGenerator *m_generator; +class InstanceResourceManagerStub : public TRenderResourceManager { + TRenderResourceManagerGenerator *m_generator; public: - InstanceResourceManagerStub(TRenderResourceManagerGenerator *generator) - : m_generator(generator) - { - } + InstanceResourceManagerStub(TRenderResourceManagerGenerator *generator) + : m_generator(generator) {} - void onRenderInstanceStart(unsigned long id); - void onRenderInstanceEnd(unsigned long id); + void onRenderInstanceStart(unsigned long id); + void onRenderInstanceEnd(unsigned long id); - void onRenderFrameStart(double f); - void onRenderFrameEnd(double f); + void onRenderFrameStart(double f); + void onRenderFrameEnd(double f); - virtual void onRenderStatusStart(int renderStatus); - virtual void onRenderStatusEnd(int renderStatus); + virtual void onRenderStatusStart(int renderStatus); + virtual void onRenderStatusEnd(int renderStatus); }; //=============================================================================================== -class StubGenerator : public TRenderResourceManagerGenerator -{ - TRenderResourceManagerGenerator *m_generator; +class StubGenerator : public TRenderResourceManagerGenerator { + TRenderResourceManagerGenerator *m_generator; public: - StubGenerator(TRenderResourceManagerGenerator *generator) - : m_generator(generator) - { - } - - TRenderResourceManager *operator()() - { - return new InstanceResourceManagerStub(m_generator); - } + StubGenerator(TRenderResourceManagerGenerator *generator) + : m_generator(generator) {} + + TRenderResourceManager *operator()() { + return new InstanceResourceManagerStub(m_generator); + } }; //*********************************************************************************************** // TRenderResourceManagerGenerator methods //*********************************************************************************************** -std::vector &TRenderResourceManagerGenerator::generators() -{ - static std::vector generatorsInstance; - return generatorsInstance; +std::vector + &TRenderResourceManagerGenerator::generators() { + static std::vector generatorsInstance; + return generatorsInstance; } //------------------------------------------------------------------------- -std::vector &TRenderResourceManagerGenerator::generators(bool instanceScope) -{ - static std::vector generatorsInstance; - static std::vector generatorsRenderer; - return instanceScope ? generatorsInstance : generatorsRenderer; +std::vector + &TRenderResourceManagerGenerator::generators(bool instanceScope) { + static std::vector generatorsInstance; + static std::vector generatorsRenderer; + return instanceScope ? generatorsInstance : generatorsRenderer; } //=============================================================================================== -TRenderResourceManagerGenerator::TRenderResourceManagerGenerator(bool renderInstanceScope) - : m_instanceScope(renderInstanceScope) -{ - //In case this has a renderInstanceScope, build a stub generator - if (renderInstanceScope) { - RenderInstanceManagersBuilder::gen(); //Stubs depend on this manager +TRenderResourceManagerGenerator::TRenderResourceManagerGenerator( + bool renderInstanceScope) + : m_instanceScope(renderInstanceScope) { + // In case this has a renderInstanceScope, build a stub generator + if (renderInstanceScope) { + RenderInstanceManagersBuilder::gen(); // Stubs depend on this manager - static std::vector stubGenerators; - stubGenerators.push_back(new StubGenerator(this)); - } + static std::vector stubGenerators; + stubGenerators.push_back(new StubGenerator(this)); + } - generators().push_back(this); + generators().push_back(this); - std::vector &scopeGenerators = - generators(renderInstanceScope); + std::vector &scopeGenerators = + generators(renderInstanceScope); - scopeGenerators.push_back(this); - m_managerIndex = scopeGenerators.size() - 1; + scopeGenerators.push_back(this); + m_managerIndex = scopeGenerators.size() - 1; } //------------------------------------------------------------------------- -TRenderResourceManager *TRenderResourceManagerGenerator::getManager(const TRenderer &renderer) const -{ - return m_instanceScope ? 0 : renderer.getManager(m_managerIndex); +TRenderResourceManager *TRenderResourceManagerGenerator::getManager( + const TRenderer &renderer) const { + return m_instanceScope ? 0 : renderer.getManager(m_managerIndex); } //------------------------------------------------------------------------- -TRenderResourceManager *TRenderResourceManagerGenerator::getManager(unsigned long renderId) const -{ - return m_instanceScope ? RenderInstanceManagersBuilder::instance()->getManager(renderId, m_managerIndex) : 0; +TRenderResourceManager *TRenderResourceManagerGenerator::getManager( + unsigned long renderId) const { + return m_instanceScope + ? RenderInstanceManagersBuilder::instance()->getManager( + renderId, m_managerIndex) + : 0; } //*********************************************************************************************** // "Instance-scoped Managers" - Management methods //*********************************************************************************************** -RenderInstanceManagersBuilder *RenderInstanceManagersBuilder::instance() -{ - static RenderInstanceManagersBuilder theInstance; - return &theInstance; +RenderInstanceManagersBuilder *RenderInstanceManagersBuilder::instance() { + static RenderInstanceManagersBuilder theInstance; + return &theInstance; } //------------------------------------------------------------------------- -inline TRenderResourceManager *RenderInstanceManagersBuilder:: - getManager(unsigned long renderId, unsigned int idx) const -{ - std::map::const_iterator it = m_managersMap.find(renderId); - return it == m_managersMap.end() ? 0 : it->second[idx]; +inline TRenderResourceManager *RenderInstanceManagersBuilder::getManager( + unsigned long renderId, unsigned int idx) const { + std::map::const_iterator it = + m_managersMap.find(renderId); + return it == m_managersMap.end() ? 0 : it->second[idx]; } //------------------------------------------------------------------------- -void RenderInstanceManagersBuilder::onRenderInstanceStart(unsigned long id) -{ - //Build the instance managers - std::map::iterator it = - m_managersMap.insert(std::make_pair(id, ManagersVector())).first; +void RenderInstanceManagersBuilder::onRenderInstanceStart(unsigned long id) { + // Build the instance managers + std::map::iterator it = + m_managersMap.insert(std::make_pair(id, ManagersVector())).first; - std::vector &instanceScopeGenerators = - TRenderResourceManagerGenerator::generators(true); + std::vector &instanceScopeGenerators = + TRenderResourceManagerGenerator::generators(true); - unsigned int i; - for (i = 0; i < instanceScopeGenerators.size(); ++i) - it->second.push_back((*instanceScopeGenerators[i])()); + unsigned int i; + for (i = 0; i < instanceScopeGenerators.size(); ++i) + it->second.push_back((*instanceScopeGenerators[i])()); } //------------------------------------------------------------------------- -void RenderInstanceManagersBuilder::onRenderInstanceEnd(unsigned long id) -{ - //Delete the instance managers - std::map::iterator it = - m_managersMap.find(id); +void RenderInstanceManagersBuilder::onRenderInstanceEnd(unsigned long id) { + // Delete the instance managers + std::map::iterator it = m_managersMap.find(id); - assert(it != m_managersMap.end()); + assert(it != m_managersMap.end()); - unsigned int i; - for (i = 0; i < it->second.size(); ++i) { - if (it->second[i]->renderHasOwnership()) - delete it->second[i]; - } + unsigned int i; + for (i = 0; i < it->second.size(); ++i) { + if (it->second[i]->renderHasOwnership()) delete it->second[i]; + } - m_managersMap.erase(it); + m_managersMap.erase(it); } //=============================================================================================== -void InstanceResourceManagerStub::onRenderInstanceStart(unsigned long id) -{ - RenderInstanceManagersBuilder::instance()->getManager(id, - m_generator->getGeneratorIndex()) - ->onRenderInstanceStart(id); +void InstanceResourceManagerStub::onRenderInstanceStart(unsigned long id) { + RenderInstanceManagersBuilder::instance() + ->getManager(id, m_generator->getGeneratorIndex()) + ->onRenderInstanceStart(id); } //------------------------------------------------------------------------- -void InstanceResourceManagerStub::onRenderInstanceEnd(unsigned long id) -{ - RenderInstanceManagersBuilder::instance()->getManager(id, - m_generator->getGeneratorIndex()) - ->onRenderInstanceEnd(id); +void InstanceResourceManagerStub::onRenderInstanceEnd(unsigned long id) { + RenderInstanceManagersBuilder::instance() + ->getManager(id, m_generator->getGeneratorIndex()) + ->onRenderInstanceEnd(id); } //------------------------------------------------------------------------- -void InstanceResourceManagerStub::onRenderFrameStart(double f) -{ - RenderInstanceManagersBuilder::instance()->getManager( - TRenderer::renderId(), - m_generator->getGeneratorIndex()) - ->onRenderFrameStart(f); +void InstanceResourceManagerStub::onRenderFrameStart(double f) { + RenderInstanceManagersBuilder::instance() + ->getManager(TRenderer::renderId(), m_generator->getGeneratorIndex()) + ->onRenderFrameStart(f); } //------------------------------------------------------------------------- -void InstanceResourceManagerStub::onRenderFrameEnd(double f) -{ - RenderInstanceManagersBuilder::instance()->getManager( - TRenderer::renderId(), - m_generator->getGeneratorIndex()) - ->onRenderFrameEnd(f); +void InstanceResourceManagerStub::onRenderFrameEnd(double f) { + RenderInstanceManagersBuilder::instance() + ->getManager(TRenderer::renderId(), m_generator->getGeneratorIndex()) + ->onRenderFrameEnd(f); } //------------------------------------------------------------------------- -void InstanceResourceManagerStub::onRenderStatusStart(int renderStatus) -{ - RenderInstanceManagersBuilder::instance()->getManager( - TRenderer::renderId(), - m_generator->getGeneratorIndex()) - ->onRenderStatusStart(renderStatus); +void InstanceResourceManagerStub::onRenderStatusStart(int renderStatus) { + RenderInstanceManagersBuilder::instance() + ->getManager(TRenderer::renderId(), m_generator->getGeneratorIndex()) + ->onRenderStatusStart(renderStatus); } //------------------------------------------------------------------------- -void InstanceResourceManagerStub::onRenderStatusEnd(int renderStatus) -{ - RenderInstanceManagersBuilder::instance()->getManager( - TRenderer::renderId(), - m_generator->getGeneratorIndex()) - ->onRenderStatusEnd(renderStatus); +void InstanceResourceManagerStub::onRenderStatusEnd(int renderStatus) { + RenderInstanceManagersBuilder::instance() + ->getManager(TRenderer::renderId(), m_generator->getGeneratorIndex()) + ->onRenderStatusEnd(renderStatus); } diff --git a/toonz/sources/common/tfx/ttzpimagefx.cpp b/toonz/sources/common/tfx/ttzpimagefx.cpp index 33fbc1c..31d3f84 100644 --- a/toonz/sources/common/tfx/ttzpimagefx.cpp +++ b/toonz/sources/common/tfx/ttzpimagefx.cpp @@ -9,79 +9,76 @@ // Global functions //********************************************************************************************** -void parseIndexes(std::string indexes, std::vector &items) -{ +void parseIndexes(std::string indexes, std::vector &items) { #ifdef _WIN32 - char seps[] = " ,;"; - char *token; - if (indexes == "all" || indexes == "All" || indexes == "ALL") - indexes = "0-4095"; - char *context = 0; - token = strtok_s((char *)(indexes.c_str()), seps, &context); - while (token != NULL) { - items.push_back(token); - token = strtok_s(NULL, seps, &context); - } + char seps[] = " ,;"; + char *token; + if (indexes == "all" || indexes == "All" || indexes == "ALL") + indexes = "0-4095"; + char *context = 0; + token = strtok_s((char *)(indexes.c_str()), seps, &context); + while (token != NULL) { + items.push_back(token); + token = strtok_s(NULL, seps, &context); + } #else - char seps[] = " ,;"; - char *token; - if (indexes == "all" || indexes == "All" || indexes == "ALL") - indexes = "0-4095"; - token = strtok((char *)(indexes.c_str()), seps); - while (token != NULL) { - items.push_back(token); - token = strtok(NULL, seps); - } + char seps[] = " ,;"; + char *token; + if (indexes == "all" || indexes == "All" || indexes == "ALL") + indexes = "0-4095"; + token = strtok((char *)(indexes.c_str()), seps); + while (token != NULL) { + items.push_back(token); + token = strtok(NULL, seps); + } #endif } //------------------------------------------------------------------- -void insertIndexes(std::vector items, PaletteFilterFxRenderData *t) -{ +void insertIndexes(std::vector items, + PaletteFilterFxRenderData *t) { #ifdef _WIN32 - for (int i = 0; i < (int)items.size(); i++) { - char *starttoken, *endtoken; - char subseps[] = "-"; - std::string tmp = items[i]; - char *context = 0; - starttoken = strtok_s((char *)tmp.c_str(), subseps, &context); - endtoken = strtok_s(NULL, subseps, &context); - if (!endtoken && isInt(starttoken)) { - int index; - index = std::stoi(starttoken); - t->m_colors.insert(index); - } else { - if (isInt(starttoken) && isInt(endtoken)) { - int start, end; - start = std::stoi(starttoken); - end = std::stoi(endtoken); - for (int i = start; i <= end; i++) - t->m_colors.insert(i); - } - } - } + for (int i = 0; i < (int)items.size(); i++) { + char *starttoken, *endtoken; + char subseps[] = "-"; + std::string tmp = items[i]; + char *context = 0; + starttoken = strtok_s((char *)tmp.c_str(), subseps, &context); + endtoken = strtok_s(NULL, subseps, &context); + if (!endtoken && isInt(starttoken)) { + int index; + index = std::stoi(starttoken); + t->m_colors.insert(index); + } else { + if (isInt(starttoken) && isInt(endtoken)) { + int start, end; + start = std::stoi(starttoken); + end = std::stoi(endtoken); + for (int i = start; i <= end; i++) t->m_colors.insert(i); + } + } + } #else - for (int i = 0; i < (int)items.size(); i++) { - char *starttoken, *endtoken; - char subseps[] = "-"; - std::string tmp = items[i]; - starttoken = strtok((char *)tmp.c_str(), subseps); - endtoken = strtok(NULL, subseps); - if (!endtoken && isInt(starttoken)) { - int index; - index = std::stoi(starttoken); - t->m_colors.insert(index); - } else { - if (isInt(starttoken) && isInt(endtoken)) { - int start, end; - start = std::stoi(starttoken); - end = std::stoi(endtoken); - for (int i = start; i <= end; i++) - t->m_colors.insert(i); - } - } - } + for (int i = 0; i < (int)items.size(); i++) { + char *starttoken, *endtoken; + char subseps[] = "-"; + std::string tmp = items[i]; + starttoken = strtok((char *)tmp.c_str(), subseps); + endtoken = strtok(NULL, subseps); + if (!endtoken && isInt(starttoken)) { + int index; + index = std::stoi(starttoken); + t->m_colors.insert(index); + } else { + if (isInt(starttoken) && isInt(endtoken)) { + int start, end; + start = std::stoi(starttoken); + end = std::stoi(endtoken); + for (int i = start; i <= end; i++) t->m_colors.insert(i); + } + } + } #endif } @@ -89,188 +86,198 @@ void insertIndexes(std::vector items, PaletteFilterFxRenderData *t) // ExternalPaletteFxRenderData implementation //********************************************************************************************** -ExternalPaletteFxRenderData::ExternalPaletteFxRenderData(TPaletteP palette, const std::string &name) - : m_palette(palette), m_name(name) -{ -} +ExternalPaletteFxRenderData::ExternalPaletteFxRenderData( + TPaletteP palette, const std::string &name) + : m_palette(palette), m_name(name) {} //------------------------------------------------------------------------------ -bool ExternalPaletteFxRenderData::operator==(const TRasterFxRenderData &data) const -{ - return false; // non sono capace. non ho i pezzi per browsare nell'albero da qui. +bool ExternalPaletteFxRenderData::operator==( + const TRasterFxRenderData &data) const { + return false; // non sono capace. non ho i pezzi per browsare nell'albero da + // qui. } //------------------------------------------------------------------------------ -std::string ExternalPaletteFxRenderData::toString() const -{ - return m_name; -} +std::string ExternalPaletteFxRenderData::toString() const { return m_name; } //********************************************************************************************** // PaletteFilterFxRenderData implementation //********************************************************************************************** -PaletteFilterFxRenderData::PaletteFilterFxRenderData() -{ - m_keep = false; - m_type = eApplyToInksAndPaints; +PaletteFilterFxRenderData::PaletteFilterFxRenderData() { + m_keep = false; + m_type = eApplyToInksAndPaints; } //------------------------------------------------------------------------------ -bool PaletteFilterFxRenderData::operator==(const TRasterFxRenderData &data) const -{ - const PaletteFilterFxRenderData *theData = dynamic_cast(&data); - if (!theData) - return false; +bool PaletteFilterFxRenderData::operator==( + const TRasterFxRenderData &data) const { + const PaletteFilterFxRenderData *theData = + dynamic_cast(&data); + if (!theData) return false; - return (theData->m_colors == m_colors && theData->m_type == m_type && theData->m_keep == m_keep); + return (theData->m_colors == m_colors && theData->m_type == m_type && + theData->m_keep == m_keep); } //------------------------------------------------------------------------------ -std::string PaletteFilterFxRenderData::toString() const -{ - std::string alias; - std::set::const_iterator it = m_colors.begin(); - for (; it != m_colors.end(); ++it) - alias += std::to_string(*it); - alias += "keep=" + std::to_string(m_keep); - alias += "type=" + std::to_string(m_type); - return alias; +std::string PaletteFilterFxRenderData::toString() const { + std::string alias; + std::set::const_iterator it = m_colors.begin(); + for (; it != m_colors.end(); ++it) alias += std::to_string(*it); + alias += "keep=" + std::to_string(m_keep); + alias += "type=" + std::to_string(m_type); + return alias; } //********************************************************************************************** // SandorFxRenderData implementation //********************************************************************************************** -SandorFxRenderData::SandorFxRenderData(Type type, int argc, const char *argv[], int border, int shrink, - const TRectD &controllerBBox, const TRasterP &controller) - : m_type(type), m_border(border), m_shrink(shrink), m_blendParams(), m_callParams(), m_contourParams(), m_argc(argc), m_controllerBBox(controllerBBox), m_controller(controller), m_controllerAlias() -{ - for (int i = 0; i < argc; i++) - m_argv[i] = argv[i]; +SandorFxRenderData::SandorFxRenderData(Type type, int argc, const char *argv[], + int border, int shrink, + const TRectD &controllerBBox, + const TRasterP &controller) + : m_type(type) + , m_border(border) + , m_shrink(shrink) + , m_blendParams() + , m_callParams() + , m_contourParams() + , m_argc(argc) + , m_controllerBBox(controllerBBox) + , m_controller(controller) + , m_controllerAlias() { + for (int i = 0; i < argc; i++) m_argv[i] = argv[i]; } //------------------------------------------------------------------------------ -bool SandorFxRenderData::operator==(const TRasterFxRenderData &data) const -{ - const SandorFxRenderData *theData = dynamic_cast(&data); - if (!theData) - return false; - - if (m_type == BlendTz) - return (theData->m_blendParams.m_colorIndex == m_blendParams.m_colorIndex && - theData->m_blendParams.m_noBlending == m_blendParams.m_noBlending && - theData->m_blendParams.m_amount == m_blendParams.m_amount && - theData->m_blendParams.m_smoothness == m_blendParams.m_smoothness); - - if (m_type == Calligraphic || m_type == OutBorder) - return (theData->m_callParams.m_colorIndex == m_callParams.m_colorIndex && - theData->m_callParams.m_thickness == m_callParams.m_thickness && - theData->m_callParams.m_doWDiagonal == m_callParams.m_doWDiagonal && - theData->m_callParams.m_noise == m_callParams.m_noise && - theData->m_callParams.m_horizontal == m_callParams.m_horizontal && - theData->m_callParams.m_vertical == m_callParams.m_vertical && - theData->m_callParams.m_accuracy == m_callParams.m_accuracy && - theData->m_callParams.m_upWDiagonal == m_callParams.m_upWDiagonal); - - if (m_type == ArtAtContour) - return (theData->m_contourParams.m_density == m_contourParams.m_density && - theData->m_contourParams.m_colorIndex == m_contourParams.m_colorIndex && - theData->m_contourParams.m_keepLine == m_contourParams.m_keepLine && - theData->m_contourParams.m_maxOrientation == m_contourParams.m_maxOrientation && - theData->m_contourParams.m_maxDistance == m_contourParams.m_maxDistance && - theData->m_contourParams.m_maxSize == m_contourParams.m_maxSize && - theData->m_contourParams.m_minOrientation == m_contourParams.m_minOrientation && - theData->m_contourParams.m_minDistance == m_contourParams.m_minDistance && - theData->m_contourParams.m_minSize == m_contourParams.m_minSize && - theData->m_contourParams.m_randomness == m_contourParams.m_randomness && - theData->m_contourParams.m_keepColor == m_contourParams.m_keepColor && - theData->m_contourParams.m_includeAlpha == m_contourParams.m_includeAlpha && - theData->m_controllerAlias == m_controllerAlias); - - return false; +bool SandorFxRenderData::operator==(const TRasterFxRenderData &data) const { + const SandorFxRenderData *theData = + dynamic_cast(&data); + if (!theData) return false; + + if (m_type == BlendTz) + return (theData->m_blendParams.m_colorIndex == m_blendParams.m_colorIndex && + theData->m_blendParams.m_noBlending == m_blendParams.m_noBlending && + theData->m_blendParams.m_amount == m_blendParams.m_amount && + theData->m_blendParams.m_smoothness == m_blendParams.m_smoothness); + + if (m_type == Calligraphic || m_type == OutBorder) + return (theData->m_callParams.m_colorIndex == m_callParams.m_colorIndex && + theData->m_callParams.m_thickness == m_callParams.m_thickness && + theData->m_callParams.m_doWDiagonal == m_callParams.m_doWDiagonal && + theData->m_callParams.m_noise == m_callParams.m_noise && + theData->m_callParams.m_horizontal == m_callParams.m_horizontal && + theData->m_callParams.m_vertical == m_callParams.m_vertical && + theData->m_callParams.m_accuracy == m_callParams.m_accuracy && + theData->m_callParams.m_upWDiagonal == m_callParams.m_upWDiagonal); + + if (m_type == ArtAtContour) + return ( + theData->m_contourParams.m_density == m_contourParams.m_density && + theData->m_contourParams.m_colorIndex == m_contourParams.m_colorIndex && + theData->m_contourParams.m_keepLine == m_contourParams.m_keepLine && + theData->m_contourParams.m_maxOrientation == + m_contourParams.m_maxOrientation && + theData->m_contourParams.m_maxDistance == + m_contourParams.m_maxDistance && + theData->m_contourParams.m_maxSize == m_contourParams.m_maxSize && + theData->m_contourParams.m_minOrientation == + m_contourParams.m_minOrientation && + theData->m_contourParams.m_minDistance == + m_contourParams.m_minDistance && + theData->m_contourParams.m_minSize == m_contourParams.m_minSize && + theData->m_contourParams.m_randomness == m_contourParams.m_randomness && + theData->m_contourParams.m_keepColor == m_contourParams.m_keepColor && + theData->m_contourParams.m_includeAlpha == + m_contourParams.m_includeAlpha && + theData->m_controllerAlias == m_controllerAlias); + + return false; } //------------------------------------------------------------------------------ -std::string SandorFxRenderData::toString() const -{ - std::string alias; - if (m_type == BlendTz) { - alias += ::to_string(m_blendParams.m_colorIndex) + " "; - alias += std::to_string(m_blendParams.m_smoothness) + " "; - alias += std::to_string(m_blendParams.m_amount) + " "; - alias += std::to_string(m_blendParams.m_noBlending); - return alias; - } - - if (m_type == Calligraphic || m_type == OutBorder) { - alias += ::to_string(m_callParams.m_colorIndex) + " "; - alias += std::to_string(m_callParams.m_noise) + " "; - alias += std::to_string(m_callParams.m_accuracy) + " "; - alias += std::to_string(m_callParams.m_upWDiagonal) + " "; - alias += std::to_string(m_callParams.m_vertical) + " "; - alias += std::to_string(m_callParams.m_upWDiagonal) + " "; - alias += std::to_string(m_callParams.m_horizontal) + " "; - alias += std::to_string(m_callParams.m_thickness); - return alias; - } - - if (m_type == ArtAtContour) { - alias += std::to_string(m_contourParams.m_maxSize) + " "; - alias += std::to_string(m_contourParams.m_minSize) + " "; - alias += std::to_string(m_contourParams.m_maxOrientation) + " "; - alias += std::to_string(m_contourParams.m_minOrientation) + " "; - alias += std::to_string(m_contourParams.m_randomness) + " "; - alias += std::to_string(m_contourParams.m_maxDistance) + " "; - alias += std::to_string(m_contourParams.m_minDistance) + " "; - alias += std::to_string(m_contourParams.m_density) + " "; - alias += std::to_string(m_contourParams.m_keepLine) + " "; - alias += std::to_string(m_contourParams.m_keepColor) + " "; - alias += std::to_string(m_contourParams.m_includeAlpha) + " "; - alias += ::to_string(m_contourParams.m_colorIndex) + " "; - alias += m_controllerAlias; - return alias; - } - - return alias; +std::string SandorFxRenderData::toString() const { + std::string alias; + if (m_type == BlendTz) { + alias += ::to_string(m_blendParams.m_colorIndex) + " "; + alias += std::to_string(m_blendParams.m_smoothness) + " "; + alias += std::to_string(m_blendParams.m_amount) + " "; + alias += std::to_string(m_blendParams.m_noBlending); + return alias; + } + + if (m_type == Calligraphic || m_type == OutBorder) { + alias += ::to_string(m_callParams.m_colorIndex) + " "; + alias += std::to_string(m_callParams.m_noise) + " "; + alias += std::to_string(m_callParams.m_accuracy) + " "; + alias += std::to_string(m_callParams.m_upWDiagonal) + " "; + alias += std::to_string(m_callParams.m_vertical) + " "; + alias += std::to_string(m_callParams.m_upWDiagonal) + " "; + alias += std::to_string(m_callParams.m_horizontal) + " "; + alias += std::to_string(m_callParams.m_thickness); + return alias; + } + + if (m_type == ArtAtContour) { + alias += std::to_string(m_contourParams.m_maxSize) + " "; + alias += std::to_string(m_contourParams.m_minSize) + " "; + alias += std::to_string(m_contourParams.m_maxOrientation) + " "; + alias += std::to_string(m_contourParams.m_minOrientation) + " "; + alias += std::to_string(m_contourParams.m_randomness) + " "; + alias += std::to_string(m_contourParams.m_maxDistance) + " "; + alias += std::to_string(m_contourParams.m_minDistance) + " "; + alias += std::to_string(m_contourParams.m_density) + " "; + alias += std::to_string(m_contourParams.m_keepLine) + " "; + alias += std::to_string(m_contourParams.m_keepColor) + " "; + alias += std::to_string(m_contourParams.m_includeAlpha) + " "; + alias += ::to_string(m_contourParams.m_colorIndex) + " "; + alias += m_controllerAlias; + return alias; + } + + return alias; } //------------------------------------------------------------------------------ -TRectD SandorFxRenderData::getBBoxEnlargement(const TRectD &bbox) -{ - switch (m_type) { - case BlendTz: { - //Nothing happen, unless we have color 0 among the blended ones. In such case, - //we have to enlarge the bbox proportionally to the amount param. - std::vector items; - std::string indexes = std::string(m_argv[0]); - parseIndexes(indexes, items); - PaletteFilterFxRenderData paletteFilterData; - insertIndexes(items, &paletteFilterData); - - if (paletteFilterData.m_colors.size() > 0 && *paletteFilterData.m_colors.begin() == 0) - return bbox.enlarge(m_blendParams.m_amount); - - return bbox; - } - - case Calligraphic: - case OutBorder: - return bbox.enlarge(m_callParams.m_thickness); - - case ArtAtContour: - return bbox.enlarge( - std::max(tceil(m_controllerBBox.getLx()), tceil(m_controllerBBox.getLy())) * m_contourParams.m_maxSize); - - default: - assert(false); - return bbox; - } +TRectD SandorFxRenderData::getBBoxEnlargement(const TRectD &bbox) { + switch (m_type) { + case BlendTz: { + // Nothing happen, unless we have color 0 among the blended ones. In such + // case, + // we have to enlarge the bbox proportionally to the amount param. + std::vector items; + std::string indexes = std::string(m_argv[0]); + parseIndexes(indexes, items); + PaletteFilterFxRenderData paletteFilterData; + insertIndexes(items, &paletteFilterData); + + if (paletteFilterData.m_colors.size() > 0 && + *paletteFilterData.m_colors.begin() == 0) + return bbox.enlarge(m_blendParams.m_amount); + + return bbox; + } + + case Calligraphic: + case OutBorder: + return bbox.enlarge(m_callParams.m_thickness); + + case ArtAtContour: + return bbox.enlarge(std::max(tceil(m_controllerBBox.getLx()), + tceil(m_controllerBBox.getLy())) * + m_contourParams.m_maxSize); + + default: + assert(false); + return bbox; + } } diff --git a/toonz/sources/common/tfx/unaryFx.cpp b/toonz/sources/common/tfx/unaryFx.cpp index 68677b5..bb6e3b0 100644 --- a/toonz/sources/common/tfx/unaryFx.cpp +++ b/toonz/sources/common/tfx/unaryFx.cpp @@ -12,158 +12,148 @@ //============================================================================== -TGeometryFx::TGeometryFx() -{ - setName(L"Geometry"); -} +TGeometryFx::TGeometryFx() { setName(L"Geometry"); } //-------------------------------------------------- -void TGeometryFx::compute(TFlash &flash, int frame) -{ - flash.multMatrix(getPlacement(frame)); - TRasterFx::compute(flash, frame); +void TGeometryFx::compute(TFlash &flash, int frame) { + flash.multMatrix(getPlacement(frame)); + TRasterFx::compute(flash, frame); } //--------------------------------------------------------------- -void TGeometryFx::doCompute( - TTile &tile, - double frame, - const TRenderSettings &ri) -{ - TRasterFxPort *input = dynamic_cast(getInputPort(0)); - assert(input); +void TGeometryFx::doCompute(TTile &tile, double frame, + const TRenderSettings &ri) { + TRasterFxPort *input = dynamic_cast(getInputPort(0)); + assert(input); - if (!input->isConnected()) - return; + if (!input->isConnected()) return; - if (!getActiveTimeRegion().contains(frame)) { - TRasterFxP(input->getFx())->compute(tile, frame, ri); - return; - } + if (!getActiveTimeRegion().contains(frame)) { + TRasterFxP(input->getFx())->compute(tile, frame, ri); + return; + } - if (!TRaster32P(tile.getRaster()) && !TRaster64P(tile.getRaster())) - throw TException("AffineFx unsupported pixel type"); + if (!TRaster32P(tile.getRaster()) && !TRaster64P(tile.getRaster())) + throw TException("AffineFx unsupported pixel type"); - TAffine aff1 = getPlacement(frame); - TRenderSettings ri2(ri); - ri2.m_affine = ri2.m_affine * aff1; + TAffine aff1 = getPlacement(frame); + TRenderSettings ri2(ri); + ri2.m_affine = ri2.m_affine * aff1; - TRasterFxP src = getInputPort("source")->getFx(); - src->compute(tile, frame, ri2); - return; + TRasterFxP src = getInputPort("source")->getFx(); + src->compute(tile, frame, ri2); + return; } //-------------------------------------------------- -bool TGeometryFx::doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info) -{ - TRasterFxPort *input = dynamic_cast(getInputPort(0)); - assert(input); - - if (input->isConnected()) { - TRasterFxP fx = input->getFx(); - assert(fx); - bool ret = fx->doGetBBox(frame, bBox, info); - if (getActiveTimeRegion().contains(frame)) - bBox = getPlacement(frame) * bBox; - return ret; - } else { - bBox = TRectD(); - return false; - } - return true; +bool TGeometryFx::doGetBBox(double frame, TRectD &bBox, + const TRenderSettings &info) { + TRasterFxPort *input = dynamic_cast(getInputPort(0)); + assert(input); + + if (input->isConnected()) { + TRasterFxP fx = input->getFx(); + assert(fx); + bool ret = fx->doGetBBox(frame, bBox, info); + if (getActiveTimeRegion().contains(frame)) + bBox = getPlacement(frame) * bBox; + return ret; + } else { + bBox = TRectD(); + return false; + } + return true; }; //-------------------------------------------------- -std::string TGeometryFx::getAlias(double frame, const TRenderSettings &info) const -{ - TGeometryFx *tthis = const_cast(this); - TAffine affine = tthis->getPlacement(frame); - - std::string alias = getFxType(); - alias += "["; - - // alias degli effetti connessi alle porte di input separati da virgole - // una porta non connessa da luogo a un alias vuoto (stringa vuota) - - for (int i = 0; i < getInputPortCount(); ++i) { - TFxPort *port = getInputPort(i); - if (port->isConnected()) { - TRasterFxP ifx = port->getFx(); - assert(ifx); - alias += ifx->getAlias(frame, info); - } - alias += ","; - } - - return alias + - (areAlmostEqual(affine.a11, 0) ? "0" : ::to_string(affine.a11, 5)) + "," + - (areAlmostEqual(affine.a12, 0) ? "0" : ::to_string(affine.a12, 5)) + "," + - (areAlmostEqual(affine.a13, 0) ? "0" : ::to_string(affine.a13, 5)) + "," + - (areAlmostEqual(affine.a21, 0) ? "0" : ::to_string(affine.a21, 5)) + "," + - (areAlmostEqual(affine.a22, 0) ? "0" : ::to_string(affine.a22, 5)) + "," + - (areAlmostEqual(affine.a23, 0) ? "0" : ::to_string(affine.a23, 5)) + "]"; +std::string TGeometryFx::getAlias(double frame, + const TRenderSettings &info) const { + TGeometryFx *tthis = const_cast(this); + TAffine affine = tthis->getPlacement(frame); + + std::string alias = getFxType(); + alias += "["; + + // alias degli effetti connessi alle porte di input separati da virgole + // una porta non connessa da luogo a un alias vuoto (stringa vuota) + + for (int i = 0; i < getInputPortCount(); ++i) { + TFxPort *port = getInputPort(i); + if (port->isConnected()) { + TRasterFxP ifx = port->getFx(); + assert(ifx); + alias += ifx->getAlias(frame, info); + } + alias += ","; + } + + return alias + + (areAlmostEqual(affine.a11, 0) ? "0" : ::to_string(affine.a11, 5)) + + "," + + (areAlmostEqual(affine.a12, 0) ? "0" : ::to_string(affine.a12, 5)) + + "," + + (areAlmostEqual(affine.a13, 0) ? "0" : ::to_string(affine.a13, 5)) + + "," + + (areAlmostEqual(affine.a21, 0) ? "0" : ::to_string(affine.a21, 5)) + + "," + + (areAlmostEqual(affine.a22, 0) ? "0" : ::to_string(affine.a22, 5)) + + "," + + (areAlmostEqual(affine.a23, 0) ? "0" : ::to_string(affine.a23, 5)) + + "]"; } //-------------------------------------------------- -void TGeometryFx::transform(double frame, - int port, - const TRectD &rectOnOutput, - const TRenderSettings &infoOnOutput, - TRectD &rectOnInput, - TRenderSettings &infoOnInput) -{ - rectOnInput = rectOnOutput; - TAffine aff = getPlacement(frame); - - infoOnInput = infoOnOutput; - infoOnInput.m_affine = infoOnInput.m_affine * aff; +void TGeometryFx::transform(double frame, int port, const TRectD &rectOnOutput, + const TRenderSettings &infoOnOutput, + TRectD &rectOnInput, TRenderSettings &infoOnInput) { + rectOnInput = rectOnOutput; + TAffine aff = getPlacement(frame); + + infoOnInput = infoOnOutput; + infoOnInput.m_affine = infoOnInput.m_affine * aff; } //================================================== NaAffineFx::NaAffineFx(bool isDpiAffine) - : m_aff(TAffine()), m_isDpiAffine(isDpiAffine) -{ - addInputPort("source", m_port); - setName(L"Geometry-NaAffineFx"); + : m_aff(TAffine()), m_isDpiAffine(isDpiAffine) { + addInputPort("source", m_port); + setName(L"Geometry-NaAffineFx"); } //-------------------------------------------------- -TFx *NaAffineFx::clone(bool recursive) const -{ - NaAffineFx *clonedFx = dynamic_cast(TFx::clone(recursive)); - assert(clonedFx); - clonedFx->m_aff = m_aff; - clonedFx->m_isDpiAffine = m_isDpiAffine; - return clonedFx; +TFx *NaAffineFx::clone(bool recursive) const { + NaAffineFx *clonedFx = dynamic_cast(TFx::clone(recursive)); + assert(clonedFx); + clonedFx->m_aff = m_aff; + clonedFx->m_isDpiAffine = m_isDpiAffine; + return clonedFx; } //-------------------------------------------------- -void NaAffineFx::compute(TFlash &flash, int frame) -{ - TGeometryFx::compute(flash, frame); +void NaAffineFx::compute(TFlash &flash, int frame) { + TGeometryFx::compute(flash, frame); } //================================================== -void TRasterFx::compute(TFlash &flash, int frame) -{ - for (int i = getInputPortCount() - 1; i >= 0; i--) { - TFxPort *port = getInputPort(i); - - if (port->isConnected() && !port->isaControlPort()) { - flash.pushMatrix(); - ((TRasterFxP)(port->getFx()))->compute(flash, frame); - flash.popMatrix(); - } - } +void TRasterFx::compute(TFlash &flash, int frame) { + for (int i = getInputPortCount() - 1; i >= 0; i--) { + TFxPort *port = getInputPort(i); + + if (port->isConnected() && !port->isaControlPort()) { + flash.pushMatrix(); + ((TRasterFxP)(port->getFx()))->compute(flash, frame); + flash.popMatrix(); + } + } } //-------------------------------------------------- @@ -180,47 +170,48 @@ FX_IDENTIFIER_IS_HIDDEN(NaAffineFx, "naAffineFx") //------------------------------------------------------------------------------ -class InvertFx : public TBaseRasterFx -{ - FX_DECLARATION(InvertFx) - TRasterFxPort m_input; - TBoolParamP m_redChan, m_greenChan, m_blueChan, m_alphaChan; +class InvertFx : public TBaseRasterFx { + FX_DECLARATION(InvertFx) + TRasterFxPort m_input; + TBoolParamP m_redChan, m_greenChan, m_blueChan, m_alphaChan; public: - InvertFx() : m_redChan(true), m_greenChan(true), m_blueChan(true), m_alphaChan(false) - { - addInputPort("source", m_input); - // bindParam(this, "red_channel" , m_redChan); - // bindParam(this, "green_channel", m_greenChan); - // bindParam(this, "blue_channel" , m_blueChan); - // bindParam(this, "alpha_channel", m_alphaChan); - setName(L"InvertFx"); - }; - - ~InvertFx(){}; - - bool canHandle(const TRenderSettings &info, double frame) { return true; } - - bool doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info) - { - if (m_input.isConnected()) { - bool ret = m_input->doGetBBox(frame, bBox, info); - return ret; - } else { - bBox = TRectD(); - return false; - } - }; - - void doCompute(TTile &tile, double frame, const TRenderSettings &ri) - { - if (!m_input.isConnected()) - return; - - m_input->compute(tile, frame, ri); - - TRop::invert(tile.getRaster(), m_redChan->getValue(), m_greenChan->getValue(), m_blueChan->getValue(), m_alphaChan->getValue()); - } + InvertFx() + : m_redChan(true) + , m_greenChan(true) + , m_blueChan(true) + , m_alphaChan(false) { + addInputPort("source", m_input); + // bindParam(this, "red_channel" , m_redChan); + // bindParam(this, "green_channel", m_greenChan); + // bindParam(this, "blue_channel" , m_blueChan); + // bindParam(this, "alpha_channel", m_alphaChan); + setName(L"InvertFx"); + }; + + ~InvertFx(){}; + + bool canHandle(const TRenderSettings &info, double frame) { return true; } + + bool doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info) { + if (m_input.isConnected()) { + bool ret = m_input->doGetBBox(frame, bBox, info); + return ret; + } else { + bBox = TRectD(); + return false; + } + }; + + void doCompute(TTile &tile, double frame, const TRenderSettings &ri) { + if (!m_input.isConnected()) return; + + m_input->compute(tile, frame, ri); + + TRop::invert(tile.getRaster(), m_redChan->getValue(), + m_greenChan->getValue(), m_blueChan->getValue(), + m_alphaChan->getValue()); + } }; //================================================================== @@ -232,16 +223,16 @@ public: //=== // Geometric -//FX_IDENTIFIER(ScaleFx, "scaleFx") -//FX_IDENTIFIER(MoveFx, "moveFx") -//FX_IDENTIFIER(AffineFx, "affineFx") -//FX_IDENTIFIER(CropFx, "cropFx") +// FX_IDENTIFIER(ScaleFx, "scaleFx") +// FX_IDENTIFIER(MoveFx, "moveFx") +// FX_IDENTIFIER(AffineFx, "affineFx") +// FX_IDENTIFIER(CropFx, "cropFx") // Color FX_IDENTIFIER(InvertFx, "invertFx") // Video -//FX_IDENTIFIER(FieldFx, "fieldFx") -//FX_IDENTIFIER(SwapFieldsFx, "swapFieldsFx") -//FX_IDENTIFIER(DeInterlaceFx, "deInterlaceFx") -//FX_IDENTIFIER(InterlaceFx, "interlaceFx") +// FX_IDENTIFIER(FieldFx, "fieldFx") +// FX_IDENTIFIER(SwapFieldsFx, "swapFieldsFx") +// FX_IDENTIFIER(DeInterlaceFx, "deInterlaceFx") +// FX_IDENTIFIER(InterlaceFx, "interlaceFx") diff --git a/toonz/sources/common/tfx/zeraryFx.cpp b/toonz/sources/common/tfx/zeraryFx.cpp index 3ac4f0c..3554262 100644 --- a/toonz/sources/common/tfx/zeraryFx.cpp +++ b/toonz/sources/common/tfx/zeraryFx.cpp @@ -16,96 +16,88 @@ //================================================================== -class ColorCardFx : public TBaseZeraryFx -{ - FX_DECLARATION(ColorCardFx) +class ColorCardFx : public TBaseZeraryFx { + FX_DECLARATION(ColorCardFx) - TPixelParamP m_color; + TPixelParamP m_color; public: - ColorCardFx() : m_color(TPixel32::Green) - { - bindParam(this, "color", m_color); - m_color->setDefaultValue(TPixel32::Green); - setName(L"ColorCardFx"); - } - - bool canHandle(const TRenderSettings &info, double frame) { return true; } - - bool doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info) - { - bBox = TConsts::infiniteRectD; - return true; - } - - void doCompute(TTile &tile, double frame, const TRenderSettings &) - { - TRaster32P raster32 = tile.getRaster(); - if (raster32) - raster32->fill(m_color->getPremultipliedValue(frame)); - else { - TRaster64P ras64 = tile.getRaster(); - if (ras64) - ras64->fill(toPixel64(m_color->getPremultipliedValue(frame))); - else - throw TException("ColorCardFx unsupported pixel type"); - } - }; + ColorCardFx() : m_color(TPixel32::Green) { + bindParam(this, "color", m_color); + m_color->setDefaultValue(TPixel32::Green); + setName(L"ColorCardFx"); + } + + bool canHandle(const TRenderSettings &info, double frame) { return true; } + + bool doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info) { + bBox = TConsts::infiniteRectD; + return true; + } + + void doCompute(TTile &tile, double frame, const TRenderSettings &) { + TRaster32P raster32 = tile.getRaster(); + if (raster32) + raster32->fill(m_color->getPremultipliedValue(frame)); + else { + TRaster64P ras64 = tile.getRaster(); + if (ras64) + ras64->fill(toPixel64(m_color->getPremultipliedValue(frame))); + else + throw TException("ColorCardFx unsupported pixel type"); + } + }; }; //================================================================== -class CheckBoardFx : public TBaseZeraryFx -{ - FX_DECLARATION(CheckBoardFx) +class CheckBoardFx : public TBaseZeraryFx { + FX_DECLARATION(CheckBoardFx) - TPixelParamP m_color1, m_color2; - TDoubleParamP m_size; + TPixelParamP m_color1, m_color2; + TDoubleParamP m_size; public: - CheckBoardFx() : m_color1(TPixel32::Black), m_color2(TPixel32::White), m_size(50) - { - m_size->setMeasureName("fxLength"); - bindParam(this, "color1", m_color1); - bindParam(this, "color2", m_color2); - bindParam(this, "size", m_size); - m_color1->setDefaultValue(TPixel32::Black); - m_color2->setDefaultValue(TPixel32::White); - m_size->setValueRange(1, 1000); - m_size->setDefaultValue(50); - setName(L"CheckBoardFx"); - } - - bool canHandle(const TRenderSettings &info, double frame) { return false; } - - bool doGetBBox(double, TRectD &bBox, const TRenderSettings &info) - { - bBox = TConsts::infiniteRectD; - return true; - } - - void doCompute(TTile &tile, double frame, const TRenderSettings &info) - { - const TPixel32 &c1 = m_color1->getValue(frame); - const TPixel32 &c2 = m_color2->getValue(frame); - - double size = m_size->getValue(frame); - - assert(info.m_shrinkX == info.m_shrinkY); - size *= info.m_affine.a11 / info.m_shrinkX; - - TDimensionD dim(size, size); - TRop::checkBoard(tile.getRaster(), c1, c2, dim, tile.m_pos); - } - - void getParamUIs(TParamUIConcept *&concepts, int &length) - { - concepts = new TParamUIConcept[length = 1]; - - concepts[0].m_type = TParamUIConcept::SIZE; - concepts[0].m_label = "Size"; - concepts[0].m_params.push_back(m_size); - } + CheckBoardFx() + : m_color1(TPixel32::Black), m_color2(TPixel32::White), m_size(50) { + m_size->setMeasureName("fxLength"); + bindParam(this, "color1", m_color1); + bindParam(this, "color2", m_color2); + bindParam(this, "size", m_size); + m_color1->setDefaultValue(TPixel32::Black); + m_color2->setDefaultValue(TPixel32::White); + m_size->setValueRange(1, 1000); + m_size->setDefaultValue(50); + setName(L"CheckBoardFx"); + } + + bool canHandle(const TRenderSettings &info, double frame) { return false; } + + bool doGetBBox(double, TRectD &bBox, const TRenderSettings &info) { + bBox = TConsts::infiniteRectD; + return true; + } + + void doCompute(TTile &tile, double frame, const TRenderSettings &info) { + const TPixel32 &c1 = m_color1->getValue(frame); + const TPixel32 &c2 = m_color2->getValue(frame); + + double size = m_size->getValue(frame); + + assert(info.m_shrinkX == info.m_shrinkY); + size *= info.m_affine.a11 / info.m_shrinkX; + + TDimensionD dim(size, size); + TRop::checkBoard(tile.getRaster(), c1, c2, dim, tile.m_pos); + } + + void getParamUIs(TParamUIConcept *&concepts, int &length) { + concepts = new TParamUIConcept[length = 1]; + + concepts[0].m_type = TParamUIConcept::SIZE; + concepts[0].m_label = "Size"; + concepts[0].m_params.push_back(m_size); + } }; //================================================================== diff --git a/toonz/sources/common/tgeometry/tcurves.cpp b/toonz/sources/common/tgeometry/tcurves.cpp index 7a5c8e4..9d73f6a 100644 --- a/toonz/sources/common/tgeometry/tcurves.cpp +++ b/toonz/sources/common/tgeometry/tcurves.cpp @@ -10,180 +10,165 @@ using namespace std; //============================================================================= -ostream &operator<<(ostream &out, const TSegment &segment) -{ - return out << "S{" << segment.getP0() << ", " << segment.getP1() << "}"; +ostream &operator<<(ostream &out, const TSegment &segment) { + return out << "S{" << segment.getP0() << ", " << segment.getP1() << "}"; } //============================================================================= -void TCubic::split(double t, TCubic &first, TCubic &second) const -{ - double s = 1.0 - t; +void TCubic::split(double t, TCubic &first, TCubic &second) const { + double s = 1.0 - t; - TPointD H = s * m_p1 + t * m_p2; + TPointD H = s * m_p1 + t * m_p2; - first.m_p0 = m_p0; - first.m_p1 = s * m_p0 + t * m_p1; - first.m_p2 = s * first.m_p1 + t * H; + first.m_p0 = m_p0; + first.m_p1 = s * m_p0 + t * m_p1; + first.m_p2 = s * first.m_p1 + t * H; - second.m_p3 = m_p3; - second.m_p2 = s * m_p2 + t * m_p3; - second.m_p1 = s * H + t * second.m_p2; + second.m_p3 = m_p3; + second.m_p2 = s * m_p2 + t * m_p3; + second.m_p1 = s * H + t * second.m_p2; - first.m_p3 = s * first.m_p2 + t * second.m_p1; - second.m_p0 = first.m_p3; + first.m_p3 = s * first.m_p2 + t * second.m_p1; + second.m_p0 = first.m_p3; } -double TCubic::getLength(double t0, double t1) const -{ - return -1; -} +double TCubic::getLength(double t0, double t1) const { return -1; } //============================================================================= -TPointD TQuadratic::getPoint(double t) const -{ - double s = 1 - t; - return m_p0 * s * s + 2 * t * s * m_p1 + t * t * m_p2; +TPointD TQuadratic::getPoint(double t) const { + double s = 1 - t; + return m_p0 * s * s + 2 * t * s * m_p1 + t * t * m_p2; } //----------------------------------------------------------------------------- -double TQuadratic::getX(double t) const -{ - double s = 1 - t; - return m_p0.x * s * s + 2 * t * s * m_p1.x + t * t * m_p2.x; +double TQuadratic::getX(double t) const { + double s = 1 - t; + return m_p0.x * s * s + 2 * t * s * m_p1.x + t * t * m_p2.x; } //----------------------------------------------------------------------------- -double TQuadratic::getY(double t) const -{ - double s = 1 - t; - return m_p0.y * s * s + 2 * t * s * m_p1.y + t * t * m_p2.y; +double TQuadratic::getY(double t) const { + double s = 1 - t; + return m_p0.y * s * s + 2 * t * s * m_p1.y + t * t * m_p2.y; } //----------------------------------------------------------------------------- -double TQuadratic::getT(const TPointD &p) const -{ - - // risolvo l'equazione min|| b(t) - p || +double TQuadratic::getT(const TPointD &p) const { + // risolvo l'equazione min|| b(t) - p || - // esprimo b in forma di polinomio ed ottengo - // - // || 2 || - //min || a t + b t + c - p || - // || || - // - // il tutto si riconduce a cercare le radici - // di un'equazione del tipo - // 2 3 2 2 - // 2·a ·t + 3·a·b·t + t·(2·a·v + b ) + b·v - // dove v e' pari a c - p + // esprimo b in forma di polinomio ed ottengo + // + // || 2 || + // min || a t + b t + c - p || + // || || + // + // il tutto si riconduce a cercare le radici + // di un'equazione del tipo + // 2 3 2 2 + // 2·a ·t + 3·a·b·t + t·(2·a·v + b ) + b·v + // dove v e' pari a c - p - vector - bez(3), - poly(3); + vector bez(3), poly(3); - bez[0] = m_p0; - bez[1] = m_p1; - bez[2] = m_p2; + bez[0] = m_p0; + bez[1] = m_p1; + bez[2] = m_p2; - bezier2poly(bez, poly); + bezier2poly(bez, poly); - TPointD v = poly[0] - p; + TPointD v = poly[0] - p; - vector toSolve(4); - vector sol; + vector toSolve(4); + vector sol; - toSolve[3] = 2.0 * norm2(poly[2]); - toSolve[2] = 3.0 * (poly[2].x * poly[1].x + poly[2].y * poly[1].y); - toSolve[1] = 2.0 * (poly[2].x * v.x + poly[2].y * v.y) + norm2(poly[1]); - toSolve[0] = (poly[1].x * v.x + poly[1].y * v.y); + toSolve[3] = 2.0 * norm2(poly[2]); + toSolve[2] = 3.0 * (poly[2].x * poly[1].x + poly[2].y * poly[1].y); + toSolve[1] = 2.0 * (poly[2].x * v.x + poly[2].y * v.y) + norm2(poly[1]); + toSolve[0] = (poly[1].x * v.x + poly[1].y * v.y); - int nSol = rootFinding(toSolve, sol); + int nSol = rootFinding(toSolve, sol); - if (-1 == nSol) // infinite soluzioni - return 0; + if (-1 == nSol) // infinite soluzioni + return 0; - int minParameter = -1; - double minDist = (std::numeric_limits::max)(); + int minParameter = -1; + double minDist = (std::numeric_limits::max)(); - for (int i = 0; i < nSol; ++i) { - if (sol[i] < 0.0) - sol[i] = 0.0; - else if (sol[i] > 1.0) - sol[i] = 1.0; + for (int i = 0; i < nSol; ++i) { + if (sol[i] < 0.0) + sol[i] = 0.0; + else if (sol[i] > 1.0) + sol[i] = 1.0; - double tmpDist = tdistance2(p, getPoint(sol[i])); - if (tmpDist < minDist) { - minDist = tmpDist; - minParameter = i; - } - } + double tmpDist = tdistance2(p, getPoint(sol[i])); + if (tmpDist < minDist) { + minDist = tmpDist; + minParameter = i; + } + } - if (minParameter != -1) - return sol[minParameter]; + if (minParameter != -1) return sol[minParameter]; - return tdistance2(m_p0, p) < tdistance2(m_p2, p) ? 0 : 1; + return tdistance2(m_p0, p) < tdistance2(m_p2, p) ? 0 : 1; } //----------------------------------------------------------------------------- -void TQuadratic::split(double t, TQuadratic &left, TQuadratic &right) const -{ - double dt; - TPointD p; - dt = 1.0 - t; +void TQuadratic::split(double t, TQuadratic &left, TQuadratic &right) const { + double dt; + TPointD p; + dt = 1.0 - t; - left.m_p0 = m_p0; - right.m_p2 = m_p2; + left.m_p0 = m_p0; + right.m_p2 = m_p2; - left.m_p1 = dt * m_p0 + t * m_p1; - right.m_p1 = dt * m_p1 + t * m_p2; - p = dt * left.m_p1 + t * right.m_p1; + left.m_p1 = dt * m_p0 + t * m_p1; + right.m_p1 = dt * m_p1 + t * m_p2; + p = dt * left.m_p1 + t * right.m_p1; - left.m_p2 = right.m_p0 = p; + left.m_p2 = right.m_p0 = p; } //----------------------------------------------------------------------------- -TRectD TQuadratic::getBBox() const -{ - TRectD bBox; - if (m_p0.x < m_p2.x) - bBox.x0 = m_p0.x, bBox.x1 = m_p2.x; - else - bBox.x0 = m_p2.x, bBox.x1 = m_p0.x; - - if (m_p0.y < m_p2.y) - bBox.y0 = m_p0.y, bBox.y1 = m_p2.y; - else - bBox.y0 = m_p2.y, bBox.y1 = m_p0.y; - - TPointD denom = 2 * m_p1 - m_p0 - m_p2; - if (denom.x != 0) { - double tx = (m_p1.x - m_p0.x) / denom.x; - if (tx >= 0 && tx <= 1) { - double x = getPoint(tx).x; - if (x < bBox.x0) - bBox.x0 = x; - else if (x > bBox.x1) - bBox.x1 = x; - } - } - if (denom.y != 0) { - double ty = (m_p1.y - m_p0.y) / denom.y; - if (ty >= 0 && ty <= 1) { - double y = getPoint(ty).y; - if (y < bBox.y0) - bBox.y0 = y; - else if (y > bBox.y1) - bBox.y1 = y; - } - } - - return bBox; +TRectD TQuadratic::getBBox() const { + TRectD bBox; + if (m_p0.x < m_p2.x) + bBox.x0 = m_p0.x, bBox.x1 = m_p2.x; + else + bBox.x0 = m_p2.x, bBox.x1 = m_p0.x; + + if (m_p0.y < m_p2.y) + bBox.y0 = m_p0.y, bBox.y1 = m_p2.y; + else + bBox.y0 = m_p2.y, bBox.y1 = m_p0.y; + + TPointD denom = 2 * m_p1 - m_p0 - m_p2; + if (denom.x != 0) { + double tx = (m_p1.x - m_p0.x) / denom.x; + if (tx >= 0 && tx <= 1) { + double x = getPoint(tx).x; + if (x < bBox.x0) + bBox.x0 = x; + else if (x > bBox.x1) + bBox.x1 = x; + } + } + if (denom.y != 0) { + double ty = (m_p1.y - m_p0.y) / denom.y; + if (ty >= 0 && ty <= 1) { + double y = getPoint(ty).y; + if (y < bBox.y0) + bBox.y0 = y; + else if (y > bBox.y1) + bBox.y1 = y; + } + } + + return bBox; } /*! @@ -191,299 +176,280 @@ Calcolo della curvatura per una Quadratica. Vedi Farin pag.176 per la spiegazione della formula usata. */ -double TQuadratic::getCurvature(double t) const -{ - assert(0 <= t && t <= 1.0); +double TQuadratic::getCurvature(double t) const { + assert(0 <= t && t <= 1.0); - TQuadratic q1, q2; + TQuadratic q1, q2; - split(t, q1, q2); + split(t, q1, q2); - double signum = 1.0; - if (areAlmostEqual(t, 1.0)) { - signum *= -1.0; - std::swap(q1, q2); - std::swap(q2.m_p0, q2.m_p2); - } + double signum = 1.0; + if (areAlmostEqual(t, 1.0)) { + signum *= -1.0; + std::swap(q1, q2); + std::swap(q2.m_p0, q2.m_p2); + } - TPointD v_1_0(q2.m_p1 - q2.m_p0); + TPointD v_1_0(q2.m_p1 - q2.m_p0); - double - a = norm2(v_1_0); + double a = norm2(v_1_0); - if (isAlmostZero(a)) - return (std::numeric_limits::max)(); + if (isAlmostZero(a)) return (std::numeric_limits::max)(); - a = 1.0 / sqrt(a); + a = 1.0 / sqrt(a); - double - b = cross(v_1_0 * a, q2.m_p2 - q2.m_p0); + double b = cross(v_1_0 * a, q2.m_p2 - q2.m_p0); - return 0.5 * signum * b / a; + return 0.5 * signum * b / a; } //----------------------------------------------------------------------------- -double TQuadratic::getLength(double t0, double t1) const -{ - TQuadraticLengthEvaluator lengthEval(*this); +double TQuadratic::getLength(double t0, double t1) const { + TQuadraticLengthEvaluator lengthEval(*this); - t0 = min(max(0.0, t0), 1.0); // backward compatibility - t1 = min(max(0.0, t1), 1.0); // backward compatibility - if (t0 > t1) - std::swap(t0, t1); + t0 = min(max(0.0, t0), 1.0); // backward compatibility + t1 = min(max(0.0, t1), 1.0); // backward compatibility + if (t0 > t1) std::swap(t0, t1); - if (t0 > 0.0) - return lengthEval.getLengthAt(t1) - lengthEval.getLengthAt(t0); + if (t0 > 0.0) return lengthEval.getLengthAt(t1) - lengthEval.getLengthAt(t0); - return lengthEval.getLengthAt(t1); + return lengthEval.getLengthAt(t1); } -double TQuadratic::getApproximateLength(double t0, double t1, double error) const -{ - if (t0 == t1) - return 0; +double TQuadratic::getApproximateLength(double t0, double t1, + double error) const { + if (t0 == t1) return 0; - t0 = min(max(0.0, t0), 1.0); - t1 = min(max(0.0, t1), 1.0); + t0 = min(max(0.0, t0), 1.0); + t1 = min(max(0.0, t1), 1.0); - if (t0 > t1) - std::swap(t0, t1); + if (t0 > t1) std::swap(t0, t1); - TQuadratic q; + TQuadratic q; - if (t0 == 0.0 && t1 == 1.0) - q = *this; - else { - TQuadratic q1; - split(t0, q, q1); + if (t0 == 0.0 && t1 == 1.0) + q = *this; + else { + TQuadratic q1; + split(t0, q, q1); - assert(t0 != 1.0); + assert(t0 != 1.0); - double newPar = (t1 - t0) / (1.0 - t0); - q1.split(newPar, q, q1); - } + double newPar = (t1 - t0) / (1.0 - t0); + q1.split(newPar, q, q1); + } - double step = computeStep(q, error); + double step = computeStep(q, error); - double length = 0.0; + double length = 0.0; - TPointD p1 = q.getP0(); - TPointD p2; - for (double t = step; t < 1.0; t += step) { - p2 = q.getPoint(t); - length += tdistance(p1, p2); - p1 = p2; - } - length += tdistance(p1, q.getP2()); + TPointD p1 = q.getP0(); + TPointD p2; + for (double t = step; t < 1.0; t += step) { + p2 = q.getPoint(t); + length += tdistance(p1, p2); + p1 = p2; + } + length += tdistance(p1, q.getP2()); - return length; + return length; } //----------------------------------------------------------------------------- -int TQuadratic::getX(double y, double &x0, double &x1) const -{ - int ret = 0; - double t; - - if (y > getBBox().y1 || y < getBBox().y0) - return 0; - - double a = getP0().y - 2 * getP1().y + getP2().y; - double half_b = getP1().y - getP0().y; - double c = getP0().y - y; - - if (a == 0) //segment - { - if (half_b == 0) //horizontal segment, or point - { - if (c == 0) { - x0 = getP0().x; - x1 = getP2().x; - return 2; - } else - return 0; - } else { - t = -c / (2 * half_b); - if (t >= 0 && t <= 1) { - x0 = getPoint(t).x; - return 1; - } - } - } - - double discr = half_b * half_b - a * c; - - if (discr < 0) - return 0; - - double coeff = 1.0 / a; - double coeff1 = -half_b * coeff; - - if (discr == 0) { - t = coeff1; - if (t >= 0 && t <= 1) { - ret = 2; - x0 = x1 = getPoint(t).x; - } - } else { - discr = sqrt(discr) * coeff; - t = coeff1 + discr; - if (t >= 0 && t <= 1) { - ret++; - x0 = getPoint(t).x; - } - - t = coeff1 - discr; - if (t >= 0 && t <= 1) { - ret++; - if (ret == 2) - x1 = getPoint(t).x; - else - x0 = getPoint(t).x; - } - } - return ret; -} - -int TQuadratic::getY(double y, double &y0, double &y1) const -{ - TQuadratic temp(*this); - - swap(temp.m_p0.x, temp.m_p0.y); - swap(temp.m_p1.x, temp.m_p1.y); - swap(temp.m_p2.x, temp.m_p2.y); - - return temp.getX(y, y0, y1); +int TQuadratic::getX(double y, double &x0, double &x1) const { + int ret = 0; + double t; + + if (y > getBBox().y1 || y < getBBox().y0) return 0; + + double a = getP0().y - 2 * getP1().y + getP2().y; + double half_b = getP1().y - getP0().y; + double c = getP0().y - y; + + if (a == 0) // segment + { + if (half_b == 0) // horizontal segment, or point + { + if (c == 0) { + x0 = getP0().x; + x1 = getP2().x; + return 2; + } else + return 0; + } else { + t = -c / (2 * half_b); + if (t >= 0 && t <= 1) { + x0 = getPoint(t).x; + return 1; + } + } + } + + double discr = half_b * half_b - a * c; + + if (discr < 0) return 0; + + double coeff = 1.0 / a; + double coeff1 = -half_b * coeff; + + if (discr == 0) { + t = coeff1; + if (t >= 0 && t <= 1) { + ret = 2; + x0 = x1 = getPoint(t).x; + } + } else { + discr = sqrt(discr) * coeff; + t = coeff1 + discr; + if (t >= 0 && t <= 1) { + ret++; + x0 = getPoint(t).x; + } + + t = coeff1 - discr; + if (t >= 0 && t <= 1) { + ret++; + if (ret == 2) + x1 = getPoint(t).x; + else + x0 = getPoint(t).x; + } + } + return ret; +} + +int TQuadratic::getY(double y, double &y0, double &y1) const { + TQuadratic temp(*this); + + swap(temp.m_p0.x, temp.m_p0.y); + swap(temp.m_p1.x, temp.m_p1.y); + swap(temp.m_p2.x, temp.m_p2.y); + + return temp.getX(y, y0, y1); } //============================================================================= -TPointD TCubic::getPoint(double t) const -{ - double s = 1 - t; - return m_p0 * s * s * s + 3 * t * s * (s * m_p1 + t * m_p2) + t * t * t * m_p3; +TPointD TCubic::getPoint(double t) const { + double s = 1 - t; + return m_p0 * s * s * s + 3 * t * s * (s * m_p1 + t * m_p2) + + t * t * t * m_p3; } //----------------------------------------------------------------------------- -TPointD TCubic::getSpeed(double t) const -{ - double s = 1 - t; - return 3.0 * ((m_p1 - m_p0) * s * s + 2 * (m_p2 - m_p0) * s * t + (m_p3 - m_p2) * t * t); +TPointD TCubic::getSpeed(double t) const { + double s = 1 - t; + return 3.0 * ((m_p1 - m_p0) * s * s + 2 * (m_p2 - m_p0) * s * t + + (m_p3 - m_p2) * t * t); } //============================================================================= TThickQuadratic::TThickQuadratic() - : TQuadratic(), m_thickP0(0), m_thickP1(0), m_thickP2(0) -{ -} + : TQuadratic(), m_thickP0(0), m_thickP1(0), m_thickP2(0) {} //----------------------------------------------------------------------------- TThickQuadratic::TThickQuadratic(const TQuadratic &q) - : TQuadratic(q), m_thickP0(0.0), m_thickP1(0.0), m_thickP2(0.0) -{ -} + : TQuadratic(q), m_thickP0(0.0), m_thickP1(0.0), m_thickP2(0.0) {} //----------------------------------------------------------------------------- TThickQuadratic::TThickQuadratic(const TPointD &p0, double thickP0, - const TPointD &p1, double thickP1, - const TPointD &p2, double thickP2) - : TQuadratic(p0, p1, p2), m_thickP0(thickP0), m_thickP1(thickP1), m_thickP2(thickP2) -{ -} + const TPointD &p1, double thickP1, + const TPointD &p2, double thickP2) + : TQuadratic(p0, p1, p2) + , m_thickP0(thickP0) + , m_thickP1(thickP1) + , m_thickP2(thickP2) {} //----------------------------------------------------------------------------- -TThickQuadratic::TThickQuadratic(const TThickPoint &p0, - const TThickPoint &p1, - const TThickPoint &p2) - : TQuadratic(TPointD(p0.x, p0.y), TPointD(p1.x, p1.y), TPointD(p2.x, p2.y)), m_thickP0(p0.thick), m_thickP1(p1.thick), m_thickP2(p2.thick) -{ -} +TThickQuadratic::TThickQuadratic(const TThickPoint &p0, const TThickPoint &p1, + const TThickPoint &p2) + : TQuadratic(TPointD(p0.x, p0.y), TPointD(p1.x, p1.y), TPointD(p2.x, p2.y)) + , m_thickP0(p0.thick) + , m_thickP1(p1.thick) + , m_thickP2(p2.thick) {} //----------------------------------------------------------------------------- TThickQuadratic::TThickQuadratic(const TThickQuadratic &thickQuadratic) - : TQuadratic(thickQuadratic), m_thickP0(thickQuadratic.m_thickP0), m_thickP1(thickQuadratic.m_thickP1), m_thickP2(thickQuadratic.m_thickP2) -{ -} + : TQuadratic(thickQuadratic) + , m_thickP0(thickQuadratic.m_thickP0) + , m_thickP1(thickQuadratic.m_thickP1) + , m_thickP2(thickQuadratic.m_thickP2) {} //----------------------------------------------------------------------------- -void TThickQuadratic::setThickP0(const TThickPoint &p) -{ - m_p0 = p; - m_thickP0 = p.thick; +void TThickQuadratic::setThickP0(const TThickPoint &p) { + m_p0 = p; + m_thickP0 = p.thick; } //----------------------------------------------------------------------------- -void TThickQuadratic::setThickP1(const TThickPoint &p) -{ - m_p1 = p; - m_thickP1 = p.thick; +void TThickQuadratic::setThickP1(const TThickPoint &p) { + m_p1 = p; + m_thickP1 = p.thick; } //----------------------------------------------------------------------------- -void TThickQuadratic::setThickP2(const TThickPoint &p) -{ - m_p2 = p; - m_thickP2 = p.thick; +void TThickQuadratic::setThickP2(const TThickPoint &p) { + m_p2 = p; + m_thickP2 = p.thick; } //----------------------------------------------------------------------------- -TThickPoint TThickQuadratic::getThickPoint(double t) const -{ - double s = 1 - t; - return TThickPoint(m_p0 * s * s + 2 * t * s * m_p1 + t * t * m_p2, m_thickP0 * s * s + 2 * t * s * m_thickP1 + t * t * m_thickP2); +TThickPoint TThickQuadratic::getThickPoint(double t) const { + double s = 1 - t; + return TThickPoint( + m_p0 * s * s + 2 * t * s * m_p1 + t * t * m_p2, + m_thickP0 * s * s + 2 * t * s * m_thickP1 + t * t * m_thickP2); } //----------------------------------------------------------------------------- -void TThickQuadratic::split(double t, TThickQuadratic &left, TThickQuadratic &right) const -{ - double dt; - TPointD p; - dt = 1.0 - t; +void TThickQuadratic::split(double t, TThickQuadratic &left, + TThickQuadratic &right) const { + double dt; + TPointD p; + dt = 1.0 - t; - // control points - left.m_p0 = m_p0; - right.m_p2 = m_p2; + // control points + left.m_p0 = m_p0; + right.m_p2 = m_p2; - left.m_p1 = dt * m_p0 + t * m_p1; - right.m_p1 = dt * m_p1 + t * m_p2; - p = dt * left.m_p1 + t * right.m_p1; + left.m_p1 = dt * m_p0 + t * m_p1; + right.m_p1 = dt * m_p1 + t * m_p2; + p = dt * left.m_p1 + t * right.m_p1; - left.m_p2 = right.m_p0 = p; + left.m_p2 = right.m_p0 = p; - // thick points - left.m_thickP0 = m_thickP0; - right.m_thickP2 = m_thickP2; + // thick points + left.m_thickP0 = m_thickP0; + right.m_thickP2 = m_thickP2; - left.m_thickP1 = dt * m_thickP0 + t * m_thickP1; - right.m_thickP1 = dt * m_thickP1 + t * m_thickP2; + left.m_thickP1 = dt * m_thickP0 + t * m_thickP1; + right.m_thickP1 = dt * m_thickP1 + t * m_thickP2; - // store thickness of intermediary point - p.x = dt * left.m_thickP1 + t * right.m_thickP1; + // store thickness of intermediary point + p.x = dt * left.m_thickP1 + t * right.m_thickP1; - left.m_thickP2 = right.m_thickP0 = p.x; + left.m_thickP2 = right.m_thickP0 = p.x; } //----------------------------------------------------------------------------- -TRectD TThickQuadratic::getBBox() const -{ +TRectD TThickQuadratic::getBBox() const { + TRectD bBox = TQuadratic::getBBox(); - TRectD bBox = TQuadratic::getBBox(); + double maxRadius = std::max({m_thickP0, m_thickP1, m_thickP2}); + if (maxRadius > 0) { + // bBox.enlarge(maxRadius) si comporta male nel caso bBox.isEmpty() + bBox.x0 -= maxRadius; + bBox.y0 -= maxRadius; - double maxRadius = std::max({m_thickP0, m_thickP1, m_thickP2}); - if (maxRadius > 0) { - // bBox.enlarge(maxRadius) si comporta male nel caso bBox.isEmpty() - bBox.x0 -= maxRadius; - bBox.y0 -= maxRadius; + bBox.x1 += maxRadius; + bBox.y1 += maxRadius; + } - bBox.x1 += maxRadius; - bBox.y1 += maxRadius; - } - - return bBox; + return bBox; } // ============================================================================ @@ -491,184 +457,174 @@ TRectD TThickQuadratic::getBBox() const // ============================================================================ TThickCubic::TThickCubic() - : TCubic(), m_thickP0(0), m_thickP1(0), m_thickP2(0), m_thickP3(0) -{ -} + : TCubic(), m_thickP0(0), m_thickP1(0), m_thickP2(0), m_thickP3(0) {} //----------------------------------------------------------------------------- -TThickCubic::TThickCubic(const TPointD &p0, double thickP0, - const TPointD &p1, double thickP1, - const TPointD &p2, double thickP2, - const TPointD &p3, double thickP3) - : TCubic(p0, p1, p2, p3), m_thickP0(thickP0), m_thickP1(thickP1), m_thickP2(thickP2), m_thickP3(thickP3) -{ -} +TThickCubic::TThickCubic(const TPointD &p0, double thickP0, const TPointD &p1, + double thickP1, const TPointD &p2, double thickP2, + const TPointD &p3, double thickP3) + : TCubic(p0, p1, p2, p3) + , m_thickP0(thickP0) + , m_thickP1(thickP1) + , m_thickP2(thickP2) + , m_thickP3(thickP3) {} //----------------------------------------------------------------------------- -TThickCubic::TThickCubic(const TThickPoint &p0, - const TThickPoint &p1, - const TThickPoint &p2, - const TThickPoint &p3) - : TCubic(TPointD(p0.x, p0.y), TPointD(p1.x, p1.y), TPointD(p2.x, p2.y), TPointD(p3.x, p3.y)), m_thickP0(p0.thick), m_thickP1(p1.thick), m_thickP2(p2.thick), m_thickP3(p3.thick) -{ -} +TThickCubic::TThickCubic(const TThickPoint &p0, const TThickPoint &p1, + const TThickPoint &p2, const TThickPoint &p3) + : TCubic(TPointD(p0.x, p0.y), TPointD(p1.x, p1.y), TPointD(p2.x, p2.y), + TPointD(p3.x, p3.y)) + , m_thickP0(p0.thick) + , m_thickP1(p1.thick) + , m_thickP2(p2.thick) + , m_thickP3(p3.thick) {} // tonino *************************************************************** -TThickCubic::TThickCubic(const T3DPointD &p0, - const T3DPointD &p1, - const T3DPointD &p2, - const T3DPointD &p3) - : TCubic(TPointD(p0.x, p0.y), TPointD(p1.x, p1.y), TPointD(p2.x, p2.y), TPointD(p3.x, p3.y)), m_thickP0(p0.z), m_thickP1(p1.z), m_thickP2(p2.z), m_thickP3(p3.z) -{ -} +TThickCubic::TThickCubic(const T3DPointD &p0, const T3DPointD &p1, + const T3DPointD &p2, const T3DPointD &p3) + : TCubic(TPointD(p0.x, p0.y), TPointD(p1.x, p1.y), TPointD(p2.x, p2.y), + TPointD(p3.x, p3.y)) + , m_thickP0(p0.z) + , m_thickP1(p1.z) + , m_thickP2(p2.z) + , m_thickP3(p3.z) {} // tonino *************************************************************** //----------------------------------------------------------------------------- TThickCubic::TThickCubic(const TThickCubic &thickCubic) - : TCubic(thickCubic), m_thickP0(thickCubic.m_thickP0), m_thickP1(thickCubic.m_thickP1), m_thickP2(thickCubic.m_thickP2), m_thickP3(thickCubic.m_thickP3) -{ -} + : TCubic(thickCubic) + , m_thickP0(thickCubic.m_thickP0) + , m_thickP1(thickCubic.m_thickP1) + , m_thickP2(thickCubic.m_thickP2) + , m_thickP3(thickCubic.m_thickP3) {} //----------------------------------------------------------------------------- -void TThickCubic::setThickP0(const TThickPoint &p) -{ - m_p0.x = p.x; - m_p0.y = p.y; - m_thickP0 = p.thick; +void TThickCubic::setThickP0(const TThickPoint &p) { + m_p0.x = p.x; + m_p0.y = p.y; + m_thickP0 = p.thick; } //----------------------------------------------------------------------------- -void TThickCubic::setThickP1(const TThickPoint &p) -{ - m_p1.x = p.x; - m_p1.y = p.y; - m_thickP1 = p.thick; +void TThickCubic::setThickP1(const TThickPoint &p) { + m_p1.x = p.x; + m_p1.y = p.y; + m_thickP1 = p.thick; } //----------------------------------------------------------------------------- -void TThickCubic::setThickP2(const TThickPoint &p) -{ - m_p2.x = p.x; - m_p2.y = p.y; - m_thickP2 = p.thick; +void TThickCubic::setThickP2(const TThickPoint &p) { + m_p2.x = p.x; + m_p2.y = p.y; + m_thickP2 = p.thick; } //----------------------------------------------------------------------------- -void TThickCubic::setThickP3(const TThickPoint &p) -{ - m_p3.x = p.x; - m_p3.y = p.y; - m_thickP3 = p.thick; +void TThickCubic::setThickP3(const TThickPoint &p) { + m_p3.x = p.x; + m_p3.y = p.y; + m_thickP3 = p.thick; } //----------------------------------------------------------------------------- -TThickPoint TThickCubic::getThickPoint(double t) const -{ - double - thick_l1, - thick_h, - thick_r3; +TThickPoint TThickCubic::getThickPoint(double t) const { + double thick_l1, thick_h, thick_r3; - double s = 1.0 - t; + double s = 1.0 - t; - TPointD l1(m_p0 * s + m_p1 * t); - thick_l1 = m_thickP0 * s + m_thickP1 * t; + TPointD l1(m_p0 * s + m_p1 * t); + thick_l1 = m_thickP0 * s + m_thickP1 * t; - TPointD h(m_p1 * s + m_p2 * t); - thick_h = m_thickP1 * s + m_thickP2 * t; + TPointD h(m_p1 * s + m_p2 * t); + thick_h = m_thickP1 * s + m_thickP2 * t; - TPointD r3(m_p2 * s + m_p3 * t); - thick_r3 = m_thickP2 * s + m_thickP3 * t; + TPointD r3(m_p2 * s + m_p3 * t); + thick_r3 = m_thickP2 * s + m_thickP3 * t; - // adesso riutilizzo le variabili gia' utilizzate + // adesso riutilizzo le variabili gia' utilizzate - // l2 - l1 = l1 * s + h * t; - thick_l1 = thick_l1 * s + thick_h * t; + // l2 + l1 = l1 * s + h * t; + thick_l1 = thick_l1 * s + thick_h * t; - // r1 - r3 = h * s + r3 * t; - thick_r3 = thick_h * s + thick_r3 * t; + // r1 + r3 = h * s + r3 * t; + thick_r3 = thick_h * s + thick_r3 * t; - // l3-r0 - h = l1 * s + r3 * t; - thick_h = thick_l1 * s + thick_r3 * t; + // l3-r0 + h = l1 * s + r3 * t; + thick_h = thick_l1 * s + thick_r3 * t; - return TThickPoint(h, thick_h); + return TThickPoint(h, thick_h); } //----------------------------------------------------------------------------- -void TThickCubic::split(double t, TThickCubic &first, TThickCubic &second) const -{ - double s = 1.0 - t; +void TThickCubic::split(double t, TThickCubic &first, + TThickCubic &second) const { + double s = 1.0 - t; - TPointD H(m_p1 * s + m_p2 * t); - double thick_h = m_thickP1 * s + m_thickP2 * t; + TPointD H(m_p1 * s + m_p2 * t); + double thick_h = m_thickP1 * s + m_thickP2 * t; - first.m_p0 = m_p0; - first.m_thickP0 = m_thickP0; + first.m_p0 = m_p0; + first.m_thickP0 = m_thickP0; - first.m_p1 = m_p0 * s + m_p1 * t; - first.m_thickP1 = m_thickP0 * s + m_thickP1 * t; + first.m_p1 = m_p0 * s + m_p1 * t; + first.m_thickP1 = m_thickP0 * s + m_thickP1 * t; - first.m_p2 = first.m_p1 * s + H * t; - first.m_thickP2 = first.m_thickP1 * s + thick_h * t; + first.m_p2 = first.m_p1 * s + H * t; + first.m_thickP2 = first.m_thickP1 * s + thick_h * t; - second.m_p3 = m_p3; - second.m_thickP3 = m_thickP3; + second.m_p3 = m_p3; + second.m_thickP3 = m_thickP3; - second.m_p2 = m_p2 * s + m_p3 * t; - second.m_thickP2 = m_thickP2 * s + m_thickP3 * t; + second.m_p2 = m_p2 * s + m_p3 * t; + second.m_thickP2 = m_thickP2 * s + m_thickP3 * t; - second.m_p1 = H * s + second.m_p2 * t; - second.m_thickP1 = thick_h * s + second.m_thickP2 * t; + second.m_p1 = H * s + second.m_p2 * t; + second.m_thickP1 = thick_h * s + second.m_thickP2 * t; - first.m_p3 = first.m_p2 * s + second.m_p1 * t; - first.m_thickP3 = first.m_thickP2 * s + second.m_thickP1 * t; + first.m_p3 = first.m_p2 * s + second.m_p1 * t; + first.m_thickP3 = first.m_thickP2 * s + second.m_thickP1 * t; - second.m_p0 = first.m_p3; - second.m_thickP0 = first.m_thickP3; + second.m_p0 = first.m_p3; + second.m_thickP0 = first.m_thickP3; } //----------------------------------------------------------------------------- -ostream &operator<<(ostream &out, const TQuadratic &curve) -{ - return out << "Q{" << curve.getP0() << ", " << curve.getP1() << ", " - << curve.getP2() << "}"; +ostream &operator<<(ostream &out, const TQuadratic &curve) { + return out << "Q{" << curve.getP0() << ", " << curve.getP1() << ", " + << curve.getP2() << "}"; } -ostream &operator<<(ostream &out, const TCubic &curve) -{ - return out << "C{" << curve.getP0() << ", " << curve.getP1() << ", " - << curve.getP2() << ", " << curve.getP3() << "}"; +ostream &operator<<(ostream &out, const TCubic &curve) { + return out << "C{" << curve.getP0() << ", " << curve.getP1() << ", " + << curve.getP2() << ", " << curve.getP3() << "}"; } -ostream &operator<<(ostream &out, const TThickSegment &segment) -{ - return out << "TS{" << segment.getThickP0() << ", " << segment.getThickP1() << "}"; +ostream &operator<<(ostream &out, const TThickSegment &segment) { + return out << "TS{" << segment.getThickP0() << ", " << segment.getThickP1() + << "}"; } -ostream &operator<<(ostream &out, const TThickQuadratic &tq) -{ - return out << "TQ{" << tq.getThickP0() << ", " << tq.getThickP1() << ", " << tq.getThickP2() << "}"; +ostream &operator<<(ostream &out, const TThickQuadratic &tq) { + return out << "TQ{" << tq.getThickP0() << ", " << tq.getThickP1() << ", " + << tq.getThickP2() << "}"; } -ostream &operator<<(ostream &out, const TThickCubic &tc) -{ - return out << "TC{" << tc.getThickP0() << ", " - << tc.getThickP1() << ", " - << tc.getThickP2() << ", " - << tc.getThickP3() << "}"; +ostream &operator<<(ostream &out, const TThickCubic &tc) { + return out << "TC{" << tc.getThickP0() << ", " << tc.getThickP1() << ", " + << tc.getThickP2() << ", " << tc.getThickP3() << "}"; } //----------------------------------------------------------------------------- diff --git a/toonz/sources/common/tgeometry/tcurveutil.cpp b/toonz/sources/common/tgeometry/tcurveutil.cpp index 7a1fcd7..bc0807e 100644 --- a/toonz/sources/common/tgeometry/tcurveutil.cpp +++ b/toonz/sources/common/tgeometry/tcurveutil.cpp @@ -9,482 +9,463 @@ /* Questa funzione ritorna un vettore di -coppie di double (DoublePair) che individua i parametri +coppie di double (DoublePair) che individua i parametri dei punti d'intersezione. - L'intero restituito indica il numero d'intersezioni che + L'intero restituito indica il numero d'intersezioni che sono state individuate (per due segmenti una). - + Se i segmenti sono paralleli il parametro viene posto a -1. */ -int intersect(const TSegment &first, - const TSegment &second, - std::vector &intersections) -{ - return intersect(first.getP0(), first.getP1(), second.getP0(), second.getP1(), intersections); +int intersect(const TSegment &first, const TSegment &second, + std::vector &intersections) { + return intersect(first.getP0(), first.getP1(), second.getP0(), second.getP1(), + intersections); } -int intersect(const TPointD &p1, const TPointD &p2, const TPointD &p3, const TPointD &p4, - std::vector &intersections) -{ - // This algorithm is presented in Graphics Geems III pag 199 - - static double Ax, Bx, Ay, By, Cx, Cy, d, f, e; - static double x1lo, x1hi, y1lo, y1hi; - - Ax = p2.x - p1.x; - Bx = p3.x - p4.x; - - //test delle BBox - if (Ax < 0.0) { - x1lo = p2.x; - x1hi = p1.x; - } else { - x1lo = p1.x; - x1hi = p2.x; - } - - if (Bx > 0.0) { - if (x1hi < p4.x || x1lo > p3.x) - return 0; - } else if (x1hi < p3.x || x1lo > p4.x) - return 0; - - Ay = p2.y - p1.y; - By = p3.y - p4.y; - - if (Ay < 0) { - y1lo = p2.y; - y1hi = p1.y; - } else { - y1lo = p1.y; - y1hi = p2.y; - } - - if (By > 0) { - if (y1hi < p4.y || y1lo > p3.y) - return 0; - } else if (y1hi < p3.y || y1lo > p4.y) - return 0; - - Cx = p1.x - p3.x; - Cy = p1.y - p3.y; - - d = By * Cx - Bx * Cy; - f = Ay * Bx - Ax * By; - e = Ax * Cy - Ay * Cx; - - if (f > 0) { - if (d < 0) - return 0; - - if (!areAlmostEqual(d, f)) - if (d > f) - return 0; - - if (e < 0) - return 0; - if (!areAlmostEqual(e, f)) - if (e > f) - return 0; - } else if (f < 0) { - if (d > 0) - return 0; - - if (!areAlmostEqual(d, f)) - if (d < f) - return 0; - - if (e > 0) - return 0; - if (!areAlmostEqual(e, f)) - if (e < f) - return 0; - } else { - if (d < 0 || d > 1 || e < 0 || e > 1) - return 0; - - if (p1 == p2 && p3 == p4) { - intersections.push_back(DoublePair(0, 0)); - return 1; - } - - // controllo che i segmenti non siano sulla stessa retta - if (!cross(p2 - p1, p4 - p1)) { - // calcolo delle combinazioni baricentriche - double distp2p1 = norm2(p2 - p1); - double distp3p4 = norm2(p3 - p4); - - double dist2_p3p1 = norm2(p3 - p1); - double dist2_p4p1 = norm2(p4 - p1); - double dist2_p3p2 = norm2(p3 - p2); - double dist2_p4p2 = norm2(p4 - p2); - - int intersection = 0; - - // calcolo delle prime due soluzioni - double vol1; - - if (distp3p4) { - distp3p4 = sqrt(distp3p4); - - vol1 = (p1 - p3) * normalize(p4 - p3); - - if (vol1 >= 0 && vol1 <= distp3p4) // combinazione baricentrica valida - { - intersections.push_back(DoublePair(0.0, vol1 / distp3p4)); - ++intersection; - } - - vol1 = (p2 - p3) * normalize(p4 - p3); - - if (vol1 >= 0 && vol1 <= distp3p4) { - intersections.push_back(DoublePair(1.0, vol1 / distp3p4)); - ++intersection; - } - } - - if (distp2p1) { - distp2p1 = sqrt(distp2p1); - - vol1 = (p3 - p1) * normalize(p2 - p1); - - if (dist2_p3p2 && dist2_p3p1) - if (vol1 >= 0 && vol1 <= distp2p1) { - intersections.push_back(DoublePair(vol1 / distp2p1, 0.0)); - ++intersection; - } - - vol1 = (p4 - p1) * normalize(p2 - p1); - - if (dist2_p4p2 && dist2_p4p1) - if (vol1 >= 0 && vol1 <= distp2p1) { - intersections.push_back(DoublePair(vol1 / distp2p1, 1.0)); - ++intersection; - } - } - return intersection; - } - return -1; - } - - double par_s = d / f; - double par_t = e / f; - - intersections.push_back(DoublePair(par_s, par_t)); - return 1; +int intersect(const TPointD &p1, const TPointD &p2, const TPointD &p3, + const TPointD &p4, std::vector &intersections) { + // This algorithm is presented in Graphics Geems III pag 199 + + static double Ax, Bx, Ay, By, Cx, Cy, d, f, e; + static double x1lo, x1hi, y1lo, y1hi; + + Ax = p2.x - p1.x; + Bx = p3.x - p4.x; + + // test delle BBox + if (Ax < 0.0) { + x1lo = p2.x; + x1hi = p1.x; + } else { + x1lo = p1.x; + x1hi = p2.x; + } + + if (Bx > 0.0) { + if (x1hi < p4.x || x1lo > p3.x) return 0; + } else if (x1hi < p3.x || x1lo > p4.x) + return 0; + + Ay = p2.y - p1.y; + By = p3.y - p4.y; + + if (Ay < 0) { + y1lo = p2.y; + y1hi = p1.y; + } else { + y1lo = p1.y; + y1hi = p2.y; + } + + if (By > 0) { + if (y1hi < p4.y || y1lo > p3.y) return 0; + } else if (y1hi < p3.y || y1lo > p4.y) + return 0; + + Cx = p1.x - p3.x; + Cy = p1.y - p3.y; + + d = By * Cx - Bx * Cy; + f = Ay * Bx - Ax * By; + e = Ax * Cy - Ay * Cx; + + if (f > 0) { + if (d < 0) return 0; + + if (!areAlmostEqual(d, f)) + if (d > f) return 0; + + if (e < 0) return 0; + if (!areAlmostEqual(e, f)) + if (e > f) return 0; + } else if (f < 0) { + if (d > 0) return 0; + + if (!areAlmostEqual(d, f)) + if (d < f) return 0; + + if (e > 0) return 0; + if (!areAlmostEqual(e, f)) + if (e < f) return 0; + } else { + if (d < 0 || d > 1 || e < 0 || e > 1) return 0; + + if (p1 == p2 && p3 == p4) { + intersections.push_back(DoublePair(0, 0)); + return 1; + } + + // controllo che i segmenti non siano sulla stessa retta + if (!cross(p2 - p1, p4 - p1)) { + // calcolo delle combinazioni baricentriche + double distp2p1 = norm2(p2 - p1); + double distp3p4 = norm2(p3 - p4); + + double dist2_p3p1 = norm2(p3 - p1); + double dist2_p4p1 = norm2(p4 - p1); + double dist2_p3p2 = norm2(p3 - p2); + double dist2_p4p2 = norm2(p4 - p2); + + int intersection = 0; + + // calcolo delle prime due soluzioni + double vol1; + + if (distp3p4) { + distp3p4 = sqrt(distp3p4); + + vol1 = (p1 - p3) * normalize(p4 - p3); + + if (vol1 >= 0 && vol1 <= distp3p4) // combinazione baricentrica valida + { + intersections.push_back(DoublePair(0.0, vol1 / distp3p4)); + ++intersection; + } + + vol1 = (p2 - p3) * normalize(p4 - p3); + + if (vol1 >= 0 && vol1 <= distp3p4) { + intersections.push_back(DoublePair(1.0, vol1 / distp3p4)); + ++intersection; + } + } + + if (distp2p1) { + distp2p1 = sqrt(distp2p1); + + vol1 = (p3 - p1) * normalize(p2 - p1); + + if (dist2_p3p2 && dist2_p3p1) + if (vol1 >= 0 && vol1 <= distp2p1) { + intersections.push_back(DoublePair(vol1 / distp2p1, 0.0)); + ++intersection; + } + + vol1 = (p4 - p1) * normalize(p2 - p1); + + if (dist2_p4p2 && dist2_p4p1) + if (vol1 >= 0 && vol1 <= distp2p1) { + intersections.push_back(DoublePair(vol1 / distp2p1, 1.0)); + ++intersection; + } + } + return intersection; + } + return -1; + } + + double par_s = d / f; + double par_t = e / f; + + intersections.push_back(DoublePair(par_s, par_t)); + return 1; } //------------------------------------------------------------------------------------------------------------ -int intersectCloseControlPoints(const TQuadratic &c0, - const TQuadratic &c1, - std::vector &intersections); +int intersectCloseControlPoints(const TQuadratic &c0, const TQuadratic &c1, + std::vector &intersections); -int intersect(const TQuadratic &c0, - const TQuadratic &c1, - std::vector &intersections, bool checksegments) -{ - int ret; - - // funziona male, a volte toppa le intersezioni... - if (checksegments) { - ret = intersectCloseControlPoints(c0, c1, intersections); - if (ret != -2) - return ret; - } - - double a = c0.getP0().x - 2 * c0.getP1().x + c0.getP2().x; - double b = 2 * (c0.getP1().x - c0.getP0().x); - double d = c0.getP0().y - 2 * c0.getP1().y + c0.getP2().y; - double e = 2 * (c0.getP1().y - c0.getP0().y); - - double coeff = b * d - a * e; - int i = 0; - - if (areAlmostEqual(coeff, 0.0)) //c0 is a Segment, or a single point!!! - { - - TSegment s = TSegment(c0.getP0(), c0.getP2()); - ret = intersect(s, c1, intersections); - if (a == 0 && d == 0) //values of t in s coincide with values of t in c0 - return ret; - - for (i = intersections.size() - ret; i < (int)intersections.size(); i++) { - intersections[i].first = c0.getT(s.getPoint(intersections[i].first)); - } - return ret; - } - - double c = c0.getP0().x; - double f = c0.getP0().y; - - double g = c1.getP0().x - 2 * c1.getP1().x + c1.getP2().x; - double h = 2 * (c1.getP1().x - c1.getP0().x); - double k = c1.getP0().x; - - double m = c1.getP0().y - 2 * c1.getP1().y + c1.getP2().y; - double p = 2 * (c1.getP1().y - c1.getP0().y); - double q = c1.getP0().y; - - if (areAlmostEqual(h * m - g * p, 0.0)) //c1 is a Segment, or a single point!!! - { - TSegment s = TSegment(c1.getP0(), c1.getP2()); - ret = intersect(c0, s, intersections); - if (g == 0 && m == 0) //values of t in s coincide with values of t in c0 - return ret; - - for (i = intersections.size() - ret; i < (int)intersections.size(); i++) { - intersections[i].second = c1.getT(s.getPoint(intersections[i].second)); - } - return ret; - } - - double a2 = (g * d - a * m); - double b2 = (h * d - a * p); - double c2 = ((k - c) * d + (f - q) * a); - - coeff = 1.0 / coeff; - - double A = (a * a + d * d) * coeff * coeff; - double aux = A * c2 + (a * b + d * e) * coeff; - - std::vector t; - std::vector solutions; - - t.push_back(aux * c2 + a * c + d * f - k * a - d * q); - aux += A * c2; - t.push_back(aux * b2 - h * a - d * p); - t.push_back(aux * a2 + A * b2 * b2 - g * a - d * m); - t.push_back(2 * A * a2 * b2); - t.push_back(A * a2 * a2); - - rootFinding(t, solutions); - // solutions.push_back(0.0); //per convenzione; un valore vale l'altro.... - - for (i = 0; i < (int)solutions.size(); i++) { - if (solutions[i] < 0) { - if (areAlmostEqual(solutions[i], 0, 1e-6)) - solutions[i] = 0; - else - continue; - } else if (solutions[i] > 1) { - if (areAlmostEqual(solutions[i], 1, 1e-6)) - solutions[i] = 1; - else - continue; - } - - DoublePair tt; - tt.second = solutions[i]; - tt.first = coeff * (tt.second * (a2 * tt.second + b2) + c2); - if (tt.first < 0) { - if (areAlmostEqual(tt.first, 0, 1e-6)) - tt.first = 0; - else - continue; - } else if (tt.first > 1) { - if (areAlmostEqual(tt.first, 1, 1e-6)) - tt.first = 1; - else - continue; - } - - intersections.push_back(tt); - - assert(areAlmostEqual(c0.getPoint(tt.first), c1.getPoint(tt.second), 1e-1)); - } - return intersections.size(); +int intersect(const TQuadratic &c0, const TQuadratic &c1, + std::vector &intersections, bool checksegments) { + int ret; + + // funziona male, a volte toppa le intersezioni... + if (checksegments) { + ret = intersectCloseControlPoints(c0, c1, intersections); + if (ret != -2) return ret; + } + + double a = c0.getP0().x - 2 * c0.getP1().x + c0.getP2().x; + double b = 2 * (c0.getP1().x - c0.getP0().x); + double d = c0.getP0().y - 2 * c0.getP1().y + c0.getP2().y; + double e = 2 * (c0.getP1().y - c0.getP0().y); + + double coeff = b * d - a * e; + int i = 0; + + if (areAlmostEqual(coeff, 0.0)) // c0 is a Segment, or a single point!!! + { + TSegment s = TSegment(c0.getP0(), c0.getP2()); + ret = intersect(s, c1, intersections); + if (a == 0 && d == 0) // values of t in s coincide with values of t in c0 + return ret; + + for (i = intersections.size() - ret; i < (int)intersections.size(); i++) { + intersections[i].first = c0.getT(s.getPoint(intersections[i].first)); + } + return ret; + } + + double c = c0.getP0().x; + double f = c0.getP0().y; + + double g = c1.getP0().x - 2 * c1.getP1().x + c1.getP2().x; + double h = 2 * (c1.getP1().x - c1.getP0().x); + double k = c1.getP0().x; + + double m = c1.getP0().y - 2 * c1.getP1().y + c1.getP2().y; + double p = 2 * (c1.getP1().y - c1.getP0().y); + double q = c1.getP0().y; + + if (areAlmostEqual(h * m - g * p, + 0.0)) // c1 is a Segment, or a single point!!! + { + TSegment s = TSegment(c1.getP0(), c1.getP2()); + ret = intersect(c0, s, intersections); + if (g == 0 && m == 0) // values of t in s coincide with values of t in c0 + return ret; + + for (i = intersections.size() - ret; i < (int)intersections.size(); i++) { + intersections[i].second = c1.getT(s.getPoint(intersections[i].second)); + } + return ret; + } + + double a2 = (g * d - a * m); + double b2 = (h * d - a * p); + double c2 = ((k - c) * d + (f - q) * a); + + coeff = 1.0 / coeff; + + double A = (a * a + d * d) * coeff * coeff; + double aux = A * c2 + (a * b + d * e) * coeff; + + std::vector t; + std::vector solutions; + + t.push_back(aux * c2 + a * c + d * f - k * a - d * q); + aux += A * c2; + t.push_back(aux * b2 - h * a - d * p); + t.push_back(aux * a2 + A * b2 * b2 - g * a - d * m); + t.push_back(2 * A * a2 * b2); + t.push_back(A * a2 * a2); + + rootFinding(t, solutions); + // solutions.push_back(0.0); //per convenzione; un valore vale l'altro.... + + for (i = 0; i < (int)solutions.size(); i++) { + if (solutions[i] < 0) { + if (areAlmostEqual(solutions[i], 0, 1e-6)) + solutions[i] = 0; + else + continue; + } else if (solutions[i] > 1) { + if (areAlmostEqual(solutions[i], 1, 1e-6)) + solutions[i] = 1; + else + continue; + } + + DoublePair tt; + tt.second = solutions[i]; + tt.first = coeff * (tt.second * (a2 * tt.second + b2) + c2); + if (tt.first < 0) { + if (areAlmostEqual(tt.first, 0, 1e-6)) + tt.first = 0; + else + continue; + } else if (tt.first > 1) { + if (areAlmostEqual(tt.first, 1, 1e-6)) + tt.first = 1; + else + continue; + } + + intersections.push_back(tt); + + assert(areAlmostEqual(c0.getPoint(tt.first), c1.getPoint(tt.second), 1e-1)); + } + return intersections.size(); } //============================================================================= -//questa funzione verifica se il punto di controllo p1 e' molto vicino a p0 o a p2: -//in tal caso, si approssima la quadratica al segmento p0-p2. -//se p1 e' vicino a p0, la relazione che lega il t del segmento al t della quadratica originaria e' tq = sqrt(ts), -//se p1 e' vicino a p2, invece e' tq = 1-sqrt(1-ts). - -int intersectCloseControlPoints(const TQuadratic &c0, - const TQuadratic &c1, - std::vector &intersections) -{ - int ret = -2; - - double dist1 = tdistance2(c0.getP0(), c0.getP1()); - if (dist1 == 0) - dist1 = 1e-20; - double dist2 = tdistance2(c0.getP1(), c0.getP2()); - if (dist2 == 0) - dist2 = 1e-20; - double val0 = std::max(dist1, dist2) / std::min(dist1, dist2); - double dist3 = tdistance2(c1.getP0(), c1.getP1()); - if (dist3 == 0) - dist3 = 1e-20; - double dist4 = tdistance2(c1.getP1(), c1.getP2()); - if (dist4 == 0) - dist4 = 1e-20; - double val1 = std::max(dist3, dist4) / std::min(dist3, dist4); - - if (val0 > 1000000 && val1 > 1000000) //entrambe c0 e c1 approssimate a segmenti - { - TSegment s0 = TSegment(c0.getP0(), c0.getP2()); - TSegment s1 = TSegment(c1.getP0(), c1.getP2()); - ret = intersect(s0, s1, intersections); - for (UINT i = intersections.size() - ret; i < (int)intersections.size(); i++) { - intersections[i].first = (dist1 < dist2) ? sqrt(intersections[i].first) : 1 - sqrt(1 - intersections[i].first); - intersections[i].second = (dist3 < dist4) ? sqrt(intersections[i].second) : 1 - sqrt(1 - intersections[i].second); - } - //return ret; - } else if (val0 > 1000000) //solo c0 approssimata a segmento - { - TSegment s0 = TSegment(c0.getP0(), c0.getP2()); - ret = intersect(s0, c1, intersections); - for (UINT i = intersections.size() - ret; i < (int)intersections.size(); i++) - intersections[i].first = (dist1 < dist2) ? sqrt(intersections[i].first) : 1 - sqrt(1 - intersections[i].first); - //return ret; - } else if (val1 > 1000000) //solo c1 approssimata a segmento - { - TSegment s1 = TSegment(c1.getP0(), c1.getP2()); - ret = intersect(c0, s1, intersections); - for (UINT i = intersections.size() - ret; i < (int)intersections.size(); i++) - intersections[i].second = (dist3 < dist4) ? sqrt(intersections[i].second) : 1 - sqrt(1 - intersections[i].second); - //return ret; - } - - /* -if (ret!=-2) +// questa funzione verifica se il punto di controllo p1 e' molto vicino a p0 o a +// p2: +// in tal caso, si approssima la quadratica al segmento p0-p2. +// se p1 e' vicino a p0, la relazione che lega il t del segmento al t della +// quadratica originaria e' tq = sqrt(ts), +// se p1 e' vicino a p2, invece e' tq = 1-sqrt(1-ts). + +int intersectCloseControlPoints(const TQuadratic &c0, const TQuadratic &c1, + std::vector &intersections) { + int ret = -2; + + double dist1 = tdistance2(c0.getP0(), c0.getP1()); + if (dist1 == 0) dist1 = 1e-20; + double dist2 = tdistance2(c0.getP1(), c0.getP2()); + if (dist2 == 0) dist2 = 1e-20; + double val0 = std::max(dist1, dist2) / std::min(dist1, dist2); + double dist3 = tdistance2(c1.getP0(), c1.getP1()); + if (dist3 == 0) dist3 = 1e-20; + double dist4 = tdistance2(c1.getP1(), c1.getP2()); + if (dist4 == 0) dist4 = 1e-20; + double val1 = std::max(dist3, dist4) / std::min(dist3, dist4); + + if (val0 > 1000000 && + val1 > 1000000) // entrambe c0 e c1 approssimate a segmenti { - std::vector intersections1; - int ret1 = intersect(c0, c1, intersections1, false); - if (ret1>ret) - { - intersections = intersections1; - return ret1; + TSegment s0 = TSegment(c0.getP0(), c0.getP2()); + TSegment s1 = TSegment(c1.getP0(), c1.getP2()); + ret = intersect(s0, s1, intersections); + for (UINT i = intersections.size() - ret; i < (int)intersections.size(); + i++) { + intersections[i].first = (dist1 < dist2) + ? sqrt(intersections[i].first) + : 1 - sqrt(1 - intersections[i].first); + intersections[i].second = (dist3 < dist4) + ? sqrt(intersections[i].second) + : 1 - sqrt(1 - intersections[i].second); } + // return ret; + } else if (val0 > 1000000) // solo c0 approssimata a segmento + { + TSegment s0 = TSegment(c0.getP0(), c0.getP2()); + ret = intersect(s0, c1, intersections); + for (UINT i = intersections.size() - ret; i < (int)intersections.size(); + i++) + intersections[i].first = (dist1 < dist2) + ? sqrt(intersections[i].first) + : 1 - sqrt(1 - intersections[i].first); + // return ret; + } else if (val1 > 1000000) // solo c1 approssimata a segmento + { + TSegment s1 = TSegment(c1.getP0(), c1.getP2()); + ret = intersect(c0, s1, intersections); + for (UINT i = intersections.size() - ret; i < (int)intersections.size(); + i++) + intersections[i].second = (dist3 < dist4) + ? sqrt(intersections[i].second) + : 1 - sqrt(1 - intersections[i].second); + // return ret; } + + /* +if (ret!=-2) +{ +std::vector intersections1; +int ret1 = intersect(c0, c1, intersections1, false); +if (ret1>ret) +{ +intersections = intersections1; +return ret1; +} +} */ - return ret; + return ret; } //============================================================================= -int intersect(const TQuadratic &q, - const TSegment &s, - std::vector &intersections, - bool firstIsQuad) -{ - int solutionNumber = 0; - - // nota la retta a*x+b*y+c = 0 andiamo alla ricerca delle soluzioni - // di a*x(t)+b*y(t)+c=0 in [0,1] - double - a = s.getP0().y - s.getP1().y, - b = s.getP1().x - s.getP0().x, - c = -(a * s.getP0().x + b * s.getP0().y); - - // se il segmento e' un punto - if (0.0 == a && 0.0 == b) { - double outParForQuad = q.getT(s.getP0()); - - if (areAlmostEqual(q.getPoint(outParForQuad), s.getP0())) { - if (firstIsQuad) - intersections.push_back(DoublePair(outParForQuad, 0)); - else - intersections.push_back(DoublePair(0, outParForQuad)); - return 1; - } - return 0; - } - - if (q.getP2() - q.getP1() == q.getP1() - q.getP0()) {//pure il secondo e' unsegmento.... - if (firstIsQuad) - return intersect(TSegment(q.getP0(), q.getP2()), s, intersections); - else - return intersect(s, TSegment(q.getP0(), q.getP2()), intersections); - } - - std::vector bez, pol; - bez.push_back(q.getP0()); - bez.push_back(q.getP1()); - bez.push_back(q.getP2()); - - bezier2poly(bez, pol); - - std::vector poly_1(3, 0), sol; - - poly_1[0] = a * pol[0].x + b * pol[0].y + c; - poly_1[1] = a * pol[1].x + b * pol[1].y; - poly_1[2] = a * pol[2].x + b * pol[2].y; - - if (!(rootFinding(poly_1, sol))) - return 0; - - double - segmentPar, - solution; - - TPointD v10(s.getP1() - s.getP0()); - for (UINT i = 0; i < sol.size(); ++i) { - solution = sol[i]; - if ((0.0 <= solution && solution <= 1.0) || - areAlmostEqual(solution, 0.0, 1e-6) || - areAlmostEqual(solution, 1.0, 1e-6)) { - segmentPar = (q.getPoint(solution) - s.getP0()) * v10 / (v10 * v10); - if ((0.0 <= segmentPar && segmentPar <= 1.0) || - areAlmostEqual(segmentPar, 0.0, 1e-6) || - areAlmostEqual(segmentPar, 1.0, 1e-6)) { - TPointD p1 = q.getPoint(solution); - TPointD p2 = s.getPoint(segmentPar); - assert(areAlmostEqual(p1, p2, 1e-1)); - - if (firstIsQuad) - intersections.push_back(DoublePair(solution, segmentPar)); - else - intersections.push_back(DoublePair(segmentPar, solution)); - solutionNumber++; - } - } - } - - return solutionNumber; +int intersect(const TQuadratic &q, const TSegment &s, + std::vector &intersections, bool firstIsQuad) { + int solutionNumber = 0; + + // nota la retta a*x+b*y+c = 0 andiamo alla ricerca delle soluzioni + // di a*x(t)+b*y(t)+c=0 in [0,1] + double a = s.getP0().y - s.getP1().y, b = s.getP1().x - s.getP0().x, + c = -(a * s.getP0().x + b * s.getP0().y); + + // se il segmento e' un punto + if (0.0 == a && 0.0 == b) { + double outParForQuad = q.getT(s.getP0()); + + if (areAlmostEqual(q.getPoint(outParForQuad), s.getP0())) { + if (firstIsQuad) + intersections.push_back(DoublePair(outParForQuad, 0)); + else + intersections.push_back(DoublePair(0, outParForQuad)); + return 1; + } + return 0; + } + + if (q.getP2() - q.getP1() == + q.getP1() - q.getP0()) { // pure il secondo e' unsegmento.... + if (firstIsQuad) + return intersect(TSegment(q.getP0(), q.getP2()), s, intersections); + else + return intersect(s, TSegment(q.getP0(), q.getP2()), intersections); + } + + std::vector bez, pol; + bez.push_back(q.getP0()); + bez.push_back(q.getP1()); + bez.push_back(q.getP2()); + + bezier2poly(bez, pol); + + std::vector poly_1(3, 0), sol; + + poly_1[0] = a * pol[0].x + b * pol[0].y + c; + poly_1[1] = a * pol[1].x + b * pol[1].y; + poly_1[2] = a * pol[2].x + b * pol[2].y; + + if (!(rootFinding(poly_1, sol))) return 0; + + double segmentPar, solution; + + TPointD v10(s.getP1() - s.getP0()); + for (UINT i = 0; i < sol.size(); ++i) { + solution = sol[i]; + if ((0.0 <= solution && solution <= 1.0) || + areAlmostEqual(solution, 0.0, 1e-6) || + areAlmostEqual(solution, 1.0, 1e-6)) { + segmentPar = (q.getPoint(solution) - s.getP0()) * v10 / (v10 * v10); + if ((0.0 <= segmentPar && segmentPar <= 1.0) || + areAlmostEqual(segmentPar, 0.0, 1e-6) || + areAlmostEqual(segmentPar, 1.0, 1e-6)) { + TPointD p1 = q.getPoint(solution); + TPointD p2 = s.getPoint(segmentPar); + assert(areAlmostEqual(p1, p2, 1e-1)); + + if (firstIsQuad) + intersections.push_back(DoublePair(solution, segmentPar)); + else + intersections.push_back(DoublePair(segmentPar, solution)); + solutionNumber++; + } + } + } + + return solutionNumber; } //============================================================================= -bool isCloseToSegment(const TPointD &point, const TSegment &segment, double distance) -{ - TPointD a = segment.getP0(); - TPointD b = segment.getP1(); - double lenght2 = tdistance2(a, b); - if (lenght2 < tdistance2(a, point) || lenght2 < tdistance2(point, b)) - return false; - if (a.x == b.x) - return fabs(point.x - a.x) <= distance; - if (a.y == b.y) - return fabs(point.y - a.y) <= distance; - - // y=mx+q - double m = (a.y - b.y) / (a.x - b.x); - double q = a.y - (m * a.x); - - double d2 = pow(fabs(point.y - (m * point.x) - q), 2) / (1 + (m * m)); - return d2 <= distance * distance; +bool isCloseToSegment(const TPointD &point, const TSegment &segment, + double distance) { + TPointD a = segment.getP0(); + TPointD b = segment.getP1(); + double lenght2 = tdistance2(a, b); + if (lenght2 < tdistance2(a, point) || lenght2 < tdistance2(point, b)) + return false; + if (a.x == b.x) return fabs(point.x - a.x) <= distance; + if (a.y == b.y) return fabs(point.y - a.y) <= distance; + + // y=mx+q + double m = (a.y - b.y) / (a.x - b.x); + double q = a.y - (m * a.x); + + double d2 = pow(fabs(point.y - (m * point.x) - q), 2) / (1 + (m * m)); + return d2 <= distance * distance; } //============================================================================= -double tdistance(const TSegment &segment, const TPointD &point) -{ - TPointD v1 = segment.getP1() - segment.getP0(); - TPointD v2 = point - segment.getP0(); - TPointD v3 = point - segment.getP1(); +double tdistance(const TSegment &segment, const TPointD &point) { + TPointD v1 = segment.getP1() - segment.getP0(); + TPointD v2 = point - segment.getP0(); + TPointD v3 = point - segment.getP1(); - if (v2 * v1 <= 0) - return tdistance(point, segment.getP0()); - else if (v3 * v1 >= 0) - return tdistance(point, segment.getP1()); + if (v2 * v1 <= 0) + return tdistance(point, segment.getP0()); + else if (v3 * v1 >= 0) + return tdistance(point, segment.getP1()); - return fabs(v2 * rotate90(normalize(v1))); + return fabs(v2 * rotate90(normalize(v1))); } //----------------------------------------------------------------------------- @@ -492,47 +473,47 @@ double tdistance(const TSegment &segment, const TPointD &point) This formule is derived from Graphic Gems pag. 600 e = h^2 |a|/8 - + e = pixel size h = step a = acceleration of curve (for a quadratic is a costant value) */ -double computeStep(const TQuadratic &quad, double pixelSize) -{ - double step = 2; +double computeStep(const TQuadratic &quad, double pixelSize) { + double step = 2; - TPointD A = quad.getP0() - 2.0 * quad.getP1() + quad.getP2(); // 2*A is the acceleration of the curve + TPointD A = quad.getP0() - 2.0 * quad.getP1() + + quad.getP2(); // 2*A is the acceleration of the curve - double A_len = norm(A); + double A_len = norm(A); - /* - A_len is equal to 2*norm(a) - pixelSize will be 0.5*pixelSize - now h is equal to sqrt( 8 * 0.5 * pixelSize / (2*norm(a)) ) = sqrt(2) * sqrt( pixelSize/A_len ) - */ + /* +A_len is equal to 2*norm(a) +pixelSize will be 0.5*pixelSize +now h is equal to sqrt( 8 * 0.5 * pixelSize / (2*norm(a)) ) = sqrt(2) * sqrt( +pixelSize/A_len ) +*/ - if (A_len > 0) - step = TConsts::sqrt2 * sqrt(pixelSize / A_len); + if (A_len > 0) step = sqrt(2 * pixelSize / A_len); - return step; + return step; } //----------------------------------------------------------------------------- -double computeStep(const TThickQuadratic &quad, double pixelSize) -{ - TThickPoint - cp0 = quad.getThickP0(), - cp1 = quad.getThickP1(), - cp2 = quad.getThickP2(); +double computeStep(const TThickQuadratic &quad, double pixelSize) { + TThickPoint cp0 = quad.getThickP0(), cp1 = quad.getThickP1(), + cp2 = quad.getThickP2(); - TQuadratic - q1(TPointD(cp0.x, cp0.y), TPointD(cp1.x, cp1.y), TPointD(cp2.x, cp2.y)), - q2(TPointD(cp0.y, cp0.thick), TPointD(cp1.y, cp1.thick), TPointD(cp2.y, cp2.thick)), - q3(TPointD(cp0.x, cp0.thick), TPointD(cp1.x, cp1.thick), TPointD(cp2.x, cp2.thick)); + TQuadratic q1(TPointD(cp0.x, cp0.y), TPointD(cp1.x, cp1.y), + TPointD(cp2.x, cp2.y)), + q2(TPointD(cp0.y, cp0.thick), TPointD(cp1.y, cp1.thick), + TPointD(cp2.y, cp2.thick)), + q3(TPointD(cp0.x, cp0.thick), TPointD(cp1.x, cp1.thick), + TPointD(cp2.x, cp2.thick)); - return std::min({computeStep(q1, pixelSize), computeStep(q2, pixelSize), computeStep(q3, pixelSize)}); + return std::min({computeStep(q1, pixelSize), computeStep(q2, pixelSize), + computeStep(q3, pixelSize)}); } //============================================================================= @@ -544,7 +525,8 @@ double computeStep(const TThickQuadratic &quad, double pixelSize) - The integrand can be reformulated as: | Q'(t) | = sqrt(at^2 + bt + c); - Complete the square beneath the sqrt (add/subtract sq(b) / 4a) - and perform a linear variable change. We reduce the integrand to: sqrt(kx^2 + k), + and perform a linear variable change. We reduce the integrand to: + sqrt(kx^2 + k), where k can be taken outside => sqrt(x^2 + 1) - Use x = tan y. The integrand will yield sec^3 y. - Integrate by parts. In short, the resulting primitive of sqrt(x^2 + 1) is: @@ -552,74 +534,71 @@ double computeStep(const TThickQuadratic &quad, double pixelSize) F(x) = ( x * sqrt(x^2 + 1) + log(x + sqrt(x^2 + 1)) ) / 2; */ -void TQuadraticLengthEvaluator::setQuad(const TQuadratic &quad) -{ - const TPointD &p0 = quad.getP0(); - const TPointD &p1 = quad.getP1(); - const TPointD &p2 = quad.getP2(); +void TQuadraticLengthEvaluator::setQuad(const TQuadratic &quad) { + const TPointD &p0 = quad.getP0(); + const TPointD &p1 = quad.getP1(); + const TPointD &p2 = quad.getP2(); - TPointD speed0(2.0 * (p1 - p0)); - TPointD accel(2.0 * (p2 - p1) - speed0); + TPointD speed0(2.0 * (p1 - p0)); + TPointD accel(2.0 * (p2 - p1) - speed0); - double a = accel * accel; - double b = 2.0 * accel * speed0; - m_c = speed0 * speed0; + double a = accel * accel; + double b = 2.0 * accel * speed0; + m_c = speed0 * speed0; - m_constantSpeed = isAlmostZero(a); // => b isAlmostZero, too - if (m_constantSpeed) { - m_c = sqrt(m_c); - return; - } + m_constantSpeed = isAlmostZero(a); // => b isAlmostZero, too + if (m_constantSpeed) { + m_c = sqrt(m_c); + return; + } - m_sqrt_a_div_2 = 0.5 * sqrt(a); + m_sqrt_a_div_2 = 0.5 * sqrt(a); - m_noSpeed0 = isAlmostZero(m_c); // => b isAlmostZero, too - if (m_noSpeed0) - return; + m_noSpeed0 = isAlmostZero(m_c); // => b isAlmostZero, too + if (m_noSpeed0) return; - m_tRef = 0.5 * b / a; - double d = m_c - 0.5 * b * m_tRef; + m_tRef = 0.5 * b / a; + double d = m_c - 0.5 * b * m_tRef; - m_squareIntegrand = (d < TConsts::epsilon); - if (m_squareIntegrand) { - m_f = (b > 0) ? -sq(m_tRef) : sq(m_tRef); - return; - } + m_squareIntegrand = (d < TConsts::epsilon); + if (m_squareIntegrand) { + m_f = (b > 0) ? -sq(m_tRef) : sq(m_tRef); + return; + } - m_e = d / a; + m_e = d / a; - double sqrt_part = sqrt(sq(m_tRef) + m_e); - double log_arg = m_tRef + sqrt_part; + double sqrt_part = sqrt(sq(m_tRef) + m_e); + double log_arg = m_tRef + sqrt_part; - m_squareIntegrand = (log_arg < TConsts::epsilon); - if (m_squareIntegrand) { - m_f = (b > 0) ? -sq(m_tRef) : sq(m_tRef); - return; - } + m_squareIntegrand = (log_arg < TConsts::epsilon); + if (m_squareIntegrand) { + m_f = (b > 0) ? -sq(m_tRef) : sq(m_tRef); + return; + } - m_primitive_0 = m_sqrt_a_div_2 * (m_tRef * sqrt_part + m_e * log(log_arg)); + m_primitive_0 = m_sqrt_a_div_2 * (m_tRef * sqrt_part + m_e * log(log_arg)); } //----------------------------------------------------------------------------- -double TQuadraticLengthEvaluator::getLengthAt(double t) const -{ - if (m_constantSpeed) - return m_c * t; +double TQuadraticLengthEvaluator::getLengthAt(double t) const { + if (m_constantSpeed) return m_c * t; - if (m_noSpeed0) - return m_sqrt_a_div_2 * sq(t); + if (m_noSpeed0) return m_sqrt_a_div_2 * sq(t); - if (m_squareIntegrand) { - double t_plus_tRef = t + m_tRef; - return m_sqrt_a_div_2 * (m_f + ((t_plus_tRef > 0) ? sq(t_plus_tRef) : -sq(t_plus_tRef))); - } + if (m_squareIntegrand) { + double t_plus_tRef = t + m_tRef; + return m_sqrt_a_div_2 * + (m_f + ((t_plus_tRef > 0) ? sq(t_plus_tRef) : -sq(t_plus_tRef))); + } - double y = t + m_tRef; - double sqrt_part = sqrt(sq(y) + m_e); - double log_arg = y + sqrt_part; //NOTE: log_arg >= log_arg0 >= TConsts::epsilon + double y = t + m_tRef; + double sqrt_part = sqrt(sq(y) + m_e); + double log_arg = + y + sqrt_part; // NOTE: log_arg >= log_arg0 >= TConsts::epsilon - return m_sqrt_a_div_2 * (y * sqrt_part + m_e * log(log_arg)) - m_primitive_0; + return m_sqrt_a_div_2 * (y * sqrt_part + m_e * log(log_arg)) - m_primitive_0; } //----------------------------------------------------------------------------- diff --git a/toonz/sources/common/tgeometry/tgeometry.cpp b/toonz/sources/common/tgeometry/tgeometry.cpp index 2cec8e1..065e270 100644 --- a/toonz/sources/common/tgeometry/tgeometry.cpp +++ b/toonz/sources/common/tgeometry/tgeometry.cpp @@ -8,235 +8,204 @@ using namespace std; const T3DPointD TConsts::nap3d((numeric_limits::max)(), - (numeric_limits::max)(), - (numeric_limits::max)()); + (numeric_limits::max)(), + (numeric_limits::max)()); const TThickPoint TConsts::natp((numeric_limits::max)(), - (numeric_limits::max)(), - (numeric_limits::max)()); + (numeric_limits::max)(), + (numeric_limits::max)()); const TPointD TConsts::napd((numeric_limits::max)(), - (numeric_limits::max)()); + (numeric_limits::max)()); const TPointI TConsts::nap((numeric_limits::max)(), - (numeric_limits::max)()); + (numeric_limits::max)()); const TRectD TConsts::infiniteRectD(-(numeric_limits::max)(), - -(numeric_limits::max)(), - (numeric_limits::max)(), - (numeric_limits::max)()); + -(numeric_limits::max)(), + (numeric_limits::max)(), + (numeric_limits::max)()); const TRectI TConsts::infiniteRectI(-(numeric_limits::max)(), - -(numeric_limits::max)(), - (numeric_limits::max)(), - (numeric_limits::max)()); + -(numeric_limits::max)(), + (numeric_limits::max)(), + (numeric_limits::max)()); //================================================================================================== // operazioni fra affini -TAffine &TAffine::operator=(const TAffine &a) -{ - a11 = a.a11; - a12 = a.a12; - a13 = a.a13; - a21 = a.a21; - a22 = a.a22; - a23 = a.a23; - return *this; +TAffine &TAffine::operator=(const TAffine &a) { + a11 = a.a11; + a12 = a.a12; + a13 = a.a13; + a21 = a.a21; + a22 = a.a22; + a23 = a.a23; + return *this; } //-------------------------------------------------------------------------------------------------- -TAffine TAffine::operator*(const TAffine &b) const -{ - return TAffine( - a11 * b.a11 + a12 * b.a21, - a11 * b.a12 + a12 * b.a22, - a11 * b.a13 + a12 * b.a23 + a13, +TAffine TAffine::operator*(const TAffine &b) const { + return TAffine(a11 * b.a11 + a12 * b.a21, a11 * b.a12 + a12 * b.a22, + a11 * b.a13 + a12 * b.a23 + a13, - a21 * b.a11 + a22 * b.a21, - a21 * b.a12 + a22 * b.a22, - a21 * b.a13 + a22 * b.a23 + a23); + a21 * b.a11 + a22 * b.a21, a21 * b.a12 + a22 * b.a22, + a21 * b.a13 + a22 * b.a23 + a23); } //-------------------------------------------------------------------------------------------------- -TAffine TAffine::operator*=(const TAffine &b) -{ - return *this = *this * b; -} +TAffine TAffine::operator*=(const TAffine &b) { return *this = *this * b; } //-------------------------------------------------------------------------------------------------- -TAffine TAffine::inv() const -{ - if (a12 == 0.0 && a21 == 0.0) { - assert(a11 != 0.0); - assert(a22 != 0.0); - double inv_a11 = 1.0 / a11; - double inv_a22 = 1.0 / a22; - return TAffine(inv_a11, 0, -a13 * inv_a11, - 0, inv_a22, -a23 * inv_a22); - } else if (a11 == 0.0 && a22 == 0.0) { - assert(a12 != 0.0); - assert(a21 != 0.0); - double inv_a21 = 1.0 / a21; - double inv_a12 = 1.0 / a12; - return TAffine(0, inv_a21, -a23 * inv_a21, - inv_a12, 0, -a13 * inv_a12); - } else { - double d = 1. / det(); - return TAffine(a22 * d, -a12 * d, (a12 * a23 - a22 * a13) * d, - -a21 * d, a11 * d, (a21 * a13 - a11 * a23) * d); - } +TAffine TAffine::inv() const { + if (a12 == 0.0 && a21 == 0.0) { + assert(a11 != 0.0); + assert(a22 != 0.0); + double inv_a11 = 1.0 / a11; + double inv_a22 = 1.0 / a22; + return TAffine(inv_a11, 0, -a13 * inv_a11, 0, inv_a22, -a23 * inv_a22); + } else if (a11 == 0.0 && a22 == 0.0) { + assert(a12 != 0.0); + assert(a21 != 0.0); + double inv_a21 = 1.0 / a21; + double inv_a12 = 1.0 / a12; + return TAffine(0, inv_a21, -a23 * inv_a21, inv_a12, 0, -a13 * inv_a12); + } else { + double d = 1. / det(); + return TAffine(a22 * d, -a12 * d, (a12 * a23 - a22 * a13) * d, -a21 * d, + a11 * d, (a21 * a13 - a11 * a23) * d); + } } //-------------------------------------------------------------------------------------------------- -double TAffine::det() const -{ - return a11 * a22 - a12 * a21; -} +double TAffine::det() const { return a11 * a22 - a12 * a21; } //-------------------------------------------------------------------------------------------------- -//Confronti tra affini -bool TAffine::operator==(const TAffine &a) const -{ - return a11 == a.a11 && a12 == a.a12 && a13 == a.a13 && - a21 == a.a21 && a22 == a.a22 && a23 == a.a23; +// Confronti tra affini +bool TAffine::operator==(const TAffine &a) const { + return a11 == a.a11 && a12 == a.a12 && a13 == a.a13 && a21 == a.a21 && + a22 == a.a22 && a23 == a.a23; } //-------------------------------------------------------------------------------------------------- -bool TAffine::operator!=(const TAffine &a) const -{ - return a11 != a.a11 || a12 != a.a12 || a13 != a.a13 || - a21 != a.a21 || a22 != a.a22 || a23 != a.a23; +bool TAffine::operator!=(const TAffine &a) const { + return a11 != a.a11 || a12 != a.a12 || a13 != a.a13 || a21 != a.a21 || + a22 != a.a22 || a23 != a.a23; } //-------------------------------------------------------------------------------------------------- -bool TAffine::isIdentity(double err) const -{ - return ((a11 - 1.0) * (a11 - 1.0) + (a22 - 1.0) * (a22 - 1.0) + - a12 * a12 + a13 * a13 + a21 * a21 + a23 * a23) < err; +bool TAffine::isIdentity(double err) const { + return ((a11 - 1.0) * (a11 - 1.0) + (a22 - 1.0) * (a22 - 1.0) + a12 * a12 + + a13 * a13 + a21 * a21 + a23 * a23) < err; } //-------------------------------------------------------------------------------------------------- -bool TAffine::isTranslation(double err) const -{ - return ((a11 - 1.0) * (a11 - 1.0) + (a22 - 1.0) * (a22 - 1.0) + - a12 * a12 + a21 * a21) < err; +bool TAffine::isTranslation(double err) const { + return ((a11 - 1.0) * (a11 - 1.0) + (a22 - 1.0) * (a22 - 1.0) + a12 * a12 + + a21 * a21) < err; } //-------------------------------------------------------------------------------------------------- -bool TAffine::isIsotropic(double err) const -{ - return areAlmostEqual(a11, a22, err) && areAlmostEqual(a12, -a21, err); +bool TAffine::isIsotropic(double err) const { + return areAlmostEqual(a11, a22, err) && areAlmostEqual(a12, -a21, err); } //-------------------------------------------------------------------------------------------------- // applicazione -TPointD TAffine::operator*(const TPointD &p) const -{ - return TPointD(p.x * a11 + p.y * a12 + a13, p.x * a21 + p.y * a22 + a23); +TPointD TAffine::operator*(const TPointD &p) const { + return TPointD(p.x * a11 + p.y * a12 + a13, p.x * a21 + p.y * a22 + a23); } //-------------------------------------------------------------------------------------------------- -TRectD TAffine::operator*(const TRectD &rect) const -{ - if (rect != TConsts::infiniteRectD) { - TPointD p1 = *this * rect.getP00(), - p2 = *this * rect.getP01(), - p3 = *this * rect.getP10(), - p4 = *this * rect.getP11(); - return TRectD( - std::min({p1.x, p2.x, p3.x, p4.x}), std::min({p1.y, p2.y, p3.y, p4.y}), - std::max({p1.x, p2.x, p3.x, p4.x}), std::max({p1.y, p2.y, p3.y, p4.y})); - } else - return TConsts::infiniteRectD; +TRectD TAffine::operator*(const TRectD &rect) const { + if (rect != TConsts::infiniteRectD) { + TPointD p1 = *this * rect.getP00(), p2 = *this * rect.getP01(), + p3 = *this * rect.getP10(), p4 = *this * rect.getP11(); + return TRectD( + std::min({p1.x, p2.x, p3.x, p4.x}), std::min({p1.y, p2.y, p3.y, p4.y}), + std::max({p1.x, p2.x, p3.x, p4.x}), std::max({p1.y, p2.y, p3.y, p4.y})); + } else + return TConsts::infiniteRectD; } //-------------------------------------------------------------------------------------------------- -TAffine TAffine::place(double u, double v, double x, double y) const -{ - return TAffine(a11, a12, x - (a11 * u + a12 * v), - a21, a22, y - (a21 * u + a22 * v)); +TAffine TAffine::place(double u, double v, double x, double y) const { + return TAffine(a11, a12, x - (a11 * u + a12 * v), a21, a22, + y - (a21 * u + a22 * v)); } //-------------------------------------------------------------------------------------------------- -TAffine TAffine::place(const TPointD &pIn, const TPointD &pOut) const -{ - return TAffine(a11, a12, pOut.x - (a11 * pIn.x + a12 * pIn.y), - a21, a22, pOut.y - (a21 * pIn.x + a22 * pIn.y)); +TAffine TAffine::place(const TPointD &pIn, const TPointD &pOut) const { + return TAffine(a11, a12, pOut.x - (a11 * pIn.x + a12 * pIn.y), a21, a22, + pOut.y - (a21 * pIn.x + a22 * pIn.y)); } //================================================================================================== -TRotation::TRotation(double degrees) -{ - double rad, sn, cs; - int idegrees = (int)degrees; - if ((double)idegrees == degrees && idegrees % 90 == 0) { - switch ((idegrees / 90) & 3) { - case 0: - sn = 0; - cs = 1; - break; - case 1: - sn = 1; - cs = 0; - break; - case 2: - sn = 0; - cs = -1; - break; - case 3: - sn = -1; - cs = 0; - break; - default: - sn = 0; - cs = 0; - break; - } - } else { - rad = degrees * (TConsts::pi_180); - sn = sin(rad); - cs = cos(rad); - if (sn == 1 || sn == -1) - cs = 0; - if (cs == 1 || cs == -1) - sn = 0; - } - a11 = cs; - a12 = -sn; - a21 = -a12; - a22 = a11; +TRotation::TRotation(double degrees) { + double rad, sn, cs; + int idegrees = (int)degrees; + if ((double)idegrees == degrees && idegrees % 90 == 0) { + switch ((idegrees / 90) & 3) { + case 0: + sn = 0; + cs = 1; + break; + case 1: + sn = 1; + cs = 0; + break; + case 2: + sn = 0; + cs = -1; + break; + case 3: + sn = -1; + cs = 0; + break; + default: + sn = 0; + cs = 0; + break; + } + } else { + rad = degrees * M_PI_180; + sn = sin(rad); + cs = cos(rad); + if (sn == 1 || sn == -1) cs = 0; + if (cs == 1 || cs == -1) sn = 0; + } + a11 = cs; + a12 = -sn; + a21 = -a12; + a22 = a11; } //-------------------------------------------------------------------------------------------------- -TRotation::TRotation(const TPointD ¢er, double degrees) -{ - TAffine a = TTranslation(center) * TRotation(degrees) * TTranslation(-center); - a11 = a.a11; - a12 = a.a12; - a13 = a.a13; - a21 = a.a21; - a22 = a.a22; - a23 = a.a23; +TRotation::TRotation(const TPointD ¢er, double degrees) { + TAffine a = TTranslation(center) * TRotation(degrees) * TTranslation(-center); + a11 = a.a11; + a12 = a.a12; + a13 = a.a13; + a21 = a.a21; + a22 = a.a22; + a23 = a.a23; } //================================================================================================== -TScale::TScale(const TPointD ¢er, double sx, double sy) -{ - TAffine a = TTranslation(center) * TScale(sx, sy) * TTranslation(-center); - a11 = a.a11; - a12 = a.a12; - a13 = a.a13; - a21 = a.a21; - a22 = a.a22; - a23 = a.a23; +TScale::TScale(const TPointD ¢er, double sx, double sy) { + TAffine a = TTranslation(center) * TScale(sx, sy) * TTranslation(-center); + a11 = a.a11; + a12 = a.a12; + a13 = a.a13; + a21 = a.a21; + a22 = a.a22; + a23 = a.a23; } //-------------------------------------------------------------------------------------------------- -TScale::TScale(const TPointD ¢er, double s) -{ - TAffine a = TTranslation(center) * TScale(s) * TTranslation(-center); - a11 = a.a11; - a12 = a.a12; - a13 = a.a13; - a21 = a.a21; - a22 = a.a22; - a23 = a.a23; +TScale::TScale(const TPointD ¢er, double s) { + TAffine a = TTranslation(center) * TScale(s) * TTranslation(-center); + a11 = a.a11; + a12 = a.a12; + a13 = a.a13; + a21 = a.a21; + a22 = a.a22; + a23 = a.a23; } diff --git a/toonz/sources/common/tgl/tgl.cpp b/toonz/sources/common/tgl/tgl.cpp index a4489b8..1cc7d2b 100644 --- a/toonz/sources/common/tgl/tgl.cpp +++ b/toonz/sources/common/tgl/tgl.cpp @@ -30,312 +30,281 @@ //----------------------------------------------------------------------------- -namespace -{ +namespace { // GLUquadric* localDisk=0; /* Find the number of slices in function of radius size. - \par radius of circle + \par radius of circle \par size of pixel \ret number of division to obtain a circle */ -int computeSlices(double radius, double pixelSize = 1.0) -{ - if (radius < 0) - return 2; +int computeSlices(double radius, double pixelSize = 1.0) { + if (radius < 0) return 2; - double thetaStep; - double temp = pixelSize * 0.5 / radius; + double thetaStep; + double temp = pixelSize * 0.5 / radius; - if (fabs(1.0 - temp) <= 1) - thetaStep = acos(1.0 - temp); - else - thetaStep = TConsts::pi_2 * 0.5; + if (fabs(1.0 - temp) <= 1) + thetaStep = acos(1.0 - temp); + else + thetaStep = M_PI_4; - assert(thetaStep != 0.0); + assert(thetaStep != 0.0); - int numberOfSlices = (int)(2.0 * TConsts::pi / thetaStep); + int numberOfSlices = (int)(M_2PI / thetaStep); - return numberOfSlices != 0 ? numberOfSlices : 2; + return numberOfSlices != 0 ? numberOfSlices : 2; } -} // end of unnamed namespace +} // end of unnamed namespace //----------------------------------------------------------------------------- -double tglGetPixelSize2() -{ - double mat[16]; - glMatrixMode(GL_MODELVIEW); - glGetDoublev(GL_MODELVIEW_MATRIX, mat); +double tglGetPixelSize2() { + double mat[16]; + glMatrixMode(GL_MODELVIEW); + glGetDoublev(GL_MODELVIEW_MATRIX, mat); - double det = fabs(mat[0] * mat[5] - mat[1] * mat[4]); - if (det < TConsts::epsilon) - det = TConsts::epsilon; - return 1.0 / det; + double det = fabs(mat[0] * mat[5] - mat[1] * mat[4]); + if (det < TConsts::epsilon) det = TConsts::epsilon; + return 1.0 / det; } //----------------------------------------------------------------------------- -double tglGetTextWidth(const std::string &s, void *font) -{ - double factor = 0.07; - double w = 0; - for (int i = 0; i < (int)s.length(); i++) - w += glutStrokeWidth(font, s[i]); - return w * factor; +double tglGetTextWidth(const std::string &s, void *font) { + double factor = 0.07; + double w = 0; + for (int i = 0; i < (int)s.length(); i++) w += glutStrokeWidth(font, s[i]); + return w * factor; } //----------------------------------------------------------------------------- -void tglDrawText(const TPointD &p, const std::string &s, void *character) -{ +void tglDrawText(const TPointD &p, const std::string &s, void *character) { #ifndef __sgi - glPushMatrix(); - glTranslated(p.x, p.y, 0); - double factor = 0.07; - glScaled(factor, factor, factor); - for (int i = 0; i < (int)s.size(); i++) - glutStrokeCharacter(character, s[i]); - glPopMatrix(); + glPushMatrix(); + glTranslated(p.x, p.y, 0); + double factor = 0.07; + glScaled(factor, factor, factor); + for (int i = 0; i < (int)s.size(); i++) glutStrokeCharacter(character, s[i]); + glPopMatrix(); #else - assert("Not Yet Implemented" && 0); - std::cout << s << std::endl; + assert("Not Yet Implemented" && 0); + std::cout << s << std::endl; #endif } //----------------------------------------------------------------------------- -void tglDrawText(const TPointD &p, const std::wstring &s, void *character) -{ +void tglDrawText(const TPointD &p, const std::wstring &s, void *character) { #ifndef __sgi - glPushMatrix(); - glTranslated(p.x, p.y, 0); - double factor = 0.07; - glScaled(factor, factor, factor); - for (int i = 0; i < (int)s.size(); i++) - glutStrokeCharacter(character, s[i]); - glPopMatrix(); + glPushMatrix(); + glTranslated(p.x, p.y, 0); + double factor = 0.07; + glScaled(factor, factor, factor); + for (int i = 0; i < (int)s.size(); i++) glutStrokeCharacter(character, s[i]); + glPopMatrix(); #else - assert("Not Yet Implemented" && 0); - std::cout << s << std::endl; + assert("Not Yet Implemented" && 0); + std::cout << s << std::endl; #endif } //----------------------------------------------------------------------------- -void tglDrawSegment(const TPointD &p1, const TPointD &p2) -{ - glBegin(GL_LINES); - tglVertex(p1); - tglVertex(p2); - glEnd(); +void tglDrawSegment(const TPointD &p1, const TPointD &p2) { + glBegin(GL_LINES); + tglVertex(p1); + tglVertex(p2); + glEnd(); } //----------------------------------------------------------------------------- -void tglDrawCircle(const TPointD ¢er, double radius) -{ - if (radius <= 0) - return; +void tglDrawCircle(const TPointD ¢er, double radius) { + if (radius <= 0) return; - double pixelSize = 1; - int slices = 60; + double pixelSize = 1; + int slices = 60; - if (slices <= 0) - slices = computeSlices(radius, pixelSize) >> 1; + if (slices <= 0) slices = computeSlices(radius, pixelSize) >> 1; - double step = TConsts::pi / slices; - double step2 = 2.0 * step; + double step = M_PI / slices; + double step2 = 2.0 * step; - double - cos_t, - sin_t, - cos_ts, sin_ts, t; + double cos_t, sin_t, cos_ts, sin_ts, t; - glPushMatrix(); - glTranslated(center.x, center.y, 0.0); - glBegin(GL_LINES); + glPushMatrix(); + glTranslated(center.x, center.y, 0.0); + glBegin(GL_LINES); - cos_t = radius /* *1.0*/; - sin_t = 0.0; - for (t = 0; t + step < TConsts::pi_2; t += step2) { - cos_ts = radius * cos(t + step); - sin_ts = radius * sin(t + step); + cos_t = radius /* *1.0*/; + sin_t = 0.0; + for (t = 0; t + step < M_PI_2; t += step2) { + cos_ts = radius * cos(t + step); + sin_ts = radius * sin(t + step); - glVertex2f(cos_t, sin_t); - glVertex2f(cos_ts, sin_ts); + glVertex2f(cos_t, sin_t); + glVertex2f(cos_ts, sin_ts); - glVertex2f(-cos_t, sin_t); - glVertex2f(-cos_ts, sin_ts); + glVertex2f(-cos_t, sin_t); + glVertex2f(-cos_ts, sin_ts); - glVertex2f(-cos_t, -sin_t); - glVertex2f(-cos_ts, -sin_ts); + glVertex2f(-cos_t, -sin_t); + glVertex2f(-cos_ts, -sin_ts); - glVertex2f(cos_t, -sin_t); - glVertex2f(cos_ts, -sin_ts); + glVertex2f(cos_t, -sin_t); + glVertex2f(cos_ts, -sin_ts); - cos_t = cos_ts; - sin_t = sin_ts; - } + cos_t = cos_ts; + sin_t = sin_ts; + } - cos_ts = 0.0; - sin_ts = radius /* *1.0*/; + cos_ts = 0.0; + sin_ts = radius /* *1.0*/; - glVertex2f(cos_t, sin_t); - glVertex2f(cos_ts, sin_ts); + glVertex2f(cos_t, sin_t); + glVertex2f(cos_ts, sin_ts); - glVertex2f(-cos_t, sin_t); - glVertex2f(-cos_ts, sin_ts); + glVertex2f(-cos_t, sin_t); + glVertex2f(-cos_ts, sin_ts); - glVertex2f(-cos_t, -sin_t); - glVertex2f(-cos_ts, -sin_ts); + glVertex2f(-cos_t, -sin_t); + glVertex2f(-cos_ts, -sin_ts); - glVertex2f(cos_t, -sin_t); - glVertex2f(cos_ts, -sin_ts); + glVertex2f(cos_t, -sin_t); + glVertex2f(cos_ts, -sin_ts); - glEnd(); - glPopMatrix(); + glEnd(); + glPopMatrix(); } //----------------------------------------------------------------------------- -void tglDrawDisk(const TPointD &c, double r) -{ - if (r <= 0) - return; +void tglDrawDisk(const TPointD &c, double r) { + if (r <= 0) return; - double pixelSize = 1; - int slices = 60; + double pixelSize = 1; + int slices = 60; - if (slices <= 0) - slices = computeSlices(r, pixelSize) >> 1; + if (slices <= 0) slices = computeSlices(r, pixelSize) >> 1; - glPushMatrix(); - glTranslated(c.x, c.y, 0.0); - GLUquadric *quadric = gluNewQuadric(); - gluDisk(quadric, 0, r, slices, 1); - gluDeleteQuadric(quadric); - glPopMatrix(); + glPushMatrix(); + glTranslated(c.x, c.y, 0.0); + GLUquadric *quadric = gluNewQuadric(); + gluDisk(quadric, 0, r, slices, 1); + gluDeleteQuadric(quadric); + glPopMatrix(); } //----------------------------------------------------------------------------- -void tglDrawRect(const TRectD &rect) -{ - glBegin(GL_LINE_LOOP); - tglVertex(rect.getP00()); - tglVertex(rect.getP10()); - tglVertex(rect.getP11()); - tglVertex(rect.getP01()); - glEnd(); +void tglDrawRect(const TRectD &rect) { + glBegin(GL_LINE_LOOP); + tglVertex(rect.getP00()); + tglVertex(rect.getP10()); + tglVertex(rect.getP11()); + tglVertex(rect.getP01()); + glEnd(); } //----------------------------------------------------------------------------- -void tglFillRect(const TRectD &rect) -{ - glBegin(GL_POLYGON); - tglVertex(rect.getP00()); - tglVertex(rect.getP10()); - tglVertex(rect.getP11()); - tglVertex(rect.getP01()); - glEnd(); +void tglFillRect(const TRectD &rect) { + glBegin(GL_POLYGON); + tglVertex(rect.getP00()); + tglVertex(rect.getP10()); + tglVertex(rect.getP11()); + tglVertex(rect.getP01()); + glEnd(); } //----------------------------------------------------------------------------- -void tglRgbOnlyColorMask() -{ - tglMultColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); - tglEnableBlending(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +void tglRgbOnlyColorMask() { + tglMultColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); + tglEnableBlending(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } //----------------------------------------------------------------------------- -void tglAlphaOnlyColorMask() -{ - tglMultColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); - tglEnableBlending(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); +void tglAlphaOnlyColorMask() { + tglMultColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); + tglEnableBlending(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); } //----------------------------------------------------------------------------- -void tglEnableBlending(GLenum src, GLenum dst) -{ - glEnable(GL_BLEND); - glBlendFunc(src, dst); +void tglEnableBlending(GLenum src, GLenum dst) { + glEnable(GL_BLEND); + glBlendFunc(src, dst); } //----------------------------------------------------------------------------- -void tglEnableLineSmooth(bool enable, double lineSize) -{ - if (enable) { - glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); - glEnable(GL_LINE_SMOOTH); - glLineWidth(lineSize); - } else - glDisable(GL_LINE_SMOOTH); +void tglEnableLineSmooth(bool enable, double lineSize) { + if (enable) { + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + glEnable(GL_LINE_SMOOTH); + glLineWidth(lineSize); + } else + glDisable(GL_LINE_SMOOTH); } //----------------------------------------------------------------------------- -void tglEnablePointSmooth(double pointSize) -{ - glEnable(GL_BLEND); - glPointSize(pointSize); +void tglEnablePointSmooth(double pointSize) { + glEnable(GL_BLEND); + glPointSize(pointSize); } //----------------------------------------------------------------------------- -void tglGetColorMask(GLboolean &red, GLboolean &green, GLboolean &blue, GLboolean &alpha) -{ - GLboolean channels[4]; - glGetBooleanv(GL_COLOR_WRITEMASK, &channels[0]); - red = channels[0], green = channels[1], blue = channels[2], alpha = channels[3]; +void tglGetColorMask(GLboolean &red, GLboolean &green, GLboolean &blue, + GLboolean &alpha) { + GLboolean channels[4]; + glGetBooleanv(GL_COLOR_WRITEMASK, &channels[0]); + red = channels[0], green = channels[1], blue = channels[2], + alpha = channels[3]; } //----------------------------------------------------------------------------- -void tglMultColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) -{ - GLboolean channels[4]; - glGetBooleanv(GL_COLOR_WRITEMASK, &channels[0]); - glColorMask(red && channels[0], - green && channels[1], - blue && channels[2], - alpha && channels[3]); +void tglMultColorMask(GLboolean red, GLboolean green, GLboolean blue, + GLboolean alpha) { + GLboolean channels[4]; + glGetBooleanv(GL_COLOR_WRITEMASK, &channels[0]); + glColorMask(red && channels[0], green && channels[1], blue && channels[2], + alpha && channels[3]); } //============================================================================ -namespace -{ +namespace { //============================================================================ -class GlFontManager -{ - GlFontManager(); +class GlFontManager { + GlFontManager(); public: - ~GlFontManager(); - static GlFontManager *instance(); - bool setFont(void *font = GLUT_BITMAP_TIMES_ROMAN_10); - void drawText(/*const TRectD bBox,*/ - std::wstring wtext /*, + ~GlFontManager(); + static GlFontManager *instance(); + bool setFont(void *font = GLUT_BITMAP_TIMES_ROMAN_10); + void drawText(/*const TRectD bBox,*/ + std::wstring wtext /*, TDimensionD scale = TDimensionD(1.0, 1.0)*/); private: - static GlFontManager *m_instance; - - // font font_height - // | | - std::map m_fonts; - std::vector m_charsBBox; - void *m_currentFont; - TRaster32P m_fontTexture; - GLuint m_base; + static GlFontManager *m_instance; + + // font font_height + // | | + std::map m_fonts; + std::vector m_charsBBox; + void *m_currentFont; + TRaster32P m_fontTexture; + GLuint m_base; }; //---------------------------------------------------------------------------- @@ -344,369 +313,329 @@ GlFontManager *GlFontManager::m_instance = 0L; //---------------------------------------------------------------------------- -GlFontManager::GlFontManager() - : m_currentFont(0L), m_base(0) -{ - m_fonts.insert(std::make_pair(GLUT_BITMAP_8_BY_13, 13.0)); - m_fonts.insert(std::make_pair(GLUT_BITMAP_9_BY_15, 15.0)); - m_fonts.insert(std::make_pair(GLUT_BITMAP_TIMES_ROMAN_10, 10.0)); - m_fonts.insert(std::make_pair(GLUT_BITMAP_TIMES_ROMAN_24, 24.0)); - m_fonts.insert(std::make_pair(GLUT_BITMAP_HELVETICA_10, 10.0)); - m_fonts.insert(std::make_pair(GLUT_BITMAP_HELVETICA_12, 12.0)); - m_fonts.insert(std::make_pair(GLUT_BITMAP_HELVETICA_18, 18.0)); - bool ok = setFont(); - assert(ok); +GlFontManager::GlFontManager() : m_currentFont(0L), m_base(0) { + m_fonts.insert(std::make_pair(GLUT_BITMAP_8_BY_13, 13.0)); + m_fonts.insert(std::make_pair(GLUT_BITMAP_9_BY_15, 15.0)); + m_fonts.insert(std::make_pair(GLUT_BITMAP_TIMES_ROMAN_10, 10.0)); + m_fonts.insert(std::make_pair(GLUT_BITMAP_TIMES_ROMAN_24, 24.0)); + m_fonts.insert(std::make_pair(GLUT_BITMAP_HELVETICA_10, 10.0)); + m_fonts.insert(std::make_pair(GLUT_BITMAP_HELVETICA_12, 12.0)); + m_fonts.insert(std::make_pair(GLUT_BITMAP_HELVETICA_18, 18.0)); + bool ok = setFont(); + assert(ok); } //---------------------------------------------------------------------------- -GlFontManager::~GlFontManager() -{ - m_instance = 0L; -} +GlFontManager::~GlFontManager() { m_instance = 0L; } //---------------------------------------------------------------------------- -GlFontManager *GlFontManager::instance() -{ - if (!m_instance) - m_instance = new GlFontManager(); +GlFontManager *GlFontManager::instance() { + if (!m_instance) m_instance = new GlFontManager(); - return m_instance; + return m_instance; } //---------------------------------------------------------------------------- -bool GlFontManager::setFont(void *font) -{ - // cerca il font scelto nella mappa dei fonts conosciuti - std::map::iterator it = - m_fonts.find(font); - - // se e' stato trovato - if (it != m_fonts.end()) { - m_currentFont = font; - - glPushAttrib(GL_ALL_ATTRIB_BITS); - glPushMatrix(); - m_base = glGenLists(256); - glListBase(m_base); - int i = 0; - for (; i < 256; ++i) { - glNewList(m_base + i, GL_COMPILE); - glutStrokeCharacter(GLUT_STROKE_ROMAN, i); - //glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, i); - glEndList(); - } - glPopAttrib(); - glPopMatrix(); - return true; - } - return false; +bool GlFontManager::setFont(void *font) { + // cerca il font scelto nella mappa dei fonts conosciuti + std::map::iterator it = m_fonts.find(font); + + // se e' stato trovato + if (it != m_fonts.end()) { + m_currentFont = font; + + glPushAttrib(GL_ALL_ATTRIB_BITS); + glPushMatrix(); + m_base = glGenLists(256); + glListBase(m_base); + int i = 0; + for (; i < 256; ++i) { + glNewList(m_base + i, GL_COMPILE); + glutStrokeCharacter(GLUT_STROKE_ROMAN, i); + // glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, i); + glEndList(); + } + glPopAttrib(); + glPopMatrix(); + return true; + } + return false; } //---------------------------------------------------------------------------- void GlFontManager::drawText(/*const TRectD bBox,*/ - std::wstring wtext /*, - TDimensionD scale*/) -{ - if (!m_currentFont) - return; - - std::string text = ::to_string(wtext); - const char *textString = text.c_str(); - glListBase(m_base); - /* - glPushMatrix(); - glTranslated(bBox.x0, bBox.y0, 0.0); - glScaled(scale.lx*0.07, scale.ly*0.07, 1.0); - */ - glCallLists((GLuint)strlen(textString), GL_BYTE, textString); - /*glPopMatrix();*/ + std::wstring wtext /*, + TDimensionD scale*/) { + if (!m_currentFont) return; + + std::string text = ::to_string(wtext); + const char *textString = text.c_str(); + glListBase(m_base); + /* +glPushMatrix(); +glTranslated(bBox.x0, bBox.y0, 0.0); +glScaled(scale.lx*0.07, scale.ly*0.07, 1.0); +*/ + glCallLists((GLuint)strlen(textString), GL_BYTE, textString); + /*glPopMatrix();*/ } //============================================================================ -} // anonymous namespace +} // anonymous namespace //============================================================================ -void tglDraw(const TCubic &cubic, int precision, GLenum pointOrLine) -{ - CHECK_ERRORS_BY_GL; - assert(pointOrLine == GL_POINT || pointOrLine == GL_LINE); - float ctrlPts[4][3]; - - ctrlPts[0][0] = cubic.getP0().x; - ctrlPts[0][1] = cubic.getP0().y; - ctrlPts[0][2] = 0.0; - - ctrlPts[1][0] = cubic.getP1().x; - ctrlPts[1][1] = cubic.getP1().y; - ctrlPts[1][2] = 0.0; - - ctrlPts[2][0] = cubic.getP2().x; - ctrlPts[2][1] = cubic.getP2().y; - ctrlPts[2][2] = 0.0; - - ctrlPts[3][0] = cubic.getP3().x; - ctrlPts[3][1] = cubic.getP3().y; - ctrlPts[3][2] = 0.0; - - CHECK_ERRORS_BY_GL; - glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &ctrlPts[0][0]); - CHECK_ERRORS_BY_GL; - glEnable(GL_MAP1_VERTEX_3); - CHECK_ERRORS_BY_GL; - glMapGrid1f(precision, 0.0, 1.0); - CHECK_ERRORS_BY_GL; - glEvalMesh1(pointOrLine, 0, precision); - CHECK_ERRORS_BY_GL; +void tglDraw(const TCubic &cubic, int precision, GLenum pointOrLine) { + CHECK_ERRORS_BY_GL; + assert(pointOrLine == GL_POINT || pointOrLine == GL_LINE); + float ctrlPts[4][3]; + + ctrlPts[0][0] = cubic.getP0().x; + ctrlPts[0][1] = cubic.getP0().y; + ctrlPts[0][2] = 0.0; + + ctrlPts[1][0] = cubic.getP1().x; + ctrlPts[1][1] = cubic.getP1().y; + ctrlPts[1][2] = 0.0; + + ctrlPts[2][0] = cubic.getP2().x; + ctrlPts[2][1] = cubic.getP2().y; + ctrlPts[2][2] = 0.0; + + ctrlPts[3][0] = cubic.getP3().x; + ctrlPts[3][1] = cubic.getP3().y; + ctrlPts[3][2] = 0.0; + + CHECK_ERRORS_BY_GL; + glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &ctrlPts[0][0]); + CHECK_ERRORS_BY_GL; + glEnable(GL_MAP1_VERTEX_3); + CHECK_ERRORS_BY_GL; + glMapGrid1f(precision, 0.0, 1.0); + CHECK_ERRORS_BY_GL; + glEvalMesh1(pointOrLine, 0, precision); + CHECK_ERRORS_BY_GL; } //----------------------------------------------------------------------------- -void tglDraw(const TRectD &rect, - const std::vector &textures, - bool blending) -{ - double pixelSize2 = tglGetPixelSize2(); - // level e' la minore potenza di 2 maggiore di sqrt(pixelSize2) - unsigned int level = 1; - while (pixelSize2 * level * level <= 1.0) - level <<= 1; +void tglDraw(const TRectD &rect, const std::vector &textures, + bool blending) { + double pixelSize2 = tglGetPixelSize2(); + // level e' la minore potenza di 2 maggiore di sqrt(pixelSize2) + unsigned int level = 1; + while (pixelSize2 * level * level <= 1.0) level <<= 1; - unsigned int texturesCount = (int)textures.size(); - if (level > texturesCount) - level = texturesCount; + unsigned int texturesCount = (int)textures.size(); + if (level > texturesCount) level = texturesCount; - level = texturesCount - level; + level = texturesCount - level; - tglDraw(rect, textures[level], blending); + tglDraw(rect, textures[level], blending); } //------------------------------------------------------------------- -void tglDraw(const TRectD &rect, const TRaster32P &tex, bool blending) -{ - CHECK_ERRORS_BY_GL; - glPushAttrib(GL_ALL_ATTRIB_BITS); - if (blending) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - - unsigned int texWidth = 1; - unsigned int texHeight = 1; - - while (texWidth < (unsigned int)tex->getLx()) - texWidth = texWidth << 1; - - while (texHeight < (unsigned int)tex->getLy()) - texHeight = texHeight << 1; - - double lwTex = 1.0; - double lhTex = 1.0; - - TRaster32P texture; - unsigned int texLx = (unsigned int)tex->getLx(); - unsigned int texLy = (unsigned int)tex->getLy(); - - if (texWidth != texLx || - texHeight != texLy) { - texture = TRaster32P(texWidth, texHeight); - texture->fill(TPixel32(0, 0, 0, 0)); - texture->copy(tex); - lwTex = (texLx) / (double)(texWidth); - lhTex = (texLy) / (double)(texHeight); - if (lwTex > 1.0) - lwTex = 1.0; - if (lhTex > 1.0) - lhTex = 1.0; - } else - texture = tex; - GLenum fmt = +void tglDraw(const TRectD &rect, const TRaster32P &tex, bool blending) { + CHECK_ERRORS_BY_GL; + glPushAttrib(GL_ALL_ATTRIB_BITS); + if (blending) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + unsigned int texWidth = 1; + unsigned int texHeight = 1; + + while (texWidth < (unsigned int)tex->getLx()) texWidth = texWidth << 1; + + while (texHeight < (unsigned int)tex->getLy()) texHeight = texHeight << 1; + + double lwTex = 1.0; + double lhTex = 1.0; + + TRaster32P texture; + unsigned int texLx = (unsigned int)tex->getLx(); + unsigned int texLy = (unsigned int)tex->getLy(); + + if (texWidth != texLx || texHeight != texLy) { + texture = TRaster32P(texWidth, texHeight); + texture->fill(TPixel32(0, 0, 0, 0)); + texture->copy(tex); + lwTex = (texLx) / (double)(texWidth); + lhTex = (texLy) / (double)(texHeight); + if (lwTex > 1.0) lwTex = 1.0; + if (lhTex > 1.0) lhTex = 1.0; + } else + texture = tex; + GLenum fmt = #ifdef TNZ_MACHINE_CHANNEL_ORDER_BGRM - GL_BGRA_EXT; + GL_BGRA_EXT; #elif TNZ_MACHINE_CHANNEL_ORDER_MBGR - GL_ABGR_EXT; + GL_ABGR_EXT; #elif TNZ_MACHINE_CHANNEL_ORDER_RGBM - GL_RGBA; + GL_RGBA; #elif TNZ_MACHINE_CHANNEL_ORDER_MRGB - GL_BGRA; + GL_BGRA; #else // Error PLATFORM NOT SUPPORTED #error "unknown channel order!" #endif - // Generate a texture id and bind it. - GLuint texId; - glGenTextures(1, &texId); + // Generate a texture id and bind it. + GLuint texId; + glGenTextures(1, &texId); - glBindTexture(GL_TEXTURE_2D, texId); + glBindTexture(GL_TEXTURE_2D, texId); - glPixelStorei(GL_UNPACK_ROW_LENGTH, texture->getWrap()); + glPixelStorei(GL_UNPACK_ROW_LENGTH, texture->getWrap()); - texture->lock(); - glTexImage2D(GL_TEXTURE_2D, - 0, - 4, - texWidth, - texHeight, - 0, - fmt, + texture->lock(); + glTexImage2D(GL_TEXTURE_2D, 0, 4, texWidth, texHeight, 0, fmt, #ifdef TNZ_MACHINE_CHANNEL_ORDER_MRGB - GL_UNSIGNED_INT_8_8_8_8_REV, + GL_UNSIGNED_INT_8_8_8_8_REV, #else - GL_UNSIGNED_BYTE, + GL_UNSIGNED_BYTE, #endif - texture->getRawData()); + texture->getRawData()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glEnable(GL_TEXTURE_2D); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glEnable(GL_TEXTURE_2D); - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); - double rectLx = rect.getLx(); - double rectLy = rect.getLy(); + double rectLx = rect.getLx(); + double rectLy = rect.getLy(); - tglColor(TPixel32(0, 0, 0, 0)); + tglColor(TPixel32(0, 0, 0, 0)); - glPushMatrix(); + glPushMatrix(); - glTranslated(rect.x0, rect.y0, 0.0); - glBegin(GL_POLYGON); + glTranslated(rect.x0, rect.y0, 0.0); + glBegin(GL_POLYGON); - glTexCoord2d(0, 0); - tglVertex(TPointD(0.0, 0.0)); + glTexCoord2d(0, 0); + tglVertex(TPointD(0.0, 0.0)); - glTexCoord2d(lwTex, 0); - tglVertex(TPointD(rectLx, 0.0)); + glTexCoord2d(lwTex, 0); + tglVertex(TPointD(rectLx, 0.0)); - glTexCoord2d(lwTex, lhTex); - tglVertex(TPointD(rectLx, rectLy)); + glTexCoord2d(lwTex, lhTex); + tglVertex(TPointD(rectLx, rectLy)); - glTexCoord2d(0, lhTex); - tglVertex(TPointD(0.0, rectLy)); + glTexCoord2d(0, lhTex); + tglVertex(TPointD(0.0, rectLy)); - glEnd(); - glDisable(GL_TEXTURE_2D); + glEnd(); + glDisable(GL_TEXTURE_2D); - glPopMatrix(); - glPopAttrib(); + glPopMatrix(); + glPopAttrib(); - // Delete texture - glDeleteTextures(1, &texId); + // Delete texture + glDeleteTextures(1, &texId); - texture->unlock(); + texture->unlock(); } //----------------------------------------------------------------------------- void tglBuildMipmaps(std::vector &rasters, - const TFilePath &filepath) -{ - assert(rasters.size() > 0); - TRop::ResampleFilterType resampleFilter = TRop::ClosestPixel; - TRasterP ras; - TImageReader::load(filepath, ras); - int rasLx = ras->getLx(); - int rasLy = ras->getLy(); - - int lx = 1; - while (lx < rasLx) - lx <<= 1; - - int ly = 1; - while (ly < rasLy) - ly <<= 1; - - TRaster32P ras2(lx, ly); - double sx = (double)lx / (double)ras->getLx(); - double sy = (double)ly / (double)ras->getLy(); + const TFilePath &filepath) { + assert(rasters.size() > 0); + TRop::ResampleFilterType resampleFilter = TRop::ClosestPixel; + TRasterP ras; + TImageReader::load(filepath, ras); + int rasLx = ras->getLx(); + int rasLy = ras->getLy(); + + int lx = 1; + while (lx < rasLx) lx <<= 1; + + int ly = 1; + while (ly < rasLy) ly <<= 1; + + TRaster32P ras2(lx, ly); + double sx = (double)lx / (double)ras->getLx(); + double sy = (double)ly / (double)ras->getLy(); #ifndef SCALE_BY_GLU - TRop::resample(ras2, ras, TScale(sx, sy), resampleFilter); + TRop::resample(ras2, ras, TScale(sx, sy), resampleFilter); #else - ras->lock(); - gluScaleImage(GL_RGBA, ras->getLx(), ras->getLy(), GL_UNSIGNED_BYTE, ras->getRawData(), - lx, ly, GL_UNSIGNED_BYTE, ras2->getRawData()); - ras->unlock(); + ras->lock(); + gluScaleImage(GL_RGBA, ras->getLx(), ras->getLy(), GL_UNSIGNED_BYTE, + ras->getRawData(), lx, ly, GL_UNSIGNED_BYTE, + ras2->getRawData()); + ras->unlock(); #endif - rasters[0] = ras2; - int ras2Lx = ras2->getLx(); - int ras2Ly = ras2->getLy(); - for (int i = 1; i < (int)rasters.size(); ++i) { - lx >>= 1; - ly >>= 1; - if (lx < 1) - lx = 1; - if (ly < 1) - ly = 1; - rasters[i] = TRaster32P(lx, ly); - sx = (double)lx / (double)ras2Lx; - sy = (double)ly / (double)ras2Ly; - rasters[i] = TRaster32P(lx, ly); + rasters[0] = ras2; + int ras2Lx = ras2->getLx(); + int ras2Ly = ras2->getLy(); + for (int i = 1; i < (int)rasters.size(); ++i) { + lx >>= 1; + ly >>= 1; + if (lx < 1) lx = 1; + if (ly < 1) ly = 1; + rasters[i] = TRaster32P(lx, ly); + sx = (double)lx / (double)ras2Lx; + sy = (double)ly / (double)ras2Ly; + rasters[i] = TRaster32P(lx, ly); #ifndef SCALE_BY_GLU - TRop::resample(rasters[i], ras2, TScale(sx, sy), resampleFilter); + TRop::resample(rasters[i], ras2, TScale(sx, sy), resampleFilter); #else - ras2->lock(); - gluScaleImage(GL_RGBA, ras->getLx(), ras->getLy(), GL_UNSIGNED_BYTE, ras2->getRawData(), - lx, ly, GL_UNSIGNED_BYTE, rasters[i]->getRawData()); - ras2->unlock(); + ras2->lock(); + gluScaleImage(GL_RGBA, ras->getLx(), ras->getLy(), GL_UNSIGNED_BYTE, + ras2->getRawData(), lx, ly, GL_UNSIGNED_BYTE, + rasters[i]->getRawData()); + ras2->unlock(); #endif - } + } } //----------------------------------------------------------------------------- -//Forse si potrebbe togliere l'ifdef ed usare QT +// Forse si potrebbe togliere l'ifdef ed usare QT #if defined(_WIN32) -TGlContext tglGetCurrentContext() -{ - return std::make_pair(wglGetCurrentDC(), wglGetCurrentContext()); +TGlContext tglGetCurrentContext() { + return std::make_pair(wglGetCurrentDC(), wglGetCurrentContext()); } -void tglMakeCurrent(TGlContext context) -{ - wglMakeCurrent(context.first, context.second); +void tglMakeCurrent(TGlContext context) { + wglMakeCurrent(context.first, context.second); } -void tglDoneCurrent(TGlContext) -{ - wglMakeCurrent(NULL, NULL); -} +void tglDoneCurrent(TGlContext) { wglMakeCurrent(NULL, NULL); } #elif defined(LINUX) || defined(__sgi) || defined(MACOSX) -TGlContext tglGetCurrentContext() -{ - return reinterpret_cast( - const_cast(QGLContext::currentContext())); +TGlContext tglGetCurrentContext() { + return reinterpret_cast( + const_cast(QGLContext::currentContext())); - // (Daniele) I'm not sure why QGLContext::currentContext() returns - // const. I think it shouldn't, and guess (hope) this is safe... + // (Daniele) I'm not sure why QGLContext::currentContext() returns + // const. I think it shouldn't, and guess (hope) this is safe... } -void tglMakeCurrent(TGlContext context) -{ - if (context) - reinterpret_cast(context)->makeCurrent(); - else - tglDoneCurrent(tglGetCurrentContext()); +void tglMakeCurrent(TGlContext context) { + if (context) + reinterpret_cast(context)->makeCurrent(); + else + tglDoneCurrent(tglGetCurrentContext()); } -void tglDoneCurrent(TGlContext context) -{ - if (context) - reinterpret_cast(context)->doneCurrent(); +void tglDoneCurrent(TGlContext context) { + if (context) reinterpret_cast(context)->doneCurrent(); } #else diff --git a/toonz/sources/common/tgl/tgldisplaylistsmanager.cpp b/toonz/sources/common/tgl/tgldisplaylistsmanager.cpp index 123ff91..d4e9181 100644 --- a/toonz/sources/common/tgl/tgldisplaylistsmanager.cpp +++ b/toonz/sources/common/tgl/tgldisplaylistsmanager.cpp @@ -12,91 +12,82 @@ // Local namespace - declarations //*********************************************************************************************** -namespace -{ +namespace { struct ProxyReference { - TGLDisplayListsProxy *m_proxy; - int m_refCount; + TGLDisplayListsProxy *m_proxy; + int m_refCount; - ProxyReference(TGLDisplayListsProxy *proxy) : m_proxy(proxy), m_refCount() {} + ProxyReference(TGLDisplayListsProxy *proxy) : m_proxy(proxy), m_refCount() {} }; -} // namespace +} // namespace //*********************************************************************************************** // Local namespace - globals //*********************************************************************************************** -namespace -{ +namespace { tcg::list m_proxies; std::map m_proxyIdsByContext; -} // namespace +} // namespace //*********************************************************************************************** // TGLDisplayListsManager implementation //*********************************************************************************************** -TGLDisplayListsManager *TGLDisplayListsManager::instance() -{ - static TGLDisplayListsManager theInstance; - return &theInstance; +TGLDisplayListsManager *TGLDisplayListsManager::instance() { + static TGLDisplayListsManager theInstance; + return &theInstance; } //----------------------------------------------------------------------------------- -int TGLDisplayListsManager::storeProxy(TGLDisplayListsProxy *proxy) -{ - return m_proxies.push_back(ProxyReference(proxy)); +int TGLDisplayListsManager::storeProxy(TGLDisplayListsProxy *proxy) { + return m_proxies.push_back(ProxyReference(proxy)); } //----------------------------------------------------------------------------------- -void TGLDisplayListsManager::attachContext(int dlSpaceId, TGlContext context) -{ - m_proxyIdsByContext.insert(std::make_pair(context, dlSpaceId)); - ++m_proxies[dlSpaceId].m_refCount; +void TGLDisplayListsManager::attachContext(int dlSpaceId, TGlContext context) { + m_proxyIdsByContext.insert(std::make_pair(context, dlSpaceId)); + ++m_proxies[dlSpaceId].m_refCount; } //----------------------------------------------------------------------------------- -void TGLDisplayListsManager::releaseContext(TGlContext context) -{ - std::map::iterator it = m_proxyIdsByContext.find(context); +void TGLDisplayListsManager::releaseContext(TGlContext context) { + std::map::iterator it = m_proxyIdsByContext.find(context); - assert(it != m_proxyIdsByContext.end()); - if (it == m_proxyIdsByContext.end()) - return; + assert(it != m_proxyIdsByContext.end()); + if (it == m_proxyIdsByContext.end()) return; - int dlSpaceId = it->second; - if (--m_proxies[dlSpaceId].m_refCount <= 0) { - // Notify observers first - observers_container::const_iterator ot, oEnd = observers().end(); - for (ot = observers().begin(); ot != oEnd; ++ot) - static_cast(*ot)->onDisplayListDestroyed(dlSpaceId); + int dlSpaceId = it->second; + if (--m_proxies[dlSpaceId].m_refCount <= 0) { + // Notify observers first + observers_container::const_iterator ot, oEnd = observers().end(); + for (ot = observers().begin(); ot != oEnd; ++ot) + static_cast(*ot)->onDisplayListDestroyed(dlSpaceId); - // Then, destroy stuff - delete m_proxies[dlSpaceId].m_proxy; - m_proxies.erase(dlSpaceId); - } + // Then, destroy stuff + delete m_proxies[dlSpaceId].m_proxy; + m_proxies.erase(dlSpaceId); + } - m_proxyIdsByContext.erase(it); + m_proxyIdsByContext.erase(it); } //----------------------------------------------------------------------------------- -int TGLDisplayListsManager::displayListsSpaceId(TGlContext context) -{ - std::map::iterator it = m_proxyIdsByContext.find(context); - return (it == m_proxyIdsByContext.end()) ? -1 : it->second; +int TGLDisplayListsManager::displayListsSpaceId(TGlContext context) { + std::map::iterator it = m_proxyIdsByContext.find(context); + return (it == m_proxyIdsByContext.end()) ? -1 : it->second; } //----------------------------------------------------------------------------------- -TGLDisplayListsProxy *TGLDisplayListsManager::dlProxy(int dlSpaceId) -{ - return m_proxies[dlSpaceId].m_proxy; +TGLDisplayListsProxy *TGLDisplayListsManager::dlProxy(int dlSpaceId) { + return m_proxies[dlSpaceId].m_proxy; } diff --git a/toonz/sources/common/tgl/tstencilcontrol.cpp b/toonz/sources/common/tgl/tstencilcontrol.cpp index fae7e40..efe3bc8 100644 --- a/toonz/sources/common/tgl/tstencilcontrol.cpp +++ b/toonz/sources/common/tgl/tstencilcontrol.cpp @@ -9,369 +9,358 @@ //----------------------------------------------------------------------------------------- -namespace -{ +namespace { -//singleton -class StencilControlManager -{ +// singleton +class StencilControlManager { + QThreadStorage m_storage; - QThreadStorage m_storage; - - StencilControlManager() {} + StencilControlManager() {} public: - static StencilControlManager *instance() - { - static StencilControlManager theInstance; - return &theInstance; - } - - TStencilControl *getCurrentStencilControl() - { - if (!m_storage.hasLocalData()) { - m_storage.setLocalData(new TStencilControl); - } - - return m_storage.localData(); - } - - ~StencilControlManager() - { - } + static StencilControlManager *instance() { + static StencilControlManager theInstance; + return &theInstance; + } + + TStencilControl *getCurrentStencilControl() { + if (!m_storage.hasLocalData()) { + m_storage.setLocalData(new TStencilControl); + } + + return m_storage.localData(); + } + + ~StencilControlManager() {} }; -} //Local namepace +} // Local namepace //----------------------------------------------------------------------------------------- -class TStencilControl::Imp -{ +class TStencilControl::Imp { public: - int m_stencilBitCount; - int m_pushCount; - int m_currentWriting; //current stencil bit plane. - //0 is the first bit plane ; -1 menas no stencil mask is writing + int m_stencilBitCount; + int m_pushCount; + int m_currentWriting; // current stencil bit plane. + // 0 is the first bit plane ; -1 menas no stencil mask is writing - int m_virtualState; -//the state of the (eventually virtual) top mask. -//A mask is virtual if overflows stencil buffer -//0 is closed and disabled, 1 closed and enabled and 2 is opened + int m_virtualState; +// the state of the (eventually virtual) top mask. +// A mask is virtual if overflows stencil buffer +// 0 is closed and disabled, 1 closed and enabled and 2 is opened #ifdef _DEBUG - std::stack fullState; + std::stack fullState; // state of each mask in the stack (except top mask). // 'true' means opend; 'false' means close and enabled // Used only for assert #endif - unsigned char m_writingMask; //bit mask. The i-th bit=1 iff the i-th mask is opened to write - unsigned char m_drawOnScreenMask; //bitmsk.The ith bit=1 iff the ith mask WRITE also ON SCREEN WHEN WRITE ON STENCIL BIT PLANE - unsigned char m_enabledMask; //bit mask. The i-th bit=1 iff the i-th mask is enabled - unsigned char m_inOrOutMask; //bit mask. The i-th bit=1 iff the i-th mask is inside - unsigned char m_drawOnlyOnceMask; - - Imp(); - - void updateOpenGlState(); - - void pushMask(); - // make a new stencil plane the current one. - // if there is no plane available, increase a counter and does not push (virtual masks) - // So the same number of pop has no effect - - void popMask(); - // assert if the stencil stack contains only 0 - - void beginMask(DrawMode drawMode); - // clear the current stencil plane; start writing to it - // if drawOnScreen is not 0, it writes also to the color buffer (or stencil plane if another - // mask is open). If drawOnScreen is 2, it drows only once (by stencil buffer) - - void endMask(); - // end writing to the stencil plane. - - void enableMask(MaskType maskType); - void disableMask(); - // between enableMask()/disableMask() drawing is filtered by the values of the current - // stencil plane - // n.b. enableMask()/disableMask() can be nidified. Between the inner pair writing is enabled - // according to the AND of all of them + unsigned char m_writingMask; // bit mask. The i-th bit=1 iff the i-th mask is + // opened to write + unsigned char m_drawOnScreenMask; // bitmsk.The ith bit=1 iff the ith mask + // WRITE also ON SCREEN WHEN WRITE ON + // STENCIL BIT PLANE + unsigned char + m_enabledMask; // bit mask. The i-th bit=1 iff the i-th mask is enabled + unsigned char + m_inOrOutMask; // bit mask. The i-th bit=1 iff the i-th mask is inside + unsigned char m_drawOnlyOnceMask; + + Imp(); + + void updateOpenGlState(); + + void pushMask(); + // make a new stencil plane the current one. + // if there is no plane available, increase a counter and does not push + // (virtual masks) + // So the same number of pop has no effect + + void popMask(); + // assert if the stencil stack contains only 0 + + void beginMask(DrawMode drawMode); + // clear the current stencil plane; start writing to it + // if drawOnScreen is not 0, it writes also to the color buffer (or stencil + // plane if another + // mask is open). If drawOnScreen is 2, it drows only once (by stencil buffer) + + void endMask(); + // end writing to the stencil plane. + + void enableMask(MaskType maskType); + void disableMask(); + // between enableMask()/disableMask() drawing is filtered by the values of the + // current + // stencil plane + // n.b. enableMask()/disableMask() can be nidified. Between the inner pair + // writing is enabled + // according to the AND of all of them }; //----------------------------------------------------------------------------------------- TStencilControl::Imp::Imp() - : m_stencilBitCount(0), m_pushCount(1), m_currentWriting(-1), m_enabledMask(0), m_writingMask(0), m_inOrOutMask(0), m_drawOnScreenMask(0), m_drawOnlyOnceMask(0), m_virtualState(0) -{ - glGetIntegerv(GL_STENCIL_BITS, (GLint *)&m_stencilBitCount); - - glStencilMask(0xFFFFFFFF); - //glClearStencil(0); - glClear(GL_STENCIL_BUFFER_BIT); + : m_stencilBitCount(0) + , m_pushCount(1) + , m_currentWriting(-1) + , m_enabledMask(0) + , m_writingMask(0) + , m_inOrOutMask(0) + , m_drawOnScreenMask(0) + , m_drawOnlyOnceMask(0) + , m_virtualState(0) { + glGetIntegerv(GL_STENCIL_BITS, (GLint *)&m_stencilBitCount); + + glStencilMask(0xFFFFFFFF); + // glClearStencil(0); + glClear(GL_STENCIL_BUFFER_BIT); } //--------------------------------------------------------- -TStencilControl *TStencilControl::instance() -{ - StencilControlManager *instance = StencilControlManager::instance(); - return instance->getCurrentStencilControl(); +TStencilControl *TStencilControl::instance() { + StencilControlManager *instance = StencilControlManager::instance(); + return instance->getCurrentStencilControl(); } //--------------------------------------------------------- -TStencilControl::TStencilControl() - : m_imp(new Imp) -{ -} +TStencilControl::TStencilControl() : m_imp(new Imp) {} //--------------------------------------------------------- -TStencilControl::~TStencilControl() -{ -} +TStencilControl::~TStencilControl() {} //--------------------------------------------------------- -void TStencilControl::Imp::updateOpenGlState() -{ - if (m_currentWriting >= 0) { //writing on stencil buffer - unsigned char currentWritingMask = 1 << m_currentWriting; - - bool drawOnlyOnce = (currentWritingMask & m_drawOnlyOnceMask) != 0; - - if (currentWritingMask & m_drawOnScreenMask) { - unsigned char lastWritingMask; - int lastWriting = m_currentWriting - 1; - for (; lastWriting >= 0; lastWriting--) { - lastWritingMask = 1 << lastWriting; - if ((lastWritingMask & m_writingMask) == lastWritingMask) - break; - } - if (lastWriting < 0) { - //glColorMask(1,1,1,1); - - if (drawOnlyOnce) - m_enabledMask |= currentWritingMask; - else - m_enabledMask &= ~currentWritingMask; - } else { - tglMultColorMask(0, 0, 0, 0); - //glDrawBuffer(GL_NONE); - - drawOnlyOnce = false; //essendo solo un'effetto visivo, se sto scrivendo su una maschera e non a schermo, e' inutile - currentWritingMask |= lastWritingMask; - } - } else - tglMultColorMask(0, 0, 0, 0); - //glDrawBuffer(GL_NONE); - - glStencilMask(currentWritingMask); - - if (drawOnlyOnce) { - glStencilFunc(GL_EQUAL, m_inOrOutMask, m_enabledMask); - glStencilOp(GL_KEEP, GL_INVERT, GL_INVERT); - } else { - glStencilFunc(GL_EQUAL, currentWritingMask | m_inOrOutMask, m_enabledMask); - glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE); - } - - } else { //writing on screen buffer - glStencilMask(0xFFFFFFFF); - glStencilFunc(GL_EQUAL, m_inOrOutMask, m_enabledMask); - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - //glColorMask(1,1,1,1); - } - - if (!m_enabledMask && m_currentWriting < 0) - glDisable(GL_STENCIL_TEST); - else - glEnable(GL_STENCIL_TEST); +void TStencilControl::Imp::updateOpenGlState() { + if (m_currentWriting >= 0) { // writing on stencil buffer + unsigned char currentWritingMask = 1 << m_currentWriting; + + bool drawOnlyOnce = (currentWritingMask & m_drawOnlyOnceMask) != 0; + + if (currentWritingMask & m_drawOnScreenMask) { + unsigned char lastWritingMask; + int lastWriting = m_currentWriting - 1; + for (; lastWriting >= 0; lastWriting--) { + lastWritingMask = 1 << lastWriting; + if ((lastWritingMask & m_writingMask) == lastWritingMask) break; + } + if (lastWriting < 0) { + // glColorMask(1,1,1,1); + + if (drawOnlyOnce) + m_enabledMask |= currentWritingMask; + else + m_enabledMask &= ~currentWritingMask; + } else { + tglMultColorMask(0, 0, 0, 0); + // glDrawBuffer(GL_NONE); + + drawOnlyOnce = false; // essendo solo un'effetto visivo, se sto + // scrivendo su una maschera e non a schermo, e' + // inutile + currentWritingMask |= lastWritingMask; + } + } else + tglMultColorMask(0, 0, 0, 0); + // glDrawBuffer(GL_NONE); + + glStencilMask(currentWritingMask); + + if (drawOnlyOnce) { + glStencilFunc(GL_EQUAL, m_inOrOutMask, m_enabledMask); + glStencilOp(GL_KEEP, GL_INVERT, GL_INVERT); + } else { + glStencilFunc(GL_EQUAL, currentWritingMask | m_inOrOutMask, + m_enabledMask); + glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE); + } + + } else { // writing on screen buffer + glStencilMask(0xFFFFFFFF); + glStencilFunc(GL_EQUAL, m_inOrOutMask, m_enabledMask); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + // glColorMask(1,1,1,1); + } + + if (!m_enabledMask && m_currentWriting < 0) + glDisable(GL_STENCIL_TEST); + else + glEnable(GL_STENCIL_TEST); } //--------------------------------------------------------- -void TStencilControl::Imp::pushMask() -{ - m_pushCount++; -} +void TStencilControl::Imp::pushMask() { m_pushCount++; } //--------------------------------------------------------- -void TStencilControl::Imp::beginMask(DrawMode drawMode) -{ - m_currentWriting = m_pushCount - 1; - unsigned char currentMask = 1 << m_currentWriting; - - m_writingMask |= currentMask; - - if (drawMode == DRAW_ALSO_ON_SCREEN) { - m_drawOnScreenMask |= currentMask; - } else if (drawMode == DRAW_ON_SCREEN_ONLY_ONCE) { - m_drawOnScreenMask |= currentMask; - m_drawOnlyOnceMask |= currentMask; - } else { - m_drawOnScreenMask &= ~currentMask; - m_drawOnlyOnceMask &= ~currentMask; - } - - glEnable(GL_STENCIL_TEST); - glStencilMask(currentMask); // enabled to modify only current bitPlane - glClear(GL_STENCIL_BUFFER_BIT); // and clear it - updateOpenGlState(); +void TStencilControl::Imp::beginMask(DrawMode drawMode) { + m_currentWriting = m_pushCount - 1; + unsigned char currentMask = 1 << m_currentWriting; + + m_writingMask |= currentMask; + + if (drawMode == DRAW_ALSO_ON_SCREEN) { + m_drawOnScreenMask |= currentMask; + } else if (drawMode == DRAW_ON_SCREEN_ONLY_ONCE) { + m_drawOnScreenMask |= currentMask; + m_drawOnlyOnceMask |= currentMask; + } else { + m_drawOnScreenMask &= ~currentMask; + m_drawOnlyOnceMask &= ~currentMask; + } + + glEnable(GL_STENCIL_TEST); + glStencilMask(currentMask); // enabled to modify only current bitPlane + glClear(GL_STENCIL_BUFFER_BIT); // and clear it + updateOpenGlState(); } //--------------------------------------------------------- -void TStencilControl::Imp::endMask() -{ - assert(m_pushCount - 1 == m_currentWriting); +void TStencilControl::Imp::endMask() { + assert(m_pushCount - 1 == m_currentWriting); - unsigned char currentMask = 1 << (m_pushCount - 1); + unsigned char currentMask = 1 << (m_pushCount - 1); - m_writingMask &= ~currentMask; //stop writing - m_enabledMask &= ~currentMask; - m_drawOnScreenMask &= ~currentMask; - m_drawOnlyOnceMask &= ~currentMask; + m_writingMask &= ~currentMask; // stop writing + m_enabledMask &= ~currentMask; + m_drawOnScreenMask &= ~currentMask; + m_drawOnlyOnceMask &= ~currentMask; - //---------------------------------------------------------- + //---------------------------------------------------------- - m_currentWriting--; - for (; m_currentWriting >= 0; m_currentWriting--) { - unsigned char currentWritingMask = 1 << m_currentWriting; - if ((currentWritingMask & m_writingMask) == currentWritingMask) - break; - } + m_currentWriting--; + for (; m_currentWriting >= 0; m_currentWriting--) { + unsigned char currentWritingMask = 1 << m_currentWriting; + if ((currentWritingMask & m_writingMask) == currentWritingMask) break; + } - updateOpenGlState(); + updateOpenGlState(); } //--------------------------------------------------------- -void TStencilControl::Imp::enableMask(MaskType maskType) -{ - unsigned char currentMask = 1 << (m_pushCount - 1); +void TStencilControl::Imp::enableMask(MaskType maskType) { + unsigned char currentMask = 1 << (m_pushCount - 1); - if ((m_enabledMask & currentMask) == 0) - glPushAttrib(GL_ALL_ATTRIB_BITS); + if ((m_enabledMask & currentMask) == 0) glPushAttrib(GL_ALL_ATTRIB_BITS); - m_enabledMask |= currentMask; + m_enabledMask |= currentMask; - assert(maskType == SHOW_INSIDE || maskType == SHOW_OUTSIDE); + assert(maskType == SHOW_INSIDE || maskType == SHOW_OUTSIDE); - if (maskType == SHOW_INSIDE) - m_inOrOutMask |= currentMask; - else - m_inOrOutMask &= ~currentMask; + if (maskType == SHOW_INSIDE) + m_inOrOutMask |= currentMask; + else + m_inOrOutMask &= ~currentMask; - updateOpenGlState(); + updateOpenGlState(); } //--------------------------------------------------------- -void TStencilControl::Imp::disableMask() -{ - unsigned char currentMask = 1 << (m_pushCount - 1); +void TStencilControl::Imp::disableMask() { + unsigned char currentMask = 1 << (m_pushCount - 1); - m_enabledMask &= ~currentMask; - m_inOrOutMask &= ~currentMask; + m_enabledMask &= ~currentMask; + m_inOrOutMask &= ~currentMask; - updateOpenGlState(); - glPopAttrib(); + updateOpenGlState(); + glPopAttrib(); } //--------------------------------------------------------- -void TStencilControl::Imp::popMask() -{ - --m_pushCount; - assert(m_pushCount > 0); //there is at least one mask in the stack +void TStencilControl::Imp::popMask() { + --m_pushCount; + assert(m_pushCount > 0); // there is at least one mask in the stack } //--------------------------------------------------------- //--------------------------------------------------------- -//questo forse e' un po' brutto: -//La maschera e' chiusa. -//Se e' abilitata, open = push+open -//Se e' disabilitata, open = open +// questo forse e' un po' brutto: +// La maschera e' chiusa. +// Se e' abilitata, open = push+open +// Se e' disabilitata, open = open -void TStencilControl::beginMask(DrawMode drawMode) -{ - glPushAttrib(GL_ALL_ATTRIB_BITS); +void TStencilControl::beginMask(DrawMode drawMode) { + glPushAttrib(GL_ALL_ATTRIB_BITS); - if (m_imp->m_virtualState) //opened or enabled - { + if (m_imp->m_virtualState) // opened or enabled + { #ifdef _DEBUG - m_imp->fullState.push(m_imp->m_virtualState == 2); + m_imp->fullState.push(m_imp->m_virtualState == 2); #endif - m_imp->pushMask(); - } + m_imp->pushMask(); + } - m_imp->m_virtualState = 2; //opened + m_imp->m_virtualState = 2; // opened - if (m_imp->m_pushCount <= m_imp->m_stencilBitCount) - m_imp->beginMask(drawMode); + if (m_imp->m_pushCount <= m_imp->m_stencilBitCount) + m_imp->beginMask(drawMode); } //--------------------------------------------------------- -void TStencilControl::endMask() -{ - if (!m_imp->m_virtualState) //closed and disabled - { - m_imp->popMask(); +void TStencilControl::endMask() { + if (!m_imp->m_virtualState) // closed and disabled + { + m_imp->popMask(); #ifdef _DEBUG - assert(m_imp->fullState.top()); //the state before last push must be opened - m_imp->fullState.pop(); + assert(m_imp->fullState.top()); // the state before last push must be + // opened + m_imp->fullState.pop(); #endif - } + } - assert(m_imp->m_virtualState != 1); //yet closed + assert(m_imp->m_virtualState != 1); // yet closed - m_imp->m_virtualState = 0; + m_imp->m_virtualState = 0; - if (m_imp->m_pushCount <= m_imp->m_stencilBitCount) - m_imp->endMask(); + if (m_imp->m_pushCount <= m_imp->m_stencilBitCount) m_imp->endMask(); - glPopAttrib(); + glPopAttrib(); } //--------------------------------------------------------- -void TStencilControl::enableMask(MaskType maskType) -{ - assert(m_imp->m_virtualState != 2); //cannot enable an opened mask +void TStencilControl::enableMask(MaskType maskType) { + assert(m_imp->m_virtualState != 2); // cannot enable an opened mask - m_imp->m_virtualState = 1; //enabled + m_imp->m_virtualState = 1; // enabled - if (m_imp->m_pushCount <= m_imp->m_stencilBitCount) - m_imp->enableMask(maskType); + if (m_imp->m_pushCount <= m_imp->m_stencilBitCount) + m_imp->enableMask(maskType); } //--------------------------------------------------------- -void TStencilControl::disableMask() -{ - assert(m_imp->m_virtualState != 2); //cannot disable an opened mask +void TStencilControl::disableMask() { + assert(m_imp->m_virtualState != 2); // cannot disable an opened mask - if (!m_imp->m_virtualState) //closed and disabled - { - m_imp->popMask(); + if (!m_imp->m_virtualState) // closed and disabled + { + m_imp->popMask(); #ifdef _DEBUG - assert(!m_imp->fullState.top()); //the state before last push must be enabled - m_imp->fullState.pop(); + assert( + !m_imp->fullState.top()); // the state before last push must be enabled + m_imp->fullState.pop(); #endif - } + } - m_imp->m_virtualState = 0; //close and disabled + m_imp->m_virtualState = 0; // close and disabled - if (m_imp->m_pushCount <= m_imp->m_stencilBitCount) - m_imp->disableMask(); + if (m_imp->m_pushCount <= m_imp->m_stencilBitCount) m_imp->disableMask(); } //--------------------------------------------------------- diff --git a/toonz/sources/common/tgraphics.cpp b/toonz/sources/common/tgraphics.cpp index 3868f59..9772b33 100644 --- a/toonz/sources/common/tgraphics.cpp +++ b/toonz/sources/common/tgraphics.cpp @@ -7,307 +7,267 @@ extern "C" { #include "tvis.h" } -TGraphics::TGraphics(_TWIDGET *_gf, - int ras_x0, int ras_y0, - int ras_x1, int ras_y1, - int gf_x0, int gf_y0, - int gf_x1, int gf_y1, - int zoom_level) - : gf(_gf), currentPoint(0, 0), gfRegion(gf_x0, gf_y0, gf_x1, gf_y1), rasterRegion(ras_x0 - 1, ras_y0 - 1, ras_x1 + 1, ras_y1 + 1) - //, rasterRegion(ras_x0,ras_y0,ras_x1,ras_y1) - , - zoomFactor(1), pixelSize(1) -{ - double dx, dy; - int blx, bly; - - if (zoom_level > 0) - zoomFactor = 1 << zoom_level; - else if (zoom_level < 0) - zoomFactor = 1.0 / (1 << -zoom_level); - pixelSize = 1.0 / zoomFactor; - - blx = ras_x0 - gf_x0 / zoomFactor; - bly = ras_y0 - gf_y0 / zoomFactor; - dx = 0.5 - blx; - dy = 0.5 - bly; - - GfPushMatrix(gf); - GfTranslate(gf, -0.5, -0.5); - GfScale(gf, zoomFactor, zoomFactor); - GfTranslate(gf, dx, dy); +TGraphics::TGraphics(_TWIDGET *_gf, int ras_x0, int ras_y0, int ras_x1, + int ras_y1, int gf_x0, int gf_y0, int gf_x1, int gf_y1, + int zoom_level) + : gf(_gf) + , currentPoint(0, 0) + , gfRegion(gf_x0, gf_y0, gf_x1, gf_y1) + , rasterRegion(ras_x0 - 1, ras_y0 - 1, ras_x1 + 1, ras_y1 + 1) + //, rasterRegion(ras_x0,ras_y0,ras_x1,ras_y1) + , zoomFactor(1) + , pixelSize(1) { + double dx, dy; + int blx, bly; + + if (zoom_level > 0) + zoomFactor = 1 << zoom_level; + else if (zoom_level < 0) + zoomFactor = 1.0 / (1 << -zoom_level); + pixelSize = 1.0 / zoomFactor; + + blx = ras_x0 - gf_x0 / zoomFactor; + bly = ras_y0 - gf_y0 / zoomFactor; + dx = 0.5 - blx; + dy = 0.5 - bly; + + GfPushMatrix(gf); + GfTranslate(gf, -0.5, -0.5); + GfScale(gf, zoomFactor, zoomFactor); + GfTranslate(gf, dx, dy); } //--------------------------------------------------- -TGraphics::~TGraphics() -{ - GfPopMatrix(gf); -} +TGraphics::~TGraphics() { GfPopMatrix(gf); } //--------------------------------------------------- -void TGraphics::setColor(int r, int g, int b) -{ - _r = r; - _g = g; - _b = b; - GfCpack(gf, r, g, b); +void TGraphics::setColor(int r, int g, int b) { + _r = r; + _g = g; + _b = b; + GfCpack(gf, r, g, b); } //--------------------------------------------------- -void TGraphics::drawLine(const TPointI &a, const TPointI &b) -{ - if (a.x < rasterRegion.x0 && b.x < rasterRegion.x0 || - a.x > rasterRegion.x1 && b.x > rasterRegion.x1 || - a.y < rasterRegion.y0 && b.y < rasterRegion.y0 || - a.y > rasterRegion.y1 && b.y > rasterRegion.y1) - return; - int v[2]; - GfBgnLine(gf); - v[0] = a.x; - v[1] = a.y; - GfV2i(gf, v); - v[0] = b.x; - v[1] = b.y; - GfV2i(gf, v); - GfEndLine(gf); +void TGraphics::drawLine(const TPointI &a, const TPointI &b) { + if (a.x < rasterRegion.x0 && b.x < rasterRegion.x0 || + a.x > rasterRegion.x1 && b.x > rasterRegion.x1 || + a.y < rasterRegion.y0 && b.y < rasterRegion.y0 || + a.y > rasterRegion.y1 && b.y > rasterRegion.y1) + return; + int v[2]; + GfBgnLine(gf); + v[0] = a.x; + v[1] = a.y; + GfV2i(gf, v); + v[0] = b.x; + v[1] = b.y; + GfV2i(gf, v); + GfEndLine(gf); } //--------------------------------------------------- -void TGraphics::drawLine(const TPointD &a, const TPointD &b) -{ - if (a.x < rasterRegion.x0 && b.x < rasterRegion.x0 || - a.x > rasterRegion.x1 && b.x > rasterRegion.x1 || - a.y < rasterRegion.y0 && b.y < rasterRegion.y0 || - a.y > rasterRegion.y1 && b.y > rasterRegion.y1) - return; - double v[2]; - GfBgnLine(gf); - v[0] = a.x; - v[1] = a.y; - GfV2d(gf, v); - v[0] = b.x; - v[1] = b.y; - GfV2d(gf, v); - GfEndLine(gf); +void TGraphics::drawLine(const TPointD &a, const TPointD &b) { + if (a.x < rasterRegion.x0 && b.x < rasterRegion.x0 || + a.x > rasterRegion.x1 && b.x > rasterRegion.x1 || + a.y < rasterRegion.y0 && b.y < rasterRegion.y0 || + a.y > rasterRegion.y1 && b.y > rasterRegion.y1) + return; + double v[2]; + GfBgnLine(gf); + v[0] = a.x; + v[1] = a.y; + GfV2d(gf, v); + v[0] = b.x; + v[1] = b.y; + GfV2d(gf, v); + GfEndLine(gf); } //--------------------------------------------------- -void TGraphics::beginPolygon() -{ - GfBgnPolygon(gf); -} +void TGraphics::beginPolygon() { GfBgnPolygon(gf); } //--------------------------------------------------- -void TGraphics::endPolygon() -{ - GfEndPolygon(gf); -} +void TGraphics::endPolygon() { GfEndPolygon(gf); } //--------------------------------------------------- -void TGraphics::beginLine() -{ - GfBgnLine(gf); -} +void TGraphics::beginLine() { GfBgnLine(gf); } //--------------------------------------------------- -void TGraphics::endLine() -{ - GfEndLine(gf); -} +void TGraphics::endLine() { GfEndLine(gf); } //--------------------------------------------------- -void TGraphics::vertex(const TPointI &a) -{ - int v[2]; - v[0] = a.x; - v[1] = a.y; - GfV2i(gf, v); +void TGraphics::vertex(const TPointI &a) { + int v[2]; + v[0] = a.x; + v[1] = a.y; + GfV2i(gf, v); } //--------------------------------------------------- -void TGraphics::vertex(const TPointD &a) -{ - double v[2]; - v[0] = a.x; - v[1] = a.y; - GfV2d(gf, v); +void TGraphics::vertex(const TPointD &a) { + double v[2]; + v[0] = a.x; + v[1] = a.y; + GfV2d(gf, v); } //--------------------------------------------------- -void TGraphics::drawRect(const TPointI &a, const TPointI &b) -{ - GfRecti(gf, a.x, a.y, b.x, b.y); +void TGraphics::drawRect(const TPointI &a, const TPointI &b) { + GfRecti(gf, a.x, a.y, b.x, b.y); } //--------------------------------------------------- -void TGraphics::drawRect(const TPointD &a, const TPointD &b) -{ - GfRect(gf, a.x, a.y, b.x, b.y); +void TGraphics::drawRect(const TPointD &a, const TPointD &b) { + GfRect(gf, a.x, a.y, b.x, b.y); } //--------------------------------------------------- -void TGraphics::drawRect(const TRectI &rect) -{ - GfRecti(gf, rect.x0, rect.y0, rect.x1, rect.y1); +void TGraphics::drawRect(const TRectI &rect) { + GfRecti(gf, rect.x0, rect.y0, rect.x1, rect.y1); } //--------------------------------------------------- -void TGraphics::drawRect(const TRectD &rect) -{ - GfRect(gf, rect.x0, rect.y0, rect.x1, rect.y1); +void TGraphics::drawRect(const TRectD &rect) { + GfRect(gf, rect.x0, rect.y0, rect.x1, rect.y1); } //--------------------------------------------------- -void TGraphics::drawArc(const TBezierArc &arc) -{ - int n = 50; - beginLine(); - for (int i = 0; i <= n; i++) - vertex(arc.getPoint((double)i / (double)n)); - endLine(); +void TGraphics::drawArc(const TBezierArc &arc) { + int n = 50; + beginLine(); + for (int i = 0; i <= n; i++) vertex(arc.getPoint((double)i / (double)n)); + endLine(); } //--------------------------------------------------- -void TGraphics::drawArc(const TCubicCurve &arc) -{ - int n = 80; - beginLine(); - for (int i = 0; i <= n; i++) - vertex(arc.getPoint((double)i / (double)n)); - endLine(); +void TGraphics::drawArc(const TCubicCurve &arc) { + int n = 80; + beginLine(); + for (int i = 0; i <= n; i++) vertex(arc.getPoint((double)i / (double)n)); + endLine(); } //--------------------------------------------------- void TGraphics::drawArcTo(const TPointD &d1, const TPointD &d2, - const TPointD &d3) -{ - TPointD oldPoint = currentPoint; - currentPoint += d1 + d2 + d3; - drawArc(TBezierArc(oldPoint, oldPoint + d1, oldPoint + d1 + d2, currentPoint)); + const TPointD &d3) { + TPointD oldPoint = currentPoint; + currentPoint += d1 + d2 + d3; + drawArc( + TBezierArc(oldPoint, oldPoint + d1, oldPoint + d1 + d2, currentPoint)); } //--------------------------------------------------- -void TGraphics::drawDiamond(const TPointD &p, double r) -{ - beginPolygon(); - vertex(p + TPointD(r, 0)); - vertex(p + TPointD(0, r)); - vertex(p + TPointD(-r, 0)); - vertex(p + TPointD(0, -r)); - endPolygon(); +void TGraphics::drawDiamond(const TPointD &p, double r) { + beginPolygon(); + vertex(p + TPointD(r, 0)); + vertex(p + TPointD(0, r)); + vertex(p + TPointD(-r, 0)); + vertex(p + TPointD(0, -r)); + endPolygon(); } //--------------------------------------------------- -void TGraphics::drawCross(const TPointD &p, double r) -{ - drawLine(p - TPointD(r, r), p + TPointD(r, r)); - drawLine(p - TPointD(-r, r), p + TPointD(-r, r)); +void TGraphics::drawCross(const TPointD &p, double r) { + drawLine(p - TPointD(r, r), p + TPointD(r, r)); + drawLine(p - TPointD(-r, r), p + TPointD(-r, r)); } //--------------------------------------------------- -void TGraphics::drawSquare(const TPointD &p, double r) -{ - beginLine(); - vertex(p + TPointD(-r, -r)); - vertex(p + TPointD(-r, r)); - vertex(p + TPointD(r, r)); - vertex(p + TPointD(r, -r)); - vertex(p + TPointD(-r, -r)); - endLine(); +void TGraphics::drawSquare(const TPointD &p, double r) { + beginLine(); + vertex(p + TPointD(-r, -r)); + vertex(p + TPointD(-r, r)); + vertex(p + TPointD(r, r)); + vertex(p + TPointD(r, -r)); + vertex(p + TPointD(-r, -r)); + endLine(); } //--------------------------------------------------- -void TGraphics::drawArc( - const TPointD &p0, - const TPointD &p1, - const TPointD &p2) -{ - TRectD rect = convert(rasterRegion.enlarge(+10)); - //TRectD rect(rasterRegion.x0, rasterRegion.y0, rasterRegion.x1, rasterRegion.y1); - TRectD bBox = boundingBox(p0, p1, p2); - - if (!rect.overlaps(bBox)) { - /* - unsigned char tmp_r = _r; - unsigned char tmp_g = _g; - unsigned char tmp_b = _b; - setColor(100,100,100); - drawRect(bBox); - drawLine(TLineD(bBox.x0, bBox.y0, bBox.x1, bBox.y1)); - drawLine(TLineD(bBox.x0, bBox.y1, bBox.x1, bBox.y0)); - setColor(tmp_r, tmp_g, tmp_b); - */ - return; - } - - double threshold = pixelSize * 0.125; - - TPointD v = p2 - p0; - TPointD u = p1 - p0; - TPointD r = rotate90(v); - - double sqr_tsh = (threshold * threshold) * (v * v); - double dist = r * u; - - if ((dist * dist) > sqr_tsh) { - TPointD l1 = 0.5 * (p0 + p1); - TPointD r1 = 0.5 * (p1 + p2); - TPointD l2 = 0.5 * (l1 + r1); - drawArc(p0, l1, l2); - drawArc(l2, r1, p2); - } else { - beginLine(); - vertex(p0); - vertex(p2); - endLine(); - } +void TGraphics::drawArc(const TPointD &p0, const TPointD &p1, + const TPointD &p2) { + TRectD rect = convert(rasterRegion.enlarge(+10)); + // TRectD rect(rasterRegion.x0, rasterRegion.y0, rasterRegion.x1, + // rasterRegion.y1); + TRectD bBox = boundingBox(p0, p1, p2); + + if (!rect.overlaps(bBox)) { + /* +unsigned char tmp_r = _r; +unsigned char tmp_g = _g; +unsigned char tmp_b = _b; +setColor(100,100,100); +drawRect(bBox); +drawLine(TLineD(bBox.x0, bBox.y0, bBox.x1, bBox.y1)); +drawLine(TLineD(bBox.x0, bBox.y1, bBox.x1, bBox.y0)); +setColor(tmp_r, tmp_g, tmp_b); +*/ + return; + } + + double threshold = pixelSize * 0.125; + + TPointD v = p2 - p0; + TPointD u = p1 - p0; + TPointD r = rotate90(v); + + double sqr_tsh = (threshold * threshold) * (v * v); + double dist = r * u; + + if ((dist * dist) > sqr_tsh) { + TPointD l1 = 0.5 * (p0 + p1); + TPointD r1 = 0.5 * (p1 + p2); + TPointD l2 = 0.5 * (l1 + r1); + drawArc(p0, l1, l2); + drawArc(l2, r1, p2); + } else { + beginLine(); + vertex(p0); + vertex(p2); + endLine(); + } } //--------------------------------------------------- -void TGraphics::drawCircle(TPointD p, double radius) -{ - GfCirc(gf, p.x, p.y, radius); +void TGraphics::drawCircle(TPointD p, double radius) { + GfCirc(gf, p.x, p.y, radius); } //--------------------------------------------------- -void TGraphics::fillCircle(TPointD p, double radius) -{ - GfCircf(gf, p.x, p.y, radius); +void TGraphics::fillCircle(TPointD p, double radius) { + GfCircf(gf, p.x, p.y, radius); } //--------------------------------------------------- -void TGraphics::rectWrap(int wrap_pixels) -{ - GfRectWrap(gf, wrap_pixels); -} +void TGraphics::rectWrap(int wrap_pixels) { GfRectWrap(gf, wrap_pixels); } //--------------------------------------------------- -void TGraphics::rectWrite(int x0, int y0, int x1, int y1, void *buffer) -{ - GfRectWrite(gf, x0, y0, x1, y1, buffer); +void TGraphics::rectWrite(int x0, int y0, int x1, int y1, void *buffer) { + GfRectWrite(gf, x0, y0, x1, y1, buffer); } diff --git a/toonz/sources/common/tiio/bmp/filebmp.c b/toonz/sources/common/tiio/bmp/filebmp.c index 006c9fc..7a75cd9 100644 --- a/toonz/sources/common/tiio/bmp/filebmp.c +++ b/toonz/sources/common/tiio/bmp/filebmp.c @@ -40,47 +40,52 @@ #define BMP_RMAP(x) (x & 0xe0) | ((x & 0xe0) >> 3) | ((x & 0xc0) >> 6) #define BMP_GMAP(x) ((x & 0x1c) << 3) | (x & 0x1c) | ((x & 0x18) >> 3) -#define BMP_BMAP(x) ((x & 0x03) << 6) | ((x & 0x03) << 4) | ((x & 0x03) << 2) | (x & 0x03) - -#define BMP_RMAP16(x) ((x & 0xc0) << 0) | ((x & 0xc0) >> 2) | ((x & 0xc0) >> 4) | ((x & 0xc0) >> 6) -#define BMP_GMAP16(x) ((x & 0x60) << 1) | ((x & 0x60) >> 1) | ((x & 0x60) >> 3) | ((x & 0x60) >> 5) -#define BMP_BMAP16(x) ((x & 0x30) << 2) | ((x & 0x30) << 0) | ((x & 0x30) >> 2) | ((x & 0x30) >> 4) - -#define BMP_CUT(a, b, c) \ - { \ - if (a < b) \ - a = b; \ - else if (a > c) \ - a = c; \ - } - -#define BMP_REDUCE_COLORS(r, g, b) ((r & 0xe0) | ((g & 0xe0) >> 3) | ((b & 0xc0) >> 6)) - -#define BMP_ADD_ERROR(pix, weight) \ - { \ - tmp = (pix).r + ((r1 * weight) >> 4); \ - BMP_CUT(tmp, 0, 255); \ - (pix).r = tmp; \ - tmp = (pix).g + ((g1 * weight) >> 4); \ - BMP_CUT(tmp, 0, 255); \ - (pix).g = tmp; \ - tmp = (pix).b + ((b1 * weight) >> 4); \ - BMP_CUT(tmp, 0, 255); \ - (pix).b = tmp; \ - } - -#define BMP_ADD_ERROR_BW(pix, error) \ - { \ - tmp = (pix).r + (error); \ - BMP_CUT(tmp, 0, 255); \ - (pix).r = tmp; \ - tmp = (pix).g + (error); \ - BMP_CUT(tmp, 0, 255); \ - (pix).g = tmp; \ - tmp = (pix).b + (error); \ - BMP_CUT(tmp, 0, 255); \ - (pix).b = tmp; \ - } +#define BMP_BMAP(x) \ + ((x & 0x03) << 6) | ((x & 0x03) << 4) | ((x & 0x03) << 2) | (x & 0x03) + +#define BMP_RMAP16(x) \ + ((x & 0xc0) << 0) | ((x & 0xc0) >> 2) | ((x & 0xc0) >> 4) | ((x & 0xc0) >> 6) +#define BMP_GMAP16(x) \ + ((x & 0x60) << 1) | ((x & 0x60) >> 1) | ((x & 0x60) >> 3) | ((x & 0x60) >> 5) +#define BMP_BMAP16(x) \ + ((x & 0x30) << 2) | ((x & 0x30) << 0) | ((x & 0x30) >> 2) | ((x & 0x30) >> 4) + +#define BMP_CUT(a, b, c) \ + { \ + if (a < b) \ + a = b; \ + else if (a > c) \ + a = c; \ + } + +#define BMP_REDUCE_COLORS(r, g, b) \ + ((r & 0xe0) | ((g & 0xe0) >> 3) | ((b & 0xc0) >> 6)) + +#define BMP_ADD_ERROR(pix, weight) \ + { \ + tmp = (pix).r + ((r1 * weight) >> 4); \ + BMP_CUT(tmp, 0, 255); \ + (pix).r = tmp; \ + tmp = (pix).g + ((g1 * weight) >> 4); \ + BMP_CUT(tmp, 0, 255); \ + (pix).g = tmp; \ + tmp = (pix).b + ((b1 * weight) >> 4); \ + BMP_CUT(tmp, 0, 255); \ + (pix).b = tmp; \ + } + +#define BMP_ADD_ERROR_BW(pix, error) \ + { \ + tmp = (pix).r + (error); \ + BMP_CUT(tmp, 0, 255); \ + (pix).r = tmp; \ + tmp = (pix).g + (error); \ + BMP_CUT(tmp, 0, 255); \ + (pix).g = tmp; \ + tmp = (pix).b + (error); \ + BMP_CUT(tmp, 0, 255); \ + (pix).b = tmp; \ + } /*---------------------------------------------------------------------------*/ /*-- Structures and Enums ---------------------------------------------------*/ @@ -100,11 +105,11 @@ BMP_SUBTYPE bmp_get_colorstyle(IMAGE *img); int error_checking_bmp(BMP_HEADER *hd); -int read_bmp_line(FILE *fp, void *line, - UINT w, UINT h, UCHAR **map, BMP_SUBTYPE type); +int read_bmp_line(FILE *fp, void *line, UINT w, UINT h, UCHAR **map, + BMP_SUBTYPE type); -int write_bmp_line(FILE *fp, void *line_buffer, - UINT w, UINT row, UCHAR *map, BMP_SUBTYPE type); +int write_bmp_line(FILE *fp, void *line_buffer, UINT w, UINT row, UCHAR *map, + BMP_SUBTYPE type); int skip_bmp_lines(FILE *fp, UINT w, UINT rows, int whence, BMP_SUBTYPE type); @@ -118,17 +123,20 @@ static void putint(FILE *fp, int value); /*static int img_read_bmp_generic(const MYSTRING fname, int type, IMAGE **);*/ #ifndef UNUSED_REDUCE_COLORS -static UCHAR *reduce_colors(UCHAR *buffin, int xsize, int ysize, - UCHAR *rmap, UCHAR *gmap, UCHAR *bmap, int nc); +static UCHAR *reduce_colors(UCHAR *buffin, int xsize, int ysize, UCHAR *rmap, + UCHAR *gmap, UCHAR *bmap, int nc); #endif #ifndef __LIBSIMAGE__ #ifdef CICCIO -static int loadBMP1(FILE *fp, LPIXEL *pic, UINT w, UINT h, UCHAR *r, UCHAR *g, UCHAR *b); -static int loadBMP4(FILE *fp, LPIXEL *pic, UINT w, UINT h, UINT comp, UCHAR *r, UCHAR *g, UCHAR *b); -static int loadBMP8(FILE *fp, LPIXEL *pic, UINT w, UINT h, UINT comp, UCHAR *r, UCHAR *g, UCHAR *b); +static int loadBMP1(FILE *fp, LPIXEL *pic, UINT w, UINT h, UCHAR *r, UCHAR *g, + UCHAR *b); +static int loadBMP4(FILE *fp, LPIXEL *pic, UINT w, UINT h, UINT comp, UCHAR *r, + UCHAR *g, UCHAR *b); +static int loadBMP8(FILE *fp, LPIXEL *pic, UINT w, UINT h, UINT comp, UCHAR *r, + UCHAR *g, UCHAR *b); static int loadBMP24(FILE *fp, LPIXEL *pic, UINT w, UINT h); #endif @@ -148,11 +156,16 @@ static int load_lineBMP8(FILE *fp, LPIXEL *pic, UINT w, UINT padw, UCHAR **map); static int load_lineBMPC8(FILE *fp, LPIXEL *pic, UINT w, UINT y, UCHAR **map); static int load_lineBMP24(FILE *fp, LPIXEL *pic, UINT w, UINT padb); -static int line_writeBMP1(FILE *fp, UCHAR *pic8, UINT w, UINT padw, UCHAR *pc2nc); -static int line_writeBMP4(FILE *fp, UCHAR *pic8, UINT w, UINT padw, UCHAR *pc2nc); -static int line_writeBMPC4(FILE *fp, UCHAR *pic8, UINT w, UINT row, UCHAR *pc2nc); -static int line_writeBMP8(FILE *fp, UCHAR *pic8, UINT w, UINT padw, UCHAR *pc2nc); -static int line_writeBMPC8(FILE *fp, UCHAR *pic8, UINT w, UINT row, UCHAR *pc2nc); +static int line_writeBMP1(FILE *fp, UCHAR *pic8, UINT w, UINT padw, + UCHAR *pc2nc); +static int line_writeBMP4(FILE *fp, UCHAR *pic8, UINT w, UINT padw, + UCHAR *pc2nc); +static int line_writeBMPC4(FILE *fp, UCHAR *pic8, UINT w, UINT row, + UCHAR *pc2nc); +static int line_writeBMP8(FILE *fp, UCHAR *pic8, UINT w, UINT padw, + UCHAR *pc2nc); +static int line_writeBMPC8(FILE *fp, UCHAR *pic8, UINT w, UINT row, + UCHAR *pc2nc); static int line_writeBMP24(FILE *fp, LPIXEL *pp, UINT w, UINT padb); static int skip_rowsBMP1(FILE *fp, UINT w, UINT pad, UINT rows, int whence); @@ -167,270 +180,254 @@ static int skip_rowsBMP24(FILE *fp, UINT w, UINT pad, UINT rows, int whence); #define __BMP_READ_LINE_BY_LINE /*---------------------------------------------------------------------------*/ -int read_bmp_line(FILE *fp, void *line_buffer, - UINT w, UINT row, UCHAR **map, BMP_SUBTYPE type) +int read_bmp_line(FILE *fp, void *line_buffer, UINT w, UINT row, UCHAR **map, + BMP_SUBTYPE type) /*---------------------------------------------------------------------------*/ { - LPIXEL *pic = (LPIXEL *)line_buffer; - unsigned int pad; - int rv = 0; - - switch (type) { - case BMP_BW: - pad = ((w + 31) / 32) * 32; - rv = load_lineBMP1(fp, pic, w, (UINT)pad, map); - break; - case BMP_GREY16: - case BMP_CMAPPED16: - pad = ((w + 7) / 8) * 8; - rv = load_lineBMP4(fp, pic, w, (UINT)pad, map); - break; - case BMP_GREY16C: - case BMP_CMAPPED16C: - rv = load_lineBMPC4(fp, pic, w, row, map); - if (rv == -1) - rv = 1; - else if (rv == -2) - rv = 0; - else if (rv == -3) - rv = 0; - else - rv = 0; - break; - case BMP_GREY256: - case BMP_CMAPPED256: - pad = ((w + 3) / 4) * 4; - rv = load_lineBMP8(fp, pic, w, (UINT)pad, map); - break; - case BMP_GREY256C: - case BMP_CMAPPED256C: - rv = load_lineBMPC8(fp, pic, w, row, map); - if (rv == -1) - rv = 1; - else if (rv == -2) - rv = 0; - else if (rv == -3) - rv = 0; - else - rv = 0; - break; - case BMP_RGB: - pad = (4 - ((w * 3) % 4)) & 0x03; - rv = load_lineBMP24(fp, pic, w, (UINT)pad); - break; - } - - return !rv; /* return 0 for unsuccess */ + LPIXEL *pic = (LPIXEL *)line_buffer; + unsigned int pad; + int rv = 0; + + switch (type) { + case BMP_BW: + pad = ((w + 31) / 32) * 32; + rv = load_lineBMP1(fp, pic, w, (UINT)pad, map); + break; + case BMP_GREY16: + case BMP_CMAPPED16: + pad = ((w + 7) / 8) * 8; + rv = load_lineBMP4(fp, pic, w, (UINT)pad, map); + break; + case BMP_GREY16C: + case BMP_CMAPPED16C: + rv = load_lineBMPC4(fp, pic, w, row, map); + if (rv == -1) + rv = 1; + else if (rv == -2) + rv = 0; + else if (rv == -3) + rv = 0; + else + rv = 0; + break; + case BMP_GREY256: + case BMP_CMAPPED256: + pad = ((w + 3) / 4) * 4; + rv = load_lineBMP8(fp, pic, w, (UINT)pad, map); + break; + case BMP_GREY256C: + case BMP_CMAPPED256C: + rv = load_lineBMPC8(fp, pic, w, row, map); + if (rv == -1) + rv = 1; + else if (rv == -2) + rv = 0; + else if (rv == -3) + rv = 0; + else + rv = 0; + break; + case BMP_RGB: + pad = (4 - ((w * 3) % 4)) & 0x03; + rv = load_lineBMP24(fp, pic, w, (UINT)pad); + break; + } + + return !rv; /* return 0 for unsuccess */ } /*---------------------------------------------------------------------------*/ -int write_bmp_line(FILE *fp, void *line_buffer, - UINT w, UINT row, UCHAR *map, BMP_SUBTYPE type) +int write_bmp_line(FILE *fp, void *line_buffer, UINT w, UINT row, UCHAR *map, + BMP_SUBTYPE type) /*---------------------------------------------------------------------------*/ { - UCHAR *pic = (UCHAR *)line_buffer; - LPIXEL *p24 = (LPIXEL *)line_buffer; - unsigned int pad; - int rv = 0; - - switch (type) { - case BMP_BW: - pad = ((w + 31) / 32) * 32; - rv = line_writeBMP1(fp, pic, w, (UINT)pad, map); - break; - case BMP_GREY16: - case BMP_CMAPPED16: - pad = ((w + 7) / 8) * 8; - rv = line_writeBMP4(fp, pic, w, (UINT)pad, map); - break; - case BMP_GREY16C: - case BMP_CMAPPED16C: - rv = line_writeBMPC4(fp, pic, w, row, map); - break; - case BMP_GREY256: - case BMP_CMAPPED256: - pad = ((w + 3) / 4) * 4; - rv = line_writeBMP8(fp, pic, w, (UINT)pad, map); - break; - case BMP_GREY256C: - case BMP_CMAPPED256C: - rv = line_writeBMPC8(fp, pic, w, row, map); - break; - case BMP_RGB: - pad = (4 - ((w * 3) % 4)) & 0x03; - rv = line_writeBMP24(fp, p24, w, (UINT)pad); - break; - } - - return rv; /* 0 for unsuccess */ + UCHAR *pic = (UCHAR *)line_buffer; + LPIXEL *p24 = (LPIXEL *)line_buffer; + unsigned int pad; + int rv = 0; + + switch (type) { + case BMP_BW: + pad = ((w + 31) / 32) * 32; + rv = line_writeBMP1(fp, pic, w, (UINT)pad, map); + break; + case BMP_GREY16: + case BMP_CMAPPED16: + pad = ((w + 7) / 8) * 8; + rv = line_writeBMP4(fp, pic, w, (UINT)pad, map); + break; + case BMP_GREY16C: + case BMP_CMAPPED16C: + rv = line_writeBMPC4(fp, pic, w, row, map); + break; + case BMP_GREY256: + case BMP_CMAPPED256: + pad = ((w + 3) / 4) * 4; + rv = line_writeBMP8(fp, pic, w, (UINT)pad, map); + break; + case BMP_GREY256C: + case BMP_CMAPPED256C: + rv = line_writeBMPC8(fp, pic, w, row, map); + break; + case BMP_RGB: + pad = (4 - ((w * 3) % 4)) & 0x03; + rv = line_writeBMP24(fp, p24, w, (UINT)pad); + break; + } + + return rv; /* 0 for unsuccess */ } /*---------------------------------------------------------------------------*/ int skip_bmp_lines(FILE *fp, UINT w, UINT rows, int whence, BMP_SUBTYPE type) /*---------------------------------------------------------------------------*/ { - unsigned int pad; - int rv = 0; - - switch (type) { - case BMP_BW: - pad = ((w + 31) / 32) * 32; - rv = skip_rowsBMP1(fp, w, (UINT)pad, rows, whence); - break; - case BMP_GREY16: - case BMP_CMAPPED16: - pad = ((w + 7) / 8) * 8; - rv = skip_rowsBMP4(fp, w, (UINT)pad, rows, whence); - break; - case BMP_GREY16C: - case BMP_CMAPPED16C: - rv = skip_rowsBMPC4(fp, rows); - break; - case BMP_GREY256: - case BMP_CMAPPED256: - pad = ((w + 3) / 4) * 4; - rv = skip_rowsBMP8(fp, w, (UINT)pad, rows, whence); - break; - case BMP_GREY256C: - case BMP_CMAPPED256C: - rv = skip_rowsBMPC8(fp, rows); - break; - case BMP_RGB: - pad = (4 - ((w * 3) % 4)) & 0x03; - rv = skip_rowsBMP24(fp, w, (UINT)pad, rows, whence); - break; - } - - return !rv; + unsigned int pad; + int rv = 0; + + switch (type) { + case BMP_BW: + pad = ((w + 31) / 32) * 32; + rv = skip_rowsBMP1(fp, w, (UINT)pad, rows, whence); + break; + case BMP_GREY16: + case BMP_CMAPPED16: + pad = ((w + 7) / 8) * 8; + rv = skip_rowsBMP4(fp, w, (UINT)pad, rows, whence); + break; + case BMP_GREY16C: + case BMP_CMAPPED16C: + rv = skip_rowsBMPC4(fp, rows); + break; + case BMP_GREY256: + case BMP_CMAPPED256: + pad = ((w + 3) / 4) * 4; + rv = skip_rowsBMP8(fp, w, (UINT)pad, rows, whence); + break; + case BMP_GREY256C: + case BMP_CMAPPED256C: + rv = skip_rowsBMPC8(fp, rows); + break; + case BMP_RGB: + pad = (4 - ((w * 3) % 4)) & 0x03; + rv = skip_rowsBMP24(fp, w, (UINT)pad, rows, whence); + break; + } + + return !rv; } /*---------------------------------------------------------------------------*/ int error_checking_bmp(BMP_HEADER *hd) /*---------------------------------------------------------------------------*/ { - - /* error checking */ - if ((hd->biBitCount != 1 && - hd->biBitCount != 4 && - hd->biBitCount != 8 && - hd->biBitCount != 24) || - hd->biPlanes != 1 || hd->biCompression > BMP_BI_RLE4) { - return UNSUPPORTED_BMP_FORMAT; - } - - /* error checking */ - if (((hd->biBitCount == 1 || hd->biBitCount == 24) && - hd->biCompression != BMP_BI_RGB) || - (hd->biBitCount == 4 && hd->biCompression == BMP_BI_RLE8) || - (hd->biBitCount == 8 && hd->biCompression == BMP_BI_RLE4)) { - return UNSUPPORTED_BMP_FORMAT; - } - - return OK; + /* error checking */ + if ((hd->biBitCount != 1 && hd->biBitCount != 4 && hd->biBitCount != 8 && + hd->biBitCount != 24) || + hd->biPlanes != 1 || hd->biCompression > BMP_BI_RLE4) { + return UNSUPPORTED_BMP_FORMAT; + } + + /* error checking */ + if (((hd->biBitCount == 1 || hd->biBitCount == 24) && + hd->biCompression != BMP_BI_RGB) || + (hd->biBitCount == 4 && hd->biCompression == BMP_BI_RLE8) || + (hd->biBitCount == 8 && hd->biCompression == BMP_BI_RLE4)) { + return UNSUPPORTED_BMP_FORMAT; + } + + return OK; } /*---------------------------------------------------------------------------*/ int load_bmp_header(FILE *fp, BMP_HEADER **header) /*---------------------------------------------------------------------------*/ { - BMP_HEADER *hd = NULL; - int c, c1; - - *header = NULL; - - hd = (BMP_HEADER *)calloc((size_t)1, sizeof(BMP_HEADER)); - if (!hd) - return OUT_OF_MEMORY; - - /* figure out the file size */ - fseek(fp, 0L, SEEK_END); - hd->biFilesize = ftell(fp); - fseek(fp, 0L, 0); - - /* read the file type (first two bytes) */ - c = getc(fp); - c1 = getc(fp); - if (c != 'B' || c1 != 'M') { - free(hd); - return UNSUPPORTED_BMP_FORMAT; - } - - hd->bfSize = getint(fp); - - /* reserved and ignored */ - getshort(fp); - getshort(fp); - - hd->bfOffBits = getint(fp); - hd->biSize = getint(fp); - - if (hd->biSize == BMP_WIN_NEW || hd->biSize == BMP_OS2_NEW) { - hd->biWidth = getint(fp); - hd->biHeight = getint(fp); - hd->biPlanes = getshort(fp); - hd->biBitCount = getshort(fp); - hd->biCompression = getint(fp); - hd->biSizeImage = getint(fp); - hd->biXPelsPerMeter = getint(fp); - hd->biYPelsPerMeter = getint(fp); - hd->biClrUsed = getint(fp); - hd->biClrImportant = getint(fp); - } else /* old bitmap format */ - { - hd->biWidth = getshort(fp); - hd->biHeight = getshort(fp); - hd->biPlanes = getshort(fp); - hd->biBitCount = getshort(fp); - - /* Not in old versions so have to compute them */ - hd->biSizeImage = (((hd->biPlanes * - hd->biBitCount * - hd->biWidth) + - 31) / - 32) * - 4 * hd->biHeight; - - hd->biCompression = BMP_BI_RGB; - hd->biXPelsPerMeter = 0; - hd->biYPelsPerMeter = 0; - hd->biClrUsed = 0; - hd->biClrImportant = 0; - } - - if (BMP_DEBUG) { - printf("\nLoadBMP:\tbfSize=%u, bfOffBits=%u\n", hd->bfSize, - hd->bfOffBits); - printf("\t\tbiSize=%u, biWidth=%u, biHeight=%u, biPlanes=%u\n", - hd->biSize, - hd->biWidth, - hd->biHeight, - hd->biPlanes); - printf("\t\tbiBitCount=%u, biCompression=%u, biSizeImage=%u\n", - hd->biBitCount, - hd->biCompression, - hd->biSizeImage); - printf("\t\tbiX,YPelsPerMeter=%u,%u biClrUsed=%u, biClrImp=%u\n", - hd->biXPelsPerMeter, - hd->biYPelsPerMeter, - hd->biClrUsed, - hd->biClrImportant); - } - - if (BMP_FERROR(fp)) { - free(hd); - return UNEXPECTED_EOF; - } - - *header = hd; - return OK; + BMP_HEADER *hd = NULL; + int c, c1; + + *header = NULL; + + hd = (BMP_HEADER *)calloc((size_t)1, sizeof(BMP_HEADER)); + if (!hd) return OUT_OF_MEMORY; + + /* figure out the file size */ + fseek(fp, 0L, SEEK_END); + hd->biFilesize = ftell(fp); + fseek(fp, 0L, 0); + + /* read the file type (first two bytes) */ + c = getc(fp); + c1 = getc(fp); + if (c != 'B' || c1 != 'M') { + free(hd); + return UNSUPPORTED_BMP_FORMAT; + } + + hd->bfSize = getint(fp); + + /* reserved and ignored */ + getshort(fp); + getshort(fp); + + hd->bfOffBits = getint(fp); + hd->biSize = getint(fp); + + if (hd->biSize == BMP_WIN_NEW || hd->biSize == BMP_OS2_NEW) { + hd->biWidth = getint(fp); + hd->biHeight = getint(fp); + hd->biPlanes = getshort(fp); + hd->biBitCount = getshort(fp); + hd->biCompression = getint(fp); + hd->biSizeImage = getint(fp); + hd->biXPelsPerMeter = getint(fp); + hd->biYPelsPerMeter = getint(fp); + hd->biClrUsed = getint(fp); + hd->biClrImportant = getint(fp); + } else /* old bitmap format */ + { + hd->biWidth = getshort(fp); + hd->biHeight = getshort(fp); + hd->biPlanes = getshort(fp); + hd->biBitCount = getshort(fp); + + /* Not in old versions so have to compute them */ + hd->biSizeImage = + (((hd->biPlanes * hd->biBitCount * hd->biWidth) + 31) / 32) * 4 * + hd->biHeight; + + hd->biCompression = BMP_BI_RGB; + hd->biXPelsPerMeter = 0; + hd->biYPelsPerMeter = 0; + hd->biClrUsed = 0; + hd->biClrImportant = 0; + } + + if (BMP_DEBUG) { + printf("\nLoadBMP:\tbfSize=%u, bfOffBits=%u\n", hd->bfSize, hd->bfOffBits); + printf("\t\tbiSize=%u, biWidth=%u, biHeight=%u, biPlanes=%u\n", hd->biSize, + hd->biWidth, hd->biHeight, hd->biPlanes); + printf("\t\tbiBitCount=%u, biCompression=%u, biSizeImage=%u\n", + hd->biBitCount, hd->biCompression, hd->biSizeImage); + printf("\t\tbiX,YPelsPerMeter=%u,%u biClrUsed=%u, biClrImp=%u\n", + hd->biXPelsPerMeter, hd->biYPelsPerMeter, hd->biClrUsed, + hd->biClrImportant); + } + + if (BMP_FERROR(fp)) { + free(hd); + return UNEXPECTED_EOF; + } + + *header = hd; + return OK; } /*---------------------------------------------------------------------------*/ void release_bmp_header(BMP_HEADER *hd) /*---------------------------------------------------------------------------*/ { - if (hd) - free(hd); + if (hd) free(hd); } #ifndef __LIBSIMAGE__ @@ -441,170 +438,166 @@ void release_bmp_header(BMP_HEADER *hd) int img_read_bmp(const MYSTRING fname, IMAGE **pimg) /*---------------------------------------------------------------------------*/ { - return img_read_bmp_generic(fname, BMP_READ_IMAGE, pimg); + return img_read_bmp_generic(fname, BMP_READ_IMAGE, pimg); } /*---------------------------------------------------------------------------*/ static int img_read_bmp_generic(const MYSTRING fname, int type, IMAGE **pimg) /*---------------------------------------------------------------------------*/ { - int retCode = OK; - - UCHAR r[256], g[256], b[256]; - BMP_HEADER *hd = NULL; - IMAGE *img = NULL; - - int rv, c, i; - LPIXEL *pic; - FILE *fp; - - *pimg = 0; - - /* returns 'NULL' on unsuccess */ - - pic = (LPIXEL *)NULL; - - /* open image file */ - fp = _wfopen(fname, L"rb"); - if (!fp) - return CANT_OPEN_FILE; - - /* load up the image header */ - retCode = load_bmp_header(fp, &hd); - if (retCode != OK) - goto ERROR; - - /* error checking */ - if ((hd->biBitCount != 1 && - hd->biBitCount != 4 && - hd->biBitCount != 8 && - hd->biBitCount != 24) || - hd->biPlanes != 1 || hd->biCompression > BMP_BI_RLE4) { - retCode = UNSUPPORTED_BMP_FORMAT; - goto ERROR; - } - - /* error checking */ - if (((hd->biBitCount == 1 || hd->biBitCount == 24) && - hd->biCompression != BMP_BI_RGB) || - (hd->biBitCount == 4 && hd->biCompression == BMP_BI_RLE8) || - (hd->biBitCount == 8 && hd->biCompression == BMP_BI_RLE4)) { - retCode = UNSUPPORTED_BMP_FORMAT; - goto ERROR; - } - - img = new_img(); - img->type = TOONZRGB; - - if (type == BMP_READ_INFO) { - fclose(fp); - img->xSBsize = img->xsize = hd->biWidth; - img->ySBsize = img->ysize = hd->biHeight; - release_bmp_header(hd); - *pimg = img; - return OK; - } - - allocate_pixmap(img, (int)hd->biWidth, (int)hd->biHeight); - - /* hd->biPad; */ - if (hd->biSize != BMP_WIN_OS2_OLD) { - /* skip ahead to colormap, using biSize */ - c = hd->biSize - 40; /* 40 bytes read from biSize to biClrImportant */ - for (i = 0; i < c; i++) - getc(fp); - hd->biPad = hd->bfOffBits - (hd->biSize + 14); - } - - /* load up colormap, if any */ - if (hd->biBitCount != 24) { - int i, cmaplen; - - /*cmaplen = (hd->biClrUsed) ? hd->biClrUsed : 1 << hd->biBitCount;*/ - if (hd->biClrUsed) - cmaplen = hd->biClrUsed; - else - cmaplen = 1 << hd->biBitCount; - - for (i = 0; i < cmaplen; i++) { - b[i] = getc(fp); - g[i] = getc(fp); - r[i] = getc(fp); - if (hd->biSize != BMP_WIN_OS2_OLD) { - getc(fp); - hd->biPad -= 4; - } - } - - if (BMP_FERROR(fp)) { - retCode = UNEXPECTED_EOF; - goto ERROR; - } - - if (BMP_DEBUG) { - printf("LoadBMP: BMP colormap: (RGB order)\n"); - for (i = 0; i < cmaplen; i++) - printf("%02x%02x%02x ", r[i], g[i], b[i]); - printf("\n\n"); - } - } - - if (hd->biSize != BMP_WIN_OS2_OLD) { - /* Waste any unused bytes between the colour map (if present) - and the start of the actual bitmap data. - */ - - while (hd->biPad > 0) { - (void)getc(fp); - hd->biPad--; - } - } - - /* create 32 bit image buffer */ - - pic = (LPIXEL *)img->buffer; - - /* load up the image */ - switch (hd->biBitCount) { - case 1: - rv = loadBMP1(fp, pic, hd->biWidth, hd->biHeight, r, g, b); - break; - case 4: - rv = loadBMP4(fp, pic, hd->biWidth, hd->biHeight, hd->biCompression, r, g, b); - break; - case 8: - rv = loadBMP8(fp, pic, hd->biWidth, hd->biHeight, hd->biCompression, r, g, b); - break; - case 24: - rv = loadBMP24(fp, pic, hd->biWidth, hd->biHeight); - break; - default: - retCode = UNSUPPORTED_BMP_FORMAT; - goto ERROR; - } - - if (rv) { - retCode = UNEXPECTED_EOF; - goto ERROR; - } - - fclose(fp); - release_bmp_header(hd); - - *pimg = img; - return OK; + int retCode = OK; + + UCHAR r[256], g[256], b[256]; + BMP_HEADER *hd = NULL; + IMAGE *img = NULL; + + int rv, c, i; + LPIXEL *pic; + FILE *fp; + + *pimg = 0; + + /* returns 'NULL' on unsuccess */ + + pic = (LPIXEL *)NULL; + + /* open image file */ + fp = _wfopen(fname, L"rb"); + if (!fp) return CANT_OPEN_FILE; + + /* load up the image header */ + retCode = load_bmp_header(fp, &hd); + if (retCode != OK) goto ERROR; + + /* error checking */ + if ((hd->biBitCount != 1 && hd->biBitCount != 4 && hd->biBitCount != 8 && + hd->biBitCount != 24) || + hd->biPlanes != 1 || hd->biCompression > BMP_BI_RLE4) { + retCode = UNSUPPORTED_BMP_FORMAT; + goto ERROR; + } + + /* error checking */ + if (((hd->biBitCount == 1 || hd->biBitCount == 24) && + hd->biCompression != BMP_BI_RGB) || + (hd->biBitCount == 4 && hd->biCompression == BMP_BI_RLE8) || + (hd->biBitCount == 8 && hd->biCompression == BMP_BI_RLE4)) { + retCode = UNSUPPORTED_BMP_FORMAT; + goto ERROR; + } + + img = new_img(); + img->type = TOONZRGB; + + if (type == BMP_READ_INFO) { + fclose(fp); + img->xSBsize = img->xsize = hd->biWidth; + img->ySBsize = img->ysize = hd->biHeight; + release_bmp_header(hd); + *pimg = img; + return OK; + } + + allocate_pixmap(img, (int)hd->biWidth, (int)hd->biHeight); + + /* hd->biPad; */ + if (hd->biSize != BMP_WIN_OS2_OLD) { + /* skip ahead to colormap, using biSize */ + c = hd->biSize - 40; /* 40 bytes read from biSize to biClrImportant */ + for (i = 0; i < c; i++) getc(fp); + hd->biPad = hd->bfOffBits - (hd->biSize + 14); + } + + /* load up colormap, if any */ + if (hd->biBitCount != 24) { + int i, cmaplen; + + /*cmaplen = (hd->biClrUsed) ? hd->biClrUsed : 1 << hd->biBitCount;*/ + if (hd->biClrUsed) + cmaplen = hd->biClrUsed; + else + cmaplen = 1 << hd->biBitCount; + + for (i = 0; i < cmaplen; i++) { + b[i] = getc(fp); + g[i] = getc(fp); + r[i] = getc(fp); + if (hd->biSize != BMP_WIN_OS2_OLD) { + getc(fp); + hd->biPad -= 4; + } + } + + if (BMP_FERROR(fp)) { + retCode = UNEXPECTED_EOF; + goto ERROR; + } + + if (BMP_DEBUG) { + printf("LoadBMP: BMP colormap: (RGB order)\n"); + for (i = 0; i < cmaplen; i++) printf("%02x%02x%02x ", r[i], g[i], b[i]); + printf("\n\n"); + } + } + + if (hd->biSize != BMP_WIN_OS2_OLD) { + /* Waste any unused bytes between the colour map (if present) +and the start of the actual bitmap data. +*/ + + while (hd->biPad > 0) { + (void)getc(fp); + hd->biPad--; + } + } + + /* create 32 bit image buffer */ + + pic = (LPIXEL *)img->buffer; + + /* load up the image */ + switch (hd->biBitCount) { + case 1: + rv = loadBMP1(fp, pic, hd->biWidth, hd->biHeight, r, g, b); + break; + case 4: + rv = loadBMP4(fp, pic, hd->biWidth, hd->biHeight, hd->biCompression, r, g, + b); + break; + case 8: + rv = loadBMP8(fp, pic, hd->biWidth, hd->biHeight, hd->biCompression, r, g, + b); + break; + case 24: + rv = loadBMP24(fp, pic, hd->biWidth, hd->biHeight); + break; + default: + retCode = UNSUPPORTED_BMP_FORMAT; + goto ERROR; + } + + if (rv) { + retCode = UNEXPECTED_EOF; + goto ERROR; + } + + fclose(fp); + release_bmp_header(hd); + + *pimg = img; + return OK; ERROR: - fclose(fp); - release_bmp_header(hd); + fclose(fp); + release_bmp_header(hd); - if (img) { - TFREE(img->buffer) - TFREE(img) - } + if (img) { + TFREE(img->buffer) + TFREE(img) + } - return retCode; + return retCode; } #endif @@ -612,221 +605,213 @@ ERROR: #endif /* __LIBSIMAGE__ */ #ifdef CICCIO -static int img_read_bmp_region(const MYSTRING fname, IMAGE **pimg, int x1, int y1, int x2, int y2, int scale) +static int img_read_bmp_region(const MYSTRING fname, IMAGE **pimg, int x1, + int y1, int x2, int y2, int scale) { + UCHAR r[256], g[256], b[256] /* ,*map[3] */; + LPIXEL *line = NULL; + UINT line_size = 0; + BMP_HEADER *hd = NULL; + EXT_INFO_REGION info; + BMP_SUBTYPE subtype; + LPIXEL *pic, *appo; + IMAGE *img = NULL; + UINT start_offset; + UINT c, i, j; + char buf[512]; + FILE *fp; + UINT pad; + enum BMP_ERROR_CODE bmp_error = OK; + + /* initialize some variables */ + i = pad = 0; + + /* returns 'NULL' on unsuccess */ + pic = (LPIXEL *)NULL; + + /* open image file */ + fp = _wfopen(fname, L"rb"); + if (!fp) { + return CANT_OPEN_FILE; + } + + /* load up the image header */ + load_bmp_header(fp, &hd); + if (!hd) goto ERROR; + + /* error checking */ + if ((hd->biBitCount != 1 && hd->biBitCount != 4 && hd->biBitCount != 8 && + hd->biBitCount != 24) || + hd->biPlanes != 1 || hd->biCompression > BMP_BI_RLE4) { + sprintf(buf, "Bogus BMP File! (bitCount=%d, Planes=%d, Compression=%d)", + hd->biBitCount, hd->biPlanes, hd->biCompression); + + bmp_error = UNSUPPORTED_BMP_FORMAT; + goto ERROR; + } + + /* error checking */ + if (((hd->biBitCount == 1 || hd->biBitCount == 24) && + hd->biCompression != BMP_BI_RGB) || + (hd->biBitCount == 4 && hd->biCompression == BMP_BI_RLE8) || + (hd->biBitCount == 8 && hd->biCompression == BMP_BI_RLE4)) { + sprintf(buf, "Bogus BMP File! (bitCount=%d, Compression=%d)", + hd->biBitCount, hd->biCompression); + bmp_error = UNSUPPORTED_BMP_FORMAT; + goto ERROR; + } + + img = new_img(); + + img->type = TOONZRGB; + + img->xsize = hd->biWidth; + img->ysize = hd->biHeight; + img->xSBsize = hd->biWidth; + img->ySBsize = hd->biHeight; + img->x_dpi = (double)(hd->biXPelsPerMeter / 39); + img->y_dpi = (double)(hd->biYPelsPerMeter / 39); + + hd->biPad = 0; + if (hd->biSize != BMP_WIN_OS2_OLD) { + /* skip ahead to colormap, using biSize */ + c = hd->biSize - 40; /* 40 bytes read from biSize to biClrImportant */ + for (i = 0; i < c; i++) getc(fp); + hd->biPad = hd->bfOffBits - (hd->biSize + 14); + } + + /* load up colormap, if any */ + if (hd->biBitCount != 24) { + int i, cmaplen; + + /*cmaplen = (hd->biClrUsed) ? hd->biClrUsed : 1 << hd->biBitCount;*/ + if (hd->biClrUsed) + cmaplen = hd->biClrUsed; + else + cmaplen = hd->biBitCount; + + for (i = 0; i < cmaplen; i++) { + b[i] = getc(fp); + g[i] = getc(fp); + r[i] = getc(fp); + if (hd->biSize != BMP_WIN_OS2_OLD) { + getc(fp); + hd->biPad -= 4; + } + } + + if (BMP_FERROR(fp)) { + bmp_error = UNEXPECTED_EOF; + goto ERROR; + } + + if (BMP_DEBUG) { + printf("LoadBMP: BMP colormap: (RGB order)\n"); + for (i = 0; i < cmaplen; i++) printf("%02x%02x%02x ", r[i], g[i], b[i]); + printf("\n\n"); + } + } + + if (hd->biSize != BMP_WIN_OS2_OLD) { + /* Waste any unused bytes between the colour map (if present) +and the start of the actual bitmap data. +*/ + + while (hd->biPad > 0) { + (void)getc(fp); + hd->biPad--; + } + } + + /* get information about the portion of the image to load */ + get_info_region(&info, x1, y1, x2, y2, scale, (int)hd->biWidth, + (int)hd->biHeight, TNZ_BOTLEFT); + + /* create 32 bit image buffer */ + if (!allocate_pixmap(img, info.xsize, info.ysize)) { + bmp_error = OUT_OF_MEMORY; + goto ERROR; + } + + start_offset = info.y_offset * info.xsize + info.x_offset; + pic = ((LPIXEL *)img->buffer) + start_offset; + + if (line_size < hd->biWidth + 32) { + line_size = hd->biWidth + 32; + if (!line) + TCALLOC((LPIXEL *)line, (size_t)line_size) + else + TREALLOC(line, line_size) + } + if (!line) { + bmp_error = OUT_OF_MEMORY; + goto ERROR; + } + + switch (hd->biBitCount) { + case 1: + pad = ((hd->biWidth + 31) / 32) * 32; + break; + case 4: + pad = ((hd->biWidth + 7) / 8) * 8; + break; + case 8: + pad = ((hd->biWidth + 3) / 4) * 4; + break; + case 24: + pad = (4 - ((hd->biWidth * 3) % 4)) & 0x03; + break; + default: + /* segnala errore ed esci */ + break; + } + + subtype = bmp_get_colorstyle(img); + if (subtype == BMP_NONE) goto ERROR; + + if (info.y_offset > 0) info.scanNrow++; + if (info.x_offset > 0) info.scanNcol++; + + /* print_info_region(&info); */ + + if (info.startScanRow > 0) + skip_bmp_lines(fp, hd->biWidth, (unsigned int)(info.startScanRow - 1), + (unsigned int)SEEK_CUR, subtype); + + for (i = 0; i < (UINT)info.scanNrow; i++) { + if (load_lineBMP24(fp, line, hd->biWidth, pad)) goto ERROR; + + for (appo = pic, j = c = 0; j < (UINT)info.scanNcol; j++, c += info.step) + *appo++ = *(line + info.startScanCol + c); + pic += info.xsize; + + skip_bmp_lines(fp, hd->biWidth, (unsigned int)(info.step - 1), + (unsigned int)SEEK_CUR, subtype); + } + + /* +if (BMP_FERROR(fp)) { - UCHAR r[256], g[256], b[256] /* ,*map[3] */; - LPIXEL *line = NULL; - UINT line_size = 0; - BMP_HEADER *hd = NULL; - EXT_INFO_REGION info; - BMP_SUBTYPE subtype; - LPIXEL *pic, *appo; - IMAGE *img = NULL; - UINT start_offset; - UINT c, i, j; - char buf[512]; - FILE *fp; - UINT pad; - enum BMP_ERROR_CODE bmp_error = OK; - - /* initialize some variables */ - i = pad = 0; - - /* returns 'NULL' on unsuccess */ - pic = (LPIXEL *)NULL; - - /* open image file */ - fp = _wfopen(fname, L"rb"); - if (!fp) { - return CANT_OPEN_FILE; - } - - /* load up the image header */ - load_bmp_header(fp, &hd); - if (!hd) - goto ERROR; - - /* error checking */ - if ((hd->biBitCount != 1 && - hd->biBitCount != 4 && - hd->biBitCount != 8 && - hd->biBitCount != 24) || - hd->biPlanes != 1 || hd->biCompression > BMP_BI_RLE4) { - sprintf(buf, "Bogus BMP File! (bitCount=%d, Planes=%d, Compression=%d)", - hd->biBitCount, hd->biPlanes, hd->biCompression); - - bmp_error = UNSUPPORTED_BMP_FORMAT; - goto ERROR; - } - - /* error checking */ - if (((hd->biBitCount == 1 || hd->biBitCount == 24) && - hd->biCompression != BMP_BI_RGB) || - (hd->biBitCount == 4 && hd->biCompression == BMP_BI_RLE8) || - (hd->biBitCount == 8 && hd->biCompression == BMP_BI_RLE4)) { - sprintf(buf, "Bogus BMP File! (bitCount=%d, Compression=%d)", - hd->biBitCount, hd->biCompression); - bmp_error = UNSUPPORTED_BMP_FORMAT; - goto ERROR; - } - - img = new_img(); - - img->type = TOONZRGB; - - img->xsize = hd->biWidth; - img->ysize = hd->biHeight; - img->xSBsize = hd->biWidth; - img->ySBsize = hd->biHeight; - img->x_dpi = (double)(hd->biXPelsPerMeter / 39); - img->y_dpi = (double)(hd->biYPelsPerMeter / 39); - - hd->biPad = 0; - if (hd->biSize != BMP_WIN_OS2_OLD) { - /* skip ahead to colormap, using biSize */ - c = hd->biSize - 40; /* 40 bytes read from biSize to biClrImportant */ - for (i = 0; i < c; i++) - getc(fp); - hd->biPad = hd->bfOffBits - (hd->biSize + 14); - } - - /* load up colormap, if any */ - if (hd->biBitCount != 24) { - int i, cmaplen; - - /*cmaplen = (hd->biClrUsed) ? hd->biClrUsed : 1 << hd->biBitCount;*/ - if (hd->biClrUsed) - cmaplen = hd->biClrUsed; - else - cmaplen = hd->biBitCount; - - for (i = 0; i < cmaplen; i++) { - b[i] = getc(fp); - g[i] = getc(fp); - r[i] = getc(fp); - if (hd->biSize != BMP_WIN_OS2_OLD) { - getc(fp); - hd->biPad -= 4; - } - } - - if (BMP_FERROR(fp)) { - bmp_error = UNEXPECTED_EOF; - goto ERROR; - } - - if (BMP_DEBUG) { - printf("LoadBMP: BMP colormap: (RGB order)\n"); - for (i = 0; i < cmaplen; i++) - printf("%02x%02x%02x ", r[i], g[i], b[i]); - printf("\n\n"); - } - } - - if (hd->biSize != BMP_WIN_OS2_OLD) { - /* Waste any unused bytes between the colour map (if present) - and the start of the actual bitmap data. - */ - - while (hd->biPad > 0) { - (void)getc(fp); - hd->biPad--; - } - } - - /* get information about the portion of the image to load */ - get_info_region(&info, x1, y1, x2, y2, scale, - (int)hd->biWidth, (int)hd->biHeight, TNZ_BOTLEFT); - - /* create 32 bit image buffer */ - if (!allocate_pixmap(img, info.xsize, info.ysize)) { - bmp_error = OUT_OF_MEMORY; - goto ERROR; - } - - start_offset = info.y_offset * info.xsize + info.x_offset; - pic = ((LPIXEL *)img->buffer) + start_offset; - - if (line_size < hd->biWidth + 32) { - line_size = hd->biWidth + 32; - if (!line) - TCALLOC((LPIXEL *)line, (size_t)line_size) - else - TREALLOC(line, line_size) - } - if (!line) { - bmp_error = OUT_OF_MEMORY; - goto ERROR; - } - - switch (hd->biBitCount) { - case 1: - pad = ((hd->biWidth + 31) / 32) * 32; - break; - case 4: - pad = ((hd->biWidth + 7) / 8) * 8; - break; - case 8: - pad = ((hd->biWidth + 3) / 4) * 4; - break; - case 24: - pad = (4 - ((hd->biWidth * 3) % 4)) & 0x03; - break; - default: - /* segnala errore ed esci */ - break; - } - - subtype = bmp_get_colorstyle(img); - if (subtype == BMP_NONE) - goto ERROR; - - if (info.y_offset > 0) - info.scanNrow++; - if (info.x_offset > 0) - info.scanNcol++; - - /* print_info_region(&info); */ - - if (info.startScanRow > 0) - skip_bmp_lines(fp, hd->biWidth, (unsigned int)(info.startScanRow - 1), (unsigned int)SEEK_CUR, subtype); - - for (i = 0; i < (UINT)info.scanNrow; i++) { - if (load_lineBMP24(fp, line, hd->biWidth, pad)) - goto ERROR; - - for (appo = pic, j = c = 0; j < (UINT)info.scanNcol; j++, c += info.step) - *appo++ = *(line + info.startScanCol + c); - pic += info.xsize; - - skip_bmp_lines(fp, hd->biWidth, (unsigned int)(info.step - 1), (unsigned int)SEEK_CUR, subtype); - } - - /* - if (BMP_FERROR(fp)) - { - bmp_error(fname, "File appears truncated. Winging it.\n"); - goto ERROR; - } +bmp_error(fname, "File appears truncated. Winging it.\n"); +goto ERROR; +} */ - fclose(fp); - release_bmp_header(hd); - TFREE(line); - *pimg = img; - return OK; + fclose(fp); + release_bmp_header(hd); + TFREE(line); + *pimg = img; + return OK; ERROR: - printf("error: (row=%d)\n", i); + printf("error: (row=%d)\n", i); - fclose(fp); - release_bmp_header(hd); + fclose(fp); + release_bmp_header(hd); - if (img) - free_img(img); - TFREE(line); - return bmp_error; + if (img) free_img(img); + TFREE(line); + return bmp_error; } #endif @@ -836,58 +821,56 @@ ERROR: #ifndef __LIBSIMAGE__ #ifdef CICCIO -static int loadBMP1(FILE *fp, LPIXEL *pic, UINT w, UINT h, UCHAR *r, UCHAR *g, UCHAR *b) +static int loadBMP1(FILE *fp, LPIXEL *pic, UINT w, UINT h, UCHAR *r, UCHAR *g, + UCHAR *b) /*---------------------------------------------------------------------------*/ { - UINT i, j, c, bitnum, padw, rv; - UCHAR byte; - LPIXEL *pp; + UINT i, j, c, bitnum, padw, rv; + UCHAR byte; + LPIXEL *pp; #ifdef BMP_READ_LINE_BY_LINE - UCHAR *map[3]; + UCHAR *map[3]; - map[0] = r; - map[1] = g; - map[2] = b; + map[0] = r; + map[1] = g; + map[2] = b; #endif - rv = c = 0; - padw = ((w + 31) / 32) * 32; /* 'w', padded to be a multiple of 32 */ + rv = c = 0; + padw = ((w + 31) / 32) * 32; /* 'w', padded to be a multiple of 32 */ - for (i = 0; i < h; i++) { + for (i = 0; i < h; i++) { #ifdef BMP_READ_LINE_BY_LINE - pp = pic + (i * w); - rv = load_lineBMP1(fp, pp, w, padw, map); - if (rv) - break; + pp = pic + (i * w); + rv = load_lineBMP1(fp, pp, w, padw, map); + if (rv) break; #else - pp = pic + (i * w); - for (j = bitnum = 0; j < padw; j++, bitnum++) { - if ((bitnum & 7) == 0) /* read the next byte */ - { - c = getc(fp); - bitnum = 0; - } - if (j < w) { - byte = (c & 0x80) ? 1 : 0; - c <<= 1; - - pp->r = r[byte]; - pp->g = g[byte]; - pp->b = b[byte]; - pp->m = 255; - - pp++; - } - } - if (BMP_FERROR(fp)) - break; + pp = pic + (i * w); + for (j = bitnum = 0; j < padw; j++, bitnum++) { + if ((bitnum & 7) == 0) /* read the next byte */ + { + c = getc(fp); + bitnum = 0; + } + if (j < w) { + byte = (c & 0x80) ? 1 : 0; + c <<= 1; + + pp->r = r[byte]; + pp->g = g[byte]; + pp->b = b[byte]; + pp->m = 255; + + pp++; + } + } + if (BMP_FERROR(fp)) break; #endif - } + } - if (BMP_FERROR(fp)) - rv = 1; + if (BMP_FERROR(fp)) rv = 1; - return rv; + return rv; } #endif @@ -897,47 +880,47 @@ static int loadBMP1(FILE *fp, LPIXEL *pic, UINT w, UINT h, UCHAR *r, UCHAR *g, U int load_lineBMP1(FILE *fp, LPIXEL *pic, UINT w, UINT padw, UCHAR **map) /*---------------------------------------------------------------------------*/ { - UINT j, c, bitnum; - UCHAR byte; - LPIXEL *pp; - - for (c = 0, pp = pic, j = bitnum = 0; j < padw; j++, bitnum++) { - if ((bitnum & 7) == 0) /* read the next byte */ - { - c = getc(fp); - bitnum = 0; - } - if (j < w) { - byte = (c & 0x80) ? 1 : 0; - c <<= 1; - - pp->r = map[0][byte]; - pp->g = map[1][byte]; - pp->b = map[2][byte]; - pp->m = 255; - - pp++; - } - } - - return (BMP_FERROR(fp)); + UINT j, c, bitnum; + UCHAR byte; + LPIXEL *pp; + + for (c = 0, pp = pic, j = bitnum = 0; j < padw; j++, bitnum++) { + if ((bitnum & 7) == 0) /* read the next byte */ + { + c = getc(fp); + bitnum = 0; + } + if (j < w) { + byte = (c & 0x80) ? 1 : 0; + c <<= 1; + + pp->r = map[0][byte]; + pp->g = map[1][byte]; + pp->b = map[2][byte]; + pp->m = 255; + + pp++; + } + } + + return (BMP_FERROR(fp)); } /*---------------------------------------------------------------------------*/ static int skip_rowsBMP1(FILE *fp, UINT w, UINT pad, UINT rows, int whence) /*---------------------------------------------------------------------------*/ { - UINT offset = pad * rows; - UINT i, bitnum; + UINT offset = pad * rows; + UINT i, bitnum; - for (i = bitnum = 0; i < offset; i++, bitnum++) { - if ((bitnum & 7) == 0) { - getc(fp); - bitnum = 0; - } - } + for (i = bitnum = 0; i < offset; i++, bitnum++) { + if ((bitnum & 7) == 0) { + getc(fp); + bitnum = 0; + } + } - return (BMP_FERROR(fp)); + return (BMP_FERROR(fp)); } /*---------------------------------------------------------------------------*/ @@ -945,148 +928,141 @@ static int skip_rowsBMP1(FILE *fp, UINT w, UINT pad, UINT rows, int whence) #ifndef __LIBSIMAGE__ #ifdef CICCIO -static int loadBMP4(FILE *fp, - LPIXEL *pic, UINT w, UINT h, UINT comp, UCHAR *r, UCHAR *g, UCHAR *b) +static int loadBMP4(FILE *fp, LPIXEL *pic, UINT w, UINT h, UINT comp, UCHAR *r, + UCHAR *g, UCHAR *b) /*---------------------------------------------------------------------------*/ { - UINT i, j, c, c1, x, y, nybnum, padw, rv; - UCHAR byte; - LPIXEL *pp; + UINT i, j, c, c1, x, y, nybnum, padw, rv; + UCHAR byte; + LPIXEL *pp; #ifdef BMP_READ_LINE_BY_LINE - UCHAR *map[3]; + UCHAR *map[3]; - map[0] = r; - map[1] = g; - map[2] = b; + map[0] = r; + map[1] = g; + map[2] = b; #endif - rv = 0; - c = c1 = 0; + rv = 0; + c = c1 = 0; - if (comp == BMP_BI_RGB) /* read uncompressed data */ - { - padw = ((w + 7) / 8) * 8; /* 'w' padded to a multiple of 8pix (32 bits) */ - for (i = 0; i < h; i++) { - pp = pic + (i * w); + if (comp == BMP_BI_RGB) /* read uncompressed data */ + { + padw = ((w + 7) / 8) * 8; /* 'w' padded to a multiple of 8pix (32 bits) */ + for (i = 0; i < h; i++) { + pp = pic + (i * w); #ifdef BMP_READ_LINE_BY_LINE - rv = load_lineBMP4(fp, pp, w, padw, map); - if (rv) - break; + rv = load_lineBMP4(fp, pp, w, padw, map); + if (rv) break; #else - for (j = nybnum = 0; j < padw; j++, nybnum++) { - if ((nybnum & 1) == 0) /* read next byte */ - { - c = getc(fp); - nybnum = 0; - } - if (j < w) { - byte = (c & 0xf0) >> 4; - c <<= 4; - - pp->r = r[byte]; - pp->g = g[byte]; - pp->b = b[byte]; - pp->m = 255; - - pp++; - } - } - if (BMP_FERROR(fp)) - break; + for (j = nybnum = 0; j < padw; j++, nybnum++) { + if ((nybnum & 1) == 0) /* read next byte */ + { + c = getc(fp); + nybnum = 0; + } + if (j < w) { + byte = (c & 0xf0) >> 4; + c <<= 4; + + pp->r = r[byte]; + pp->g = g[byte]; + pp->b = b[byte]; + pp->m = 255; + + pp++; + } + } + if (BMP_FERROR(fp)) break; #endif - } - } else if (comp == BMP_BI_RLE4) /* read RLE4 compressed data */ - { - x = y = 0; - pp = pic + x + (y)*w; - while (y < h) { + } + } else if (comp == BMP_BI_RLE4) /* read RLE4 compressed data */ + { + x = y = 0; + pp = pic + x + (y)*w; + while (y < h) { #ifdef BMP_READ_LINE_BY_LINE - rv = load_lineBMPC4(fp, pp, w, y, map); - if (rv == -1) { - rv = 1; - break; - } else if (rv == -2) { - rv = 0; - y++; - pp = pic + y * w; - } else if (rv == -3) { - rv = 0; - break; - } else { - y += (rv / w); - pp = pic + rv; - rv = 0; - } + rv = load_lineBMPC4(fp, pp, w, y, map); + if (rv == -1) { + rv = 1; + break; + } else if (rv == -2) { + rv = 0; + y++; + pp = pic + y * w; + } else if (rv == -3) { + rv = 0; + break; + } else { + y += (rv / w); + pp = pic + rv; + rv = 0; + } #else - c = getc(fp); - if ((int)c == EOF) { - rv = 1; - break; - } - - if (c) /* encoded mode */ - { - c1 = getc(fp); - for (i = 0; i < c; i++, x++, pp++) { - byte = (i & 1) ? (c1 & 0x0f) : ((c1 >> 4) & 0x0f); - pp->r = r[byte]; - pp->g = g[byte]; - pp->b = b[byte]; - pp->m = 255; - } - } else /* c==0x00 : escape codes */ - { - c = getc(fp); - if ((int)c == EOF) { - rv = 1; - break; - } - - if (c == 0x00) /* end of line */ - { - x = 0; - y++; - if (y < h) - pp = pic + x + (y)*w; - } else if (c == 0x01) - break; /* end of pic */ - else if (c == 0x02) /* delta */ - { - c = getc(fp); - x += c; - c = getc(fp); - y += c; - if (y < h) - pp = pic + x + (y)*w; - } else /* absolute mode */ - { - for (i = 0; i < c; i++, x++, pp++) { - if ((i & 1) == 0) - c1 = getc(fp); - byte = (i & 1) ? (c1 & 0x0f) : ((c1 >> 4) & 0x0f); - pp->r = r[byte]; - pp->g = g[byte]; - pp->b = b[byte]; - pp->m = 255; - } - if (((c & 3) == 1) || ((c & 3) == 2)) /* read pad byte */ - getc(fp); - } - } - if (BMP_FERROR(fp)) - break; + c = getc(fp); + if ((int)c == EOF) { + rv = 1; + break; + } + + if (c) /* encoded mode */ + { + c1 = getc(fp); + for (i = 0; i < c; i++, x++, pp++) { + byte = (i & 1) ? (c1 & 0x0f) : ((c1 >> 4) & 0x0f); + pp->r = r[byte]; + pp->g = g[byte]; + pp->b = b[byte]; + pp->m = 255; + } + } else /* c==0x00 : escape codes */ + { + c = getc(fp); + if ((int)c == EOF) { + rv = 1; + break; + } + + if (c == 0x00) /* end of line */ + { + x = 0; + y++; + if (y < h) pp = pic + x + (y)*w; + } else if (c == 0x01) + break; /* end of pic */ + else if (c == 0x02) /* delta */ + { + c = getc(fp); + x += c; + c = getc(fp); + y += c; + if (y < h) pp = pic + x + (y)*w; + } else /* absolute mode */ + { + for (i = 0; i < c; i++, x++, pp++) { + if ((i & 1) == 0) c1 = getc(fp); + byte = (i & 1) ? (c1 & 0x0f) : ((c1 >> 4) & 0x0f); + pp->r = r[byte]; + pp->g = g[byte]; + pp->b = b[byte]; + pp->m = 255; + } + if (((c & 3) == 1) || ((c & 3) == 2)) /* read pad byte */ + getc(fp); + } + } + if (BMP_FERROR(fp)) break; #endif - } - } else { - return 1; - } + } + } else { + return 1; + } - if (BMP_FERROR(fp)) - rv = 1; + if (BMP_FERROR(fp)) rv = 1; - return rv; + return rv; } #endif @@ -1096,165 +1072,158 @@ static int loadBMP4(FILE *fp, int load_lineBMP4(FILE *fp, LPIXEL *pic, UINT w, UINT padw, UCHAR **map) /*---------------------------------------------------------------------------*/ { - UINT nybnum, j, c; - UCHAR byte; - LPIXEL *pp; - - for (c = 0, pp = pic, j = nybnum = 0; j < padw; j++, nybnum++) { - if ((nybnum & 1) == 0) /* read next byte */ - { - c = getc(fp); - nybnum = 0; - } - if (j < w) { - byte = (c & 0xf0) >> 4; - c <<= 4; - - pp->r = map[0][byte]; - pp->g = map[1][byte]; - pp->b = map[2][byte]; - pp->m = 255; - - pp++; - } - } - - return (BMP_FERROR(fp)); + UINT nybnum, j, c; + UCHAR byte; + LPIXEL *pp; + + for (c = 0, pp = pic, j = nybnum = 0; j < padw; j++, nybnum++) { + if ((nybnum & 1) == 0) /* read next byte */ + { + c = getc(fp); + nybnum = 0; + } + if (j < w) { + byte = (c & 0xf0) >> 4; + c <<= 4; + + pp->r = map[0][byte]; + pp->g = map[1][byte]; + pp->b = map[2][byte]; + pp->m = 255; + + pp++; + } + } + + return (BMP_FERROR(fp)); } /*---------------------------------------------------------------------------*/ static int skip_rowsBMP4(FILE *fp, UINT w, UINT pad, UINT rows, int whence) /*---------------------------------------------------------------------------*/ { - UINT offset = pad * rows; - UINT i, nybnum; + UINT offset = pad * rows; + UINT i, nybnum; - for (i = nybnum = 0; i < offset; i++, nybnum++) { - if ((nybnum & 1) == 0) { - getc(fp); - nybnum = 0; - } - } + for (i = nybnum = 0; i < offset; i++, nybnum++) { + if ((nybnum & 1) == 0) { + getc(fp); + nybnum = 0; + } + } - return (BMP_FERROR(fp)); + return (BMP_FERROR(fp)); } /*---------------------------------------------------------------------------*/ int load_lineBMPC4(FILE *fp, LPIXEL *pic, UINT w, UINT y, UCHAR **map) /*---------------------------------------------------------------------------*/ { - UINT i, c, c1, x; - UCHAR byte; - LPIXEL *pp; - - /* - * Codici di ritorno: - * - * -1: incontrata la file del file (EOF) - * -2: incontrata la fine della linea (Escape code 0x00 0x00) - * -3: incontrata la fine dell' immagine (Escape code 0x00 0x01) - * altro: incontrato un delta (Escape code 0x00 0x02) - */ - - /* initialize some variables */ - x = 0; - pp = pic; - c = c1 = 0; - - while (1) { - c = getc(fp); - if ((int)c == EOF) - return -1; - if (c) { /* encoded mode */ - c1 = getc(fp); - for (i = 0; i < c; i++, x++, pp++) { - byte = (i & 1) ? (c1 & 0x0f) : ((c1 >> 4) & 0x0f); - pp->r = map[0][byte]; - pp->g = map[1][byte]; - pp->b = map[2][byte]; - pp->m = 255; - } - } else /* c==0x00 : escape codes */ - { - c = getc(fp); - if ((int)c == EOF) - return -1; - if (c == 0x00) /* end of line */ - return -2; - else if (c == 0x01) /* end of pic */ - return -3; - else if (c == 0x02) /* delta */ - { - c = getc(fp); - x += c; - c = getc(fp); - y += c; - - return (x + y * w); - } else /* absolute mode */ - { - for (i = 0; i < c; i++, x++, pp++) { - if ((i & 1) == 0) - c1 = getc(fp); - byte = (i & 1) ? (c1 & 0x0f) : ((c1 >> 4) & 0x0f); - pp->r = map[0][byte]; - pp->g = map[1][byte]; - pp->b = map[2][byte]; - pp->m = 255; - } - if (((c & 3) == 1) || ((c & 3) == 2)) /* read pad byte */ - getc(fp); - } - } - if (BMP_FERROR(fp)) - break; - } - - return -1; + UINT i, c, c1, x; + UCHAR byte; + LPIXEL *pp; + + /* +* Codici di ritorno: +* +* -1: incontrata la file del file (EOF) +* -2: incontrata la fine della linea (Escape code 0x00 0x00) +* -3: incontrata la fine dell' immagine (Escape code 0x00 0x01) +* altro: incontrato un delta (Escape code 0x00 0x02) +*/ + + /* initialize some variables */ + x = 0; + pp = pic; + c = c1 = 0; + + while (1) { + c = getc(fp); + if ((int)c == EOF) return -1; + if (c) { /* encoded mode */ + c1 = getc(fp); + for (i = 0; i < c; i++, x++, pp++) { + byte = (i & 1) ? (c1 & 0x0f) : ((c1 >> 4) & 0x0f); + pp->r = map[0][byte]; + pp->g = map[1][byte]; + pp->b = map[2][byte]; + pp->m = 255; + } + } else /* c==0x00 : escape codes */ + { + c = getc(fp); + if ((int)c == EOF) return -1; + if (c == 0x00) /* end of line */ + return -2; + else if (c == 0x01) /* end of pic */ + return -3; + else if (c == 0x02) /* delta */ + { + c = getc(fp); + x += c; + c = getc(fp); + y += c; + + return (x + y * w); + } else /* absolute mode */ + { + for (i = 0; i < c; i++, x++, pp++) { + if ((i & 1) == 0) c1 = getc(fp); + byte = (i & 1) ? (c1 & 0x0f) : ((c1 >> 4) & 0x0f); + pp->r = map[0][byte]; + pp->g = map[1][byte]; + pp->b = map[2][byte]; + pp->m = 255; + } + if (((c & 3) == 1) || ((c & 3) == 2)) /* read pad byte */ + getc(fp); + } + } + if (BMP_FERROR(fp)) break; + } + + return -1; } /*---------------------------------------------------------------------------*/ static int skip_rowsBMPC4(FILE *fp, UINT rows) /*---------------------------------------------------------------------------*/ { - UINT i, c, c1, rv = 0; - - while (rows > 0) { - c = getc(fp); - switch (c) { - case 0x00: - c = getc(fp); - switch (c) { - case 0x00: - rows--; - break; - case 0x01: - rows = 0; - break; - case 0x02: - c1 = getc(fp); /* x buffer offest */ - c1 = getc(fp); /* y buffer offest */ - rows -= c1; - break; - default: - for (i = 0; i < c; i++) { - if ((i & 1) == 0) - getc(fp); - } - if (((c & 3) == 1) || ((c & 3) == 2)) - getc(fp); - break; - } - break; - default: - c1 = getc(fp); - } - } - - if (BMP_FERROR(fp)) - rv = 1; - - return rv; + UINT i, c, c1, rv = 0; + + while (rows > 0) { + c = getc(fp); + switch (c) { + case 0x00: + c = getc(fp); + switch (c) { + case 0x00: + rows--; + break; + case 0x01: + rows = 0; + break; + case 0x02: + c1 = getc(fp); /* x buffer offest */ + c1 = getc(fp); /* y buffer offest */ + rows -= c1; + break; + default: + for (i = 0; i < c; i++) { + if ((i & 1) == 0) getc(fp); + } + if (((c & 3) == 1) || ((c & 3) == 2)) getc(fp); + break; + } + break; + default: + c1 = getc(fp); + } + } + + if (BMP_FERROR(fp)) rv = 1; + + return rv; } /*---------------------------------------------------------------------------*/ @@ -1262,138 +1231,133 @@ static int skip_rowsBMPC4(FILE *fp, UINT rows) #ifndef __LIBSIMAGE__ #ifdef CICCIO -static int loadBMP8(FILE *fp, - LPIXEL *pic, UINT w, UINT h, UINT comp, UCHAR *r, UCHAR *g, UCHAR *b) +static int loadBMP8(FILE *fp, LPIXEL *pic, UINT w, UINT h, UINT comp, UCHAR *r, + UCHAR *g, UCHAR *b) /*---------------------------------------------------------------------------*/ { - UINT i, j, c, c1, padw, x, y, rv; + UINT i, j, c, c1, padw, x, y, rv; - LPIXEL *pp; + LPIXEL *pp; #ifdef BMP_READ_LINE_BY_LINE - UCHAR *map[3]; + UCHAR *map[3]; - map[0] = r; - map[1] = g; - map[2] = b; + map[0] = r; + map[1] = g; + map[2] = b; #endif - rv = 0; + rv = 0; - if (comp == BMP_BI_RGB) /* read uncompressed data */ - { - padw = ((w + 3) / 4) * 4; /* 'w' padded to a multiple of 4pix (32 bits) */ - for (i = 0; i < h; i++) { + if (comp == BMP_BI_RGB) /* read uncompressed data */ + { + padw = ((w + 3) / 4) * 4; /* 'w' padded to a multiple of 4pix (32 bits) */ + for (i = 0; i < h; i++) { #ifdef BMP_READ_LINE_BY_LINE - pp = pic + (i * w); - rv = load_lineBMP8(fp, pp, w, padw, map); - if (rv) - break; + pp = pic + (i * w); + rv = load_lineBMP8(fp, pp, w, padw, map); + if (rv) break; #else - pp = pic + (i * w); - for (j = 0; j < padw; j++) { - c = getc(fp); - if ((int)c == EOF) - rv = 1; - if (j < w) { - pp->r = r[c]; - pp->g = g[c]; - pp->b = b[c]; - pp->m = 255; - - pp++; - } - } - if (BMP_FERROR(fp)) - break; + pp = pic + (i * w); + for (j = 0; j < padw; j++) { + c = getc(fp); + if ((int)c == EOF) rv = 1; + if (j < w) { + pp->r = r[c]; + pp->g = g[c]; + pp->b = b[c]; + pp->m = 255; + + pp++; + } + } + if (BMP_FERROR(fp)) break; #endif - } - } else if (comp == BMP_BI_RLE8) /* read RLE8 compressed data */ - { - x = y = 0; - pp = pic + x + y * w; - while (y < h) { + } + } else if (comp == BMP_BI_RLE8) /* read RLE8 compressed data */ + { + x = y = 0; + pp = pic + x + y * w; + while (y < h) { #ifdef BMP_READ_LINE_BY_LINE - rv = load_lineBMPC8(fp, pp, w, y, map); - if (rv == -1) { - rv = 1; - break; - } else if (rv == -2) { - rv = 0; - y++; - pp = pic + y * w; - } else if (rv == -3) { - rv = 0; - break; - } else { - y += (rv / w); - pp = pic + rv; - rv = 0; - } + rv = load_lineBMPC8(fp, pp, w, y, map); + if (rv == -1) { + rv = 1; + break; + } else if (rv == -2) { + rv = 0; + y++; + pp = pic + y * w; + } else if (rv == -3) { + rv = 0; + break; + } else { + y += (rv / w); + pp = pic + rv; + rv = 0; + } #else - c = getc(fp); - if ((int)c == EOF) { - rv = 1; - break; - } - - if (c) { /* encoded mode */ - c1 = getc(fp); - for (i = 0; i < c; i++, x++, pp++) { - pp->r = r[c1]; - pp->g = g[c1]; - pp->b = b[c1]; - pp->m = 255; - } - } else /* c==0x00 : escape codes */ - { - c = getc(fp); - if ((int)c == EOF) { - rv = 1; - break; - } - - if (c == 0x00) /* end of line */ - { - x = 0; - y++; - pp = pic + x + y * w; - } else if (c == 0x01) - break; /* end of pic */ - else if (c == 0x02) /* delta */ - { - c = getc(fp); - x += c; - c = getc(fp); - y += c; - pp = pic + x + y * w; - } else /* absolute mode */ - { - for (i = 0; i < c; i++, x++, pp++) { - c1 = getc(fp); - - pp->r = r[c1]; - pp->g = g[c1]; - pp->b = b[c1]; - pp->m = 255; - } - if (c & 1) /* odd length run: read an extra pad byte */ - getc(fp); - } - } - if (BMP_FERROR(fp)) - break; + c = getc(fp); + if ((int)c == EOF) { + rv = 1; + break; + } + + if (c) { /* encoded mode */ + c1 = getc(fp); + for (i = 0; i < c; i++, x++, pp++) { + pp->r = r[c1]; + pp->g = g[c1]; + pp->b = b[c1]; + pp->m = 255; + } + } else /* c==0x00 : escape codes */ + { + c = getc(fp); + if ((int)c == EOF) { + rv = 1; + break; + } + + if (c == 0x00) /* end of line */ + { + x = 0; + y++; + pp = pic + x + y * w; + } else if (c == 0x01) + break; /* end of pic */ + else if (c == 0x02) /* delta */ + { + c = getc(fp); + x += c; + c = getc(fp); + y += c; + pp = pic + x + y * w; + } else /* absolute mode */ + { + for (i = 0; i < c; i++, x++, pp++) { + c1 = getc(fp); + + pp->r = r[c1]; + pp->g = g[c1]; + pp->b = b[c1]; + pp->m = 255; + } + if (c & 1) /* odd length run: read an extra pad byte */ + getc(fp); + } + } + if (BMP_FERROR(fp)) break; #endif - } - } else { - return 1; - } + } + } else { + return 1; + } - if (BMP_FERROR(fp)) - rv = 1; + if (BMP_FERROR(fp)) rv = 1; - return rv; + return rv; } #endif @@ -1403,146 +1367,140 @@ static int loadBMP8(FILE *fp, int load_lineBMP8(FILE *fp, LPIXEL *pic, UINT w, UINT padw, UCHAR **map) /*---------------------------------------------------------------------------*/ { - UINT j, c, rv = 0; - LPIXEL *pp; - - for (pp = pic, j = 0; j < padw; j++) { - c = getc(fp); - if ((int)c == EOF) { - rv = 1; - break; - } - if (j < w) { - pp->r = map[0][c]; - pp->g = map[1][c]; - pp->b = map[2][c]; - pp->m = 255; - - pp++; - } - } - if (BMP_FERROR(fp)) - rv = 1; - - return rv; + UINT j, c, rv = 0; + LPIXEL *pp; + + for (pp = pic, j = 0; j < padw; j++) { + c = getc(fp); + if ((int)c == EOF) { + rv = 1; + break; + } + if (j < w) { + pp->r = map[0][c]; + pp->g = map[1][c]; + pp->b = map[2][c]; + pp->m = 255; + + pp++; + } + } + if (BMP_FERROR(fp)) rv = 1; + + return rv; } /*---------------------------------------------------------------------------*/ static int skip_rowsBMP8(FILE *fp, UINT w, UINT pad, UINT rows, int whence) /*---------------------------------------------------------------------------*/ { - UINT offset = pad * rows; + UINT offset = pad * rows; - fseek(fp, (long)offset, whence); + fseek(fp, (long)offset, whence); - return (BMP_FERROR(fp)); + return (BMP_FERROR(fp)); } /*---------------------------------------------------------------------------*/ int load_lineBMPC8(FILE *fp, LPIXEL *pic, UINT w, UINT y, UCHAR **map) /*---------------------------------------------------------------------------*/ { - int i, c, c1, x; - LPIXEL *pp; - - /* - * Codici di ritorno: - * - * -1: incontrata la file del file (EOF) - * -2: incontrata la fine della linea (Escape code 0x00 0x00) - * -3: incontrata la fine dell' immagine (Escape code 0x00 0x01) - * altro: incontrato un delta (Escape code 0x00 0x02) - */ - - x = 0; - pp = pic; - - while (1) { - c = getc(fp); - if (c == EOF) - return -1; - if (c) { /* encoded mode */ - c1 = getc(fp); - for (i = 0; i < c; i++, x++, pp++) { - pp->r = map[0][c1]; - pp->g = map[1][c1]; - pp->b = map[2][c1]; - pp->m = 255; - } - } else /* c==0x00 : escape codes */ - { - c = getc(fp); - if (c == EOF) - return -1; - if (c == 0x00) /* end of line */ - return -2; - else if (c == 0x01) /* end of pic */ - return -3; - else if (c == 0x02) /* delta */ - { - c = getc(fp); - x += c; - c = getc(fp); - y += c; - - return (x + y * w); - } else /* absolute mode */ - { - for (i = 0; i < c; i++, x++, pp++) { - c1 = getc(fp); - - pp->r = map[0][c1]; - pp->g = map[1][c1]; - pp->b = map[2][c1]; - pp->m = 255; - } - if (c & 1) /* odd length run: read an extra pad byte */ - getc(fp); - } - } - } + int i, c, c1, x; + LPIXEL *pp; + + /* +* Codici di ritorno: +* +* -1: incontrata la file del file (EOF) +* -2: incontrata la fine della linea (Escape code 0x00 0x00) +* -3: incontrata la fine dell' immagine (Escape code 0x00 0x01) +* altro: incontrato un delta (Escape code 0x00 0x02) +*/ + + x = 0; + pp = pic; + + while (1) { + c = getc(fp); + if (c == EOF) return -1; + if (c) { /* encoded mode */ + c1 = getc(fp); + for (i = 0; i < c; i++, x++, pp++) { + pp->r = map[0][c1]; + pp->g = map[1][c1]; + pp->b = map[2][c1]; + pp->m = 255; + } + } else /* c==0x00 : escape codes */ + { + c = getc(fp); + if (c == EOF) return -1; + if (c == 0x00) /* end of line */ + return -2; + else if (c == 0x01) /* end of pic */ + return -3; + else if (c == 0x02) /* delta */ + { + c = getc(fp); + x += c; + c = getc(fp); + y += c; + + return (x + y * w); + } else /* absolute mode */ + { + for (i = 0; i < c; i++, x++, pp++) { + c1 = getc(fp); + + pp->r = map[0][c1]; + pp->g = map[1][c1]; + pp->b = map[2][c1]; + pp->m = 255; + } + if (c & 1) /* odd length run: read an extra pad byte */ + getc(fp); + } + } + } } /*---------------------------------------------------------------------------*/ static int skip_rowsBMPC8(FILE *fp, UINT rows) /*---------------------------------------------------------------------------*/ { - int i, c, c1, rv = 0; - - while (rows > 0) { - c = getc(fp); - switch (c) { - case 0x00: - c = getc(fp); - switch (c) { - case 0x00: - rows--; - break; - case 0x01: - rows = 0; - break; - case 0x02: - c1 = getc(fp); /* x buffer offest */ - c1 = getc(fp); /* y buffer offest */ - rows -= c1; - break; - default: - for (i = 0; i < c; i++) - getc(fp); - if (c & 1) - getc(fp); - break; - } - break; - default: - c1 = getc(fp); - } - } - - if (BMP_FERROR(fp)) - rv = 1; - - return rv; + int i, c, c1, rv = 0; + + while (rows > 0) { + c = getc(fp); + switch (c) { + case 0x00: + c = getc(fp); + switch (c) { + case 0x00: + rows--; + break; + case 0x01: + rows = 0; + break; + case 0x02: + c1 = getc(fp); /* x buffer offest */ + c1 = getc(fp); /* y buffer offest */ + rows -= c1; + break; + default: + for (i = 0; i < c; i++) getc(fp); + if (c & 1) getc(fp); + break; + } + break; + default: + c1 = getc(fp); + } + } + + if (BMP_FERROR(fp)) rv = 1; + + return rv; } /*---------------------------------------------------------------------------*/ @@ -1553,34 +1511,32 @@ static int skip_rowsBMPC8(FILE *fp, UINT rows) static int loadBMP24(FILE *fp, LPIXEL *pic, UINT w, UINT h) /*---------------------------------------------------------------------------*/ { - UINT i, j, padb, rv; - LPIXEL *pp; + UINT i, j, padb, rv; + LPIXEL *pp; - rv = 0; + rv = 0; - padb = (4 - ((w * 3) % 4)) & 0x03; /* # of pad bytes to read at EOscanline */ + padb = (4 - ((w * 3) % 4)) & 0x03; /* # of pad bytes to read at EOscanline */ - for (i = 0; i < h; i++) { + for (i = 0; i < h; i++) { #ifdef BMP_READ_LINE_BY_LINE - pp = pic + i * w; - rv = load_lineBMP24(fp, pp, w, padb); + pp = pic + i * w; + rv = load_lineBMP24(fp, pp, w, padb); #else - for (pp = pic + i * w, j = 0; j < w; j++, pp++) { - pp->b = getc(fp); /* blue */ - pp->g = getc(fp); /* green */ - pp->r = getc(fp); /* red */ - pp->m = 255; - } - for (j = 0; j < padb; j++) - getc(fp); - - rv = (BMP_FERROR(fp)); + for (pp = pic + i * w, j = 0; j < w; j++, pp++) { + pp->b = getc(fp); /* blue */ + pp->g = getc(fp); /* green */ + pp->r = getc(fp); /* red */ + pp->m = 255; + } + for (j = 0; j < padb; j++) getc(fp); + + rv = (BMP_FERROR(fp)); #endif - if (rv) - break; - } + if (rv) break; + } - return rv; + return rv; } #endif @@ -1590,30 +1546,29 @@ static int loadBMP24(FILE *fp, LPIXEL *pic, UINT w, UINT h) int load_lineBMP24(FILE *fp, LPIXEL *pic, UINT w, UINT padb) /*---------------------------------------------------------------------------*/ { - LPIXEL *pp; - UINT j; - - for (pp = pic, j = 0; j < w; j++, pp++) { - pp->b = getc(fp); /* blue */ - pp->g = getc(fp); /* green */ - pp->r = getc(fp); /* red */ - pp->m = 255; - } - for (j = 0; j < padb; j++) - getc(fp); - - return (BMP_FERROR(fp)); + LPIXEL *pp; + UINT j; + + for (pp = pic, j = 0; j < w; j++, pp++) { + pp->b = getc(fp); /* blue */ + pp->g = getc(fp); /* green */ + pp->r = getc(fp); /* red */ + pp->m = 255; + } + for (j = 0; j < padb; j++) getc(fp); + + return (BMP_FERROR(fp)); } /*---------------------------------------------------------------------------*/ static int skip_rowsBMP24(FILE *fp, UINT w, UINT pad, UINT rows, int whence) /*---------------------------------------------------------------------------*/ { - UINT offset = (w * 3 + pad) * rows; + UINT offset = (w * 3 + pad) * rows; - fseek(fp, (long)offset, whence); + fseek(fp, (long)offset, whence); - return (BMP_FERROR(fp)); + return (BMP_FERROR(fp)); } /*---------------------------------------------------------------------------*/ @@ -1623,57 +1578,56 @@ static int skip_rowsBMP24(FILE *fp, UINT w, UINT pad, UINT rows, int whence) BMP_SUBTYPE bmp_get_colorstyle(IMAGE *img) /*---------------------------------------------------------------------------*/ { - return img->type; + return img->type; } /*---------------------------------------------------------------------------*/ int write_bmp_header(FILE *fp, BMP_HEADER *hd) /*---------------------------------------------------------------------------*/ { - putc('B', fp); - putc('M', fp); /* BMP file magic number */ - - putint(fp, (int)hd->bfSize); - putshort(fp, 0); /* reserved1 */ - putshort(fp, 0); /* reserved2 */ - - putint(fp, (int)hd->bfOffBits); /* offset from BOfile to BObitmap */ - - putint(fp, (int)hd->biSize); /* size of bitmap info header */ - putint(fp, (int)hd->biWidth); /* width */ - putint(fp, (int)hd->biHeight); /* height */ - putshort(fp, (int)hd->biPlanes); /* must be '1' */ - putshort(fp, (int)hd->biBitCount); /* 1,4,8, or 24 */ - putint(fp, (int)hd->biCompression); /* BMP_BI_RGB, BMP_BI_RLE8 or BMP_BI_RLE4 */ - putint(fp, (int)hd->biSizeImage); /* size of raw image data */ - putint(fp, (int)hd->biXPelsPerMeter); /* dpi * 39" per meter */ - putint(fp, (int)hd->biYPelsPerMeter); /* dpi * 39" per meter */ - putint(fp, (int)hd->biClrUsed); /* colors used in cmap */ - putint(fp, (int)hd->biClrImportant); /* same as above */ - - if (BMP_FERROR(fp)) - return FALSE; - - return TRUE; + putc('B', fp); + putc('M', fp); /* BMP file magic number */ + + putint(fp, (int)hd->bfSize); + putshort(fp, 0); /* reserved1 */ + putshort(fp, 0); /* reserved2 */ + + putint(fp, (int)hd->bfOffBits); /* offset from BOfile to BObitmap */ + + putint(fp, (int)hd->biSize); /* size of bitmap info header */ + putint(fp, (int)hd->biWidth); /* width */ + putint(fp, (int)hd->biHeight); /* height */ + putshort(fp, (int)hd->biPlanes); /* must be '1' */ + putshort(fp, (int)hd->biBitCount); /* 1,4,8, or 24 */ + putint(fp, + (int)hd->biCompression); /* BMP_BI_RGB, BMP_BI_RLE8 or BMP_BI_RLE4 */ + putint(fp, (int)hd->biSizeImage); /* size of raw image data */ + putint(fp, (int)hd->biXPelsPerMeter); /* dpi * 39" per meter */ + putint(fp, (int)hd->biYPelsPerMeter); /* dpi * 39" per meter */ + putint(fp, (int)hd->biClrUsed); /* colors used in cmap */ + putint(fp, (int)hd->biClrImportant); /* same as above */ + + if (BMP_FERROR(fp)) return FALSE; + + return TRUE; } /*---------------------------------------------------------------------------*/ int write_bmp_palette(FILE *fp, int nc, UCHAR *b, UCHAR *g, UCHAR *r) /*---------------------------------------------------------------------------*/ { - int i; + int i; - for (i = 0; i < nc; i++) { - putc(b[i], fp); - putc(g[i], fp); - putc(r[i], fp); - putc(0, fp); - } + for (i = 0; i < nc; i++) { + putc(b[i], fp); + putc(g[i], fp); + putc(r[i], fp); + putc(0, fp); + } - if (BMP_FERROR(fp)) - return FALSE; + if (BMP_FERROR(fp)) return FALSE; - return TRUE; + return TRUE; } #ifndef __LIBSIMAGE__ @@ -1682,128 +1636,127 @@ int write_bmp_palette(FILE *fp, int nc, UCHAR *b, UCHAR *g, UCHAR *r) int img_write_bmp(const MYSTRING fname, IMAGE *img) /*---------------------------------------------------------------------------*/ { - int (*write_function)(FILE *fp, UCHAR *pic, UINT w, UINT h, UCHAR *map); - int h, w, i, nc, nbits, bperlin, comp; - UCHAR val; - UCHAR pc2nc[256], r1[256], g1[256], b1[256]; - UCHAR *pic, *graypic; - BMP_SUBTYPE subtype; - BMP_HEADER hd; - FILE *fp; - - subtype = bmp_get_colorstyle(img); - if (subtype == BMP_NONE) - return UNSUPPORTED_BMP_FORMAT; - - fp = _wfopen(fname, L"wb"); - if (!fp) - return CANT_OPEN_FILE; - - graypic = NULL; - nc = 0; - nbits = 0; - comp = 0; - h = img->ysize; - w = img->xsize; - pic = (UCHAR *)img->buffer; - - switch (subtype) { - case BMP_BW: - case BMP_GREY16: - case BMP_GREY16C: - case BMP_CMAPPED256: - case BMP_CMAPPED256C: - return UNSUPPORTED_BMP_FORMAT; - case BMP_GREY256: - case BMP_GREY256C: - nbits = 8; - break; - case BMP_RGB: - nbits = 24; - break; - default: - goto BMP_WRITE_ERROR; - } - - /* number bytes written per line */ - bperlin = ((w * nbits + 31) / 32) * 4; - - /* compute filesize and write it */ - i = 14 + /* size of bitmap file header */ - 40 + /* size of bitmap info header */ - (nc * 4) + /* size of colormap */ - bperlin * h; /* size of image data */ - - switch (nbits) { - case 4: - comp = (comp == TRUE) ? BMP_BI_RLE4 : BMP_BI_RGB; - break; - case 8: - comp = (comp == TRUE) ? BMP_BI_RLE8 : BMP_BI_RGB; - break; - default: - comp = BMP_BI_RGB; - break; - } - - /* fill image header */ - hd.bfSize = i; - hd.bfOffBits = 14 + 40 + (nc * 4); - hd.biSize = 40; - hd.biWidth = w; - hd.biHeight = h; - hd.biPlanes = 1; - hd.biBitCount = nbits; - hd.biCompression = comp; - hd.biSizeImage = bperlin * h; - hd.biXPelsPerMeter = 0 * 39; - hd.biYPelsPerMeter = 0 * 39; - hd.biClrUsed = nc; - hd.biClrImportant = nc; - - if (!write_bmp_header(fp, &hd)) - goto BMP_WRITE_ERROR; - - write_bmp_palette(fp, nc, b1, g1, r1); - - switch (nbits) { - case 1: - write_function = writeBMP1; - break; - case 4: - if (comp == BMP_BI_RGB) write_function = writeBMP4; - else write_function = writeBMPC4; - break; - case 8: - if (comp == BMP_BI_RGB) write_function = writeBMP8; - else write_function = writeBMPC8; - break; - case 24: - write_function = writeBMP24; - break; - default: - goto BMP_WRITE_ERROR; - } - - /* write out the image */ - val = write_function(fp, pic, w, h, pc2nc); - - if (graypic) - free(graypic); - fclose(fp); - - /* 0 failed , 1 ok */ - return val == 1 ? OK : WRITE_ERROR; + int (*write_function)(FILE * fp, UCHAR * pic, UINT w, UINT h, UCHAR * map); + int h, w, i, nc, nbits, bperlin, comp; + UCHAR val; + UCHAR pc2nc[256], r1[256], g1[256], b1[256]; + UCHAR *pic, *graypic; + BMP_SUBTYPE subtype; + BMP_HEADER hd; + FILE *fp; + + subtype = bmp_get_colorstyle(img); + if (subtype == BMP_NONE) return UNSUPPORTED_BMP_FORMAT; + + fp = _wfopen(fname, L"wb"); + if (!fp) return CANT_OPEN_FILE; + + graypic = NULL; + nc = 0; + nbits = 0; + comp = 0; + h = img->ysize; + w = img->xsize; + pic = (UCHAR *)img->buffer; + + switch (subtype) { + case BMP_BW: + case BMP_GREY16: + case BMP_GREY16C: + case BMP_CMAPPED256: + case BMP_CMAPPED256C: + return UNSUPPORTED_BMP_FORMAT; + case BMP_GREY256: + case BMP_GREY256C: + nbits = 8; + break; + case BMP_RGB: + nbits = 24; + break; + default: + goto BMP_WRITE_ERROR; + } + + /* number bytes written per line */ + bperlin = ((w * nbits + 31) / 32) * 4; + + /* compute filesize and write it */ + i = 14 + /* size of bitmap file header */ + 40 + /* size of bitmap info header */ + (nc * 4) + /* size of colormap */ + bperlin * h; /* size of image data */ + + switch (nbits) { + case 4: + comp = (comp == TRUE) ? BMP_BI_RLE4 : BMP_BI_RGB; + break; + case 8: + comp = (comp == TRUE) ? BMP_BI_RLE8 : BMP_BI_RGB; + break; + default: + comp = BMP_BI_RGB; + break; + } + + /* fill image header */ + hd.bfSize = i; + hd.bfOffBits = 14 + 40 + (nc * 4); + hd.biSize = 40; + hd.biWidth = w; + hd.biHeight = h; + hd.biPlanes = 1; + hd.biBitCount = nbits; + hd.biCompression = comp; + hd.biSizeImage = bperlin * h; + hd.biXPelsPerMeter = 0 * 39; + hd.biYPelsPerMeter = 0 * 39; + hd.biClrUsed = nc; + hd.biClrImportant = nc; + + if (!write_bmp_header(fp, &hd)) goto BMP_WRITE_ERROR; + + write_bmp_palette(fp, nc, b1, g1, r1); + + switch (nbits) { + case 1: + write_function = writeBMP1; + break; + case 4: + if (comp == BMP_BI_RGB) + write_function = writeBMP4; + else + write_function = writeBMPC4; + break; + case 8: + if (comp == BMP_BI_RGB) + write_function = writeBMP8; + else + write_function = writeBMPC8; + break; + case 24: + write_function = writeBMP24; + break; + default: + goto BMP_WRITE_ERROR; + } + + /* write out the image */ + val = write_function(fp, pic, w, h, pc2nc); + + if (graypic) free(graypic); + fclose(fp); + + /* 0 failed , 1 ok */ + return val == 1 ? OK : WRITE_ERROR; BMP_WRITE_ERROR: - fclose(fp); - if (graypic) - free(graypic); + fclose(fp); + if (graypic) free(graypic); - _wremove(fname); + _wremove(fname); - return WRITE_ERROR; + return WRITE_ERROR; } #endif /* __LIBSIMAGE__ */ @@ -1812,505 +1765,478 @@ BMP_WRITE_ERROR: static int writeBMP1(FILE *fp, UCHAR *pic8, UINT w, UINT h, UCHAR *pc2nc) /*---------------------------------------------------------------------------*/ { - UINT i, j, c, bitnum, padw; - UCHAR *pp; + UINT i, j, c, bitnum, padw; + UCHAR *pp; - padw = ((w + 31) / 32) * 32; /* 'w', padded to be a multiple of 32 */ + padw = ((w + 31) / 32) * 32; /* 'w', padded to be a multiple of 32 */ - for (i = 0; i < h; i++) { - pp = pic8 + (i * w); + for (i = 0; i < h; i++) { + pp = pic8 + (i * w); #ifdef BMP_WRITE_LINE_BY_LINE - if (line_writeBMP1(fp, pp, w, padw, pc2nc) == FALSE) - return FALSE; + if (line_writeBMP1(fp, pp, w, padw, pc2nc) == FALSE) return FALSE; #else - for (j = bitnum = c = 0; j <= padw; j++, bitnum++) { - if (bitnum == 8) /* write the next byte */ - { - putc((int)c, fp); - bitnum = c = 0; - } - c <<= 1; - if (j < w) { - c |= (pc2nc[*pp++] & 0x01); - } - } + for (j = bitnum = c = 0; j <= padw; j++, bitnum++) { + if (bitnum == 8) /* write the next byte */ + { + putc((int)c, fp); + bitnum = c = 0; + } + c <<= 1; + if (j < w) { + c |= (pc2nc[*pp++] & 0x01); + } + } #endif - } - if (BMP_FERROR(fp)) - return FALSE; + } + if (BMP_FERROR(fp)) return FALSE; - return TRUE; + return TRUE; } /*---------------------------------------------------------------------------*/ -static int line_writeBMP1(FILE *fp, UCHAR *pic8, UINT w, UINT padw, UCHAR *pc2nc) +static int line_writeBMP1(FILE *fp, UCHAR *pic8, UINT w, UINT padw, + UCHAR *pc2nc) /*---------------------------------------------------------------------------*/ { - UCHAR *pp = pic8; - UINT j, c, bitnum; - - for (j = bitnum = c = 0; j <= padw; j++, bitnum++) { - if (bitnum == 8) /* write the next byte */ - { - putc((int)c, fp); - bitnum = c = 0; - } - c <<= 1; - if (j < w) { - c |= (pc2nc[*pp++] & 0x01); - } - } - if (BMP_FERROR(fp)) - return FALSE; - - return TRUE; + UCHAR *pp = pic8; + UINT j, c, bitnum; + + for (j = bitnum = c = 0; j <= padw; j++, bitnum++) { + if (bitnum == 8) /* write the next byte */ + { + putc((int)c, fp); + bitnum = c = 0; + } + c <<= 1; + if (j < w) { + c |= (pc2nc[*pp++] & 0x01); + } + } + if (BMP_FERROR(fp)) return FALSE; + + return TRUE; } /*---------------------------------------------------------------------------*/ static int writeBMP4(FILE *fp, UCHAR *pic8, UINT w, UINT h, UCHAR *pc2nc) /*---------------------------------------------------------------------------*/ { - UINT i, j, c, nybnum, padw; - UCHAR *pp; + UINT i, j, c, nybnum, padw; + UCHAR *pp; - padw = ((w + 7) / 8) * 8; /* 'w' padded to a multiple of 8pix (32 bits) */ + padw = ((w + 7) / 8) * 8; /* 'w' padded to a multiple of 8pix (32 bits) */ - for (i = 0; i < h; i++) { - pp = pic8 + (i * w); + for (i = 0; i < h; i++) { + pp = pic8 + (i * w); #ifdef BMP_WRITE_LINE_BY_LINE - if (line_writeBMP4(fp, pp, w, padw, pc2nc) == FALSE) - return FALSE; + if (line_writeBMP4(fp, pp, w, padw, pc2nc) == FALSE) return FALSE; #else - for (j = nybnum = c = 0; j <= padw; j++, nybnum++) { - if (nybnum == 2) /* write next byte */ - { - putc((int)(c & 0xff), fp); - nybnum = c = 0; - } - c <<= 4; - if (j < w) { - c |= (pc2nc[*pp] & 0x0f); - pp++; - } - } + for (j = nybnum = c = 0; j <= padw; j++, nybnum++) { + if (nybnum == 2) /* write next byte */ + { + putc((int)(c & 0xff), fp); + nybnum = c = 0; + } + c <<= 4; + if (j < w) { + c |= (pc2nc[*pp] & 0x0f); + pp++; + } + } #endif - } - if (BMP_FERROR(fp)) - return FALSE; + } + if (BMP_FERROR(fp)) return FALSE; - return TRUE; + return TRUE; } /*---------------------------------------------------------------------------*/ -static int line_writeBMP4(FILE *fp, UCHAR *pic8, UINT w, UINT padw, UCHAR *pc2nc) +static int line_writeBMP4(FILE *fp, UCHAR *pic8, UINT w, UINT padw, + UCHAR *pc2nc) /*---------------------------------------------------------------------------*/ { - UINT j, c, nybnum; - UCHAR *pp = pic8; - - for (j = nybnum = c = 0; j <= padw; j++, nybnum++) { - if (nybnum == 2) /* write next byte */ - { - putc((int)(c & 0xff), fp); - nybnum = c = 0; - } - c <<= 4; - if (j < w) { - c |= (pc2nc[*pp] & 0x0f); - pp++; - } - } - if (BMP_FERROR(fp)) - return FALSE; - - return TRUE; + UINT j, c, nybnum; + UCHAR *pp = pic8; + + for (j = nybnum = c = 0; j <= padw; j++, nybnum++) { + if (nybnum == 2) /* write next byte */ + { + putc((int)(c & 0xff), fp); + nybnum = c = 0; + } + c <<= 4; + if (j < w) { + c |= (pc2nc[*pp] & 0x0f); + pp++; + } + } + if (BMP_FERROR(fp)) return FALSE; + + return TRUE; } /*---------------------------------------------------------------------------*/ static int writeBMPC4(FILE *fp, UCHAR *pic8, UINT w, UINT h, UCHAR *pc2nc) /*---------------------------------------------------------------------------*/ { - UCHAR *pp1, *pp2, *pp3, byte1, byte2; - UINT i, cnt; - - for (i = 0; i < h; i++) { - pp1 = pic8 + i * w; - pp2 = pp1 + 2; - pp3 = pp1 + w + 2; - - for (; pp2 < pp3; pp2 += 2) { - cnt = 2; - - byte1 = ((pc2nc[*pp1] << 4) & 0xf0) | (pc2nc[*(pp1 + 1)] & 0x0f); - byte2 = ((pc2nc[*pp2] << 4) & 0xf0) | (pc2nc[*(pp2 + 1)] & 0x0f); - - if (byte1 != byte2) { - putc((int)cnt, fp); - putc(byte1, fp); - pp1 = pp2; - } else { - while (cnt <= 254 && pp2 < pp3) { - cnt += 2; - pp2 += 2; - byte2 = ((pc2nc[*pp2] << 4) & 0xf0) | (pc2nc[*(pp2 + 1)] & 0x0f); - if (byte1 != byte2 || cnt >= 254 || pp2 + 2 > pp3) { - if (pp2 + 2 > pp3) - cnt -= 2; - putc((int)cnt, fp); - putc(byte1, fp); - break; - } - } - pp1 = pp2; - } - } - putc(0x00, fp); - putc(0x00, fp); - if (BMP_FERROR(fp)) - return FALSE; - } - putc(0x00, fp); - putc(0x01, fp); - - if (BMP_FERROR(fp)) - return FALSE; - - return TRUE; + UCHAR *pp1, *pp2, *pp3, byte1, byte2; + UINT i, cnt; + + for (i = 0; i < h; i++) { + pp1 = pic8 + i * w; + pp2 = pp1 + 2; + pp3 = pp1 + w + 2; + + for (; pp2 < pp3; pp2 += 2) { + cnt = 2; + + byte1 = ((pc2nc[*pp1] << 4) & 0xf0) | (pc2nc[*(pp1 + 1)] & 0x0f); + byte2 = ((pc2nc[*pp2] << 4) & 0xf0) | (pc2nc[*(pp2 + 1)] & 0x0f); + + if (byte1 != byte2) { + putc((int)cnt, fp); + putc(byte1, fp); + pp1 = pp2; + } else { + while (cnt <= 254 && pp2 < pp3) { + cnt += 2; + pp2 += 2; + byte2 = ((pc2nc[*pp2] << 4) & 0xf0) | (pc2nc[*(pp2 + 1)] & 0x0f); + if (byte1 != byte2 || cnt >= 254 || pp2 + 2 > pp3) { + if (pp2 + 2 > pp3) cnt -= 2; + putc((int)cnt, fp); + putc(byte1, fp); + break; + } + } + pp1 = pp2; + } + } + putc(0x00, fp); + putc(0x00, fp); + if (BMP_FERROR(fp)) return FALSE; + } + putc(0x00, fp); + putc(0x01, fp); + + if (BMP_FERROR(fp)) return FALSE; + + return TRUE; } /*---------------------------------------------------------------------------*/ -static int line_writeBMPC4(FILE *fp, UCHAR *pic8, UINT w, UINT row, UCHAR *pc2nc) +static int line_writeBMPC4(FILE *fp, UCHAR *pic8, UINT w, UINT row, + UCHAR *pc2nc) /*---------------------------------------------------------------------------*/ { - UCHAR *pp1, *pp2, *pp3, byte1, byte2; - UINT cnt; - - pp1 = pic8 + row * w; - pp2 = pp1 + 2; - pp3 = pp1 + w + 2; - - for (; pp2 < pp3; pp2 += 2) { - cnt = 2; - - byte1 = ((pc2nc[*pp1] << 4) & 0xf0) | (pc2nc[*(pp1 + 1)] & 0x0f); - byte2 = ((pc2nc[*pp2] << 4) & 0xf0) | (pc2nc[*(pp2 + 1)] & 0x0f); - - if (byte1 != byte2) { - putc((int)cnt, fp); - putc(byte1, fp); - pp1 = pp2; - } else { - while (cnt <= 254 && pp2 < pp3) { - cnt += 2; - pp2 += 2; - byte2 = ((pc2nc[*pp2] << 4) & 0xf0) | (pc2nc[*(pp2 + 1)] & 0x0f); - if (byte1 != byte2 || cnt >= 254 || pp2 + 2 > pp3) { - if (pp2 + 2 > pp3) - cnt -= 2; - putc((int)cnt, fp); - putc(byte1, fp); - break; - } - } - pp1 = pp2; - } - } - putc(0x00, fp); - putc(0x00, fp); - - if (BMP_FERROR(fp)) - return FALSE; - - return TRUE; + UCHAR *pp1, *pp2, *pp3, byte1, byte2; + UINT cnt; + + pp1 = pic8 + row * w; + pp2 = pp1 + 2; + pp3 = pp1 + w + 2; + + for (; pp2 < pp3; pp2 += 2) { + cnt = 2; + + byte1 = ((pc2nc[*pp1] << 4) & 0xf0) | (pc2nc[*(pp1 + 1)] & 0x0f); + byte2 = ((pc2nc[*pp2] << 4) & 0xf0) | (pc2nc[*(pp2 + 1)] & 0x0f); + + if (byte1 != byte2) { + putc((int)cnt, fp); + putc(byte1, fp); + pp1 = pp2; + } else { + while (cnt <= 254 && pp2 < pp3) { + cnt += 2; + pp2 += 2; + byte2 = ((pc2nc[*pp2] << 4) & 0xf0) | (pc2nc[*(pp2 + 1)] & 0x0f); + if (byte1 != byte2 || cnt >= 254 || pp2 + 2 > pp3) { + if (pp2 + 2 > pp3) cnt -= 2; + putc((int)cnt, fp); + putc(byte1, fp); + break; + } + } + pp1 = pp2; + } + } + putc(0x00, fp); + putc(0x00, fp); + + if (BMP_FERROR(fp)) return FALSE; + + return TRUE; } /*---------------------------------------------------------------------------*/ static int writeBMP8(FILE *fp, UCHAR *pic8, UINT w, UINT h, UCHAR *pc2nc) /*---------------------------------------------------------------------------*/ { - UINT i, j, padw; - UCHAR *pp; + UINT i, j, padw; + UCHAR *pp; - padw = ((w + 3) / 4) * 4; /* 'w' padded to a multiple of 4pix (32 bits) */ + padw = ((w + 3) / 4) * 4; /* 'w' padded to a multiple of 4pix (32 bits) */ - for (i = 0; i < h; i++) { - pp = pic8 + (i * w); + for (i = 0; i < h; i++) { + pp = pic8 + (i * w); #ifdef BMP_WRITE_LINE_BY_LINE - if (line_writeBMP8(fp, pp, w, padw, pc2nc) == FALSE) - return FALSE; + if (line_writeBMP8(fp, pp, w, padw, pc2nc) == FALSE) return FALSE; #else - /* for (j=0; j= 254 || pp2 + 1 > pp3) { - if (pp2 + 1 > pp3) - cnt--; - putc((int)cnt, fp); - putc(byte1, fp); - break; - } - } - pp1 = pp2; - } - } - putc(0x00, fp); - putc(0x00, fp); - if (BMP_FERROR(fp)) - return FALSE; - } - putc(0x00, fp); - putc(0x01, fp); - - if (BMP_FERROR(fp)) - return FALSE; - - return TRUE; + UCHAR *pp1, *pp2, *pp3, byte1, byte2; + UINT i, cnt; + + for (i = 0; i < h; i++) { + pp1 = pic8 + i * w; + pp2 = pp1 + 1; + pp3 = pp1 + w + 1; + + for (; pp2 < pp3; pp2++) { + cnt = 1; + + byte1 = pc2nc[*pp1]; + byte2 = pc2nc[*pp2]; + + if (byte1 != byte2) { + putc((int)cnt, fp); + putc(byte1, fp); + pp1 = pp2; + } else { + while (cnt <= 254 && pp2 < pp3) { + cnt++; + pp2++; + byte2 = pc2nc[*pp2]; + if (byte1 != byte2 || cnt >= 254 || pp2 + 1 > pp3) { + if (pp2 + 1 > pp3) cnt--; + putc((int)cnt, fp); + putc(byte1, fp); + break; + } + } + pp1 = pp2; + } + } + putc(0x00, fp); + putc(0x00, fp); + if (BMP_FERROR(fp)) return FALSE; + } + putc(0x00, fp); + putc(0x01, fp); + + if (BMP_FERROR(fp)) return FALSE; + + return TRUE; } /*---------------------------------------------------------------------------*/ -static int line_writeBMPC8(FILE *fp, UCHAR *pic8, UINT w, UINT row, UCHAR *pc2nc) +static int line_writeBMPC8(FILE *fp, UCHAR *pic8, UINT w, UINT row, + UCHAR *pc2nc) /*---------------------------------------------------------------------------*/ { - UCHAR *pp1, *pp2, *pp3, byte1, byte2; - UINT cnt; - - pp1 = pic8 + row * w; - pp2 = pp1 + 1; - pp3 = pp1 + w + 1; - - for (; pp2 < pp3; pp2++) { - cnt = 1; - - byte1 = pc2nc[*pp1]; - byte2 = pc2nc[*pp2]; - - if (byte1 != byte2) { - putc((int)cnt, fp); - putc(byte1, fp); - pp1 = pp2; - } else { - while (cnt <= 254 && pp2 < pp3) { - cnt++; - pp2++; - byte2 = pc2nc[*pp2]; - if (byte1 != byte2 || cnt >= 254 || pp2 + 1 > pp3) { - if (pp2 + 1 > pp3) - cnt--; - putc((int)cnt, fp); - putc(byte1, fp); - break; - } - } - pp1 = pp2; - } - } - putc(0x00, fp); - putc(0x00, fp); - - if (BMP_FERROR(fp)) - return FALSE; - - return TRUE; + UCHAR *pp1, *pp2, *pp3, byte1, byte2; + UINT cnt; + + pp1 = pic8 + row * w; + pp2 = pp1 + 1; + pp3 = pp1 + w + 1; + + for (; pp2 < pp3; pp2++) { + cnt = 1; + + byte1 = pc2nc[*pp1]; + byte2 = pc2nc[*pp2]; + + if (byte1 != byte2) { + putc((int)cnt, fp); + putc(byte1, fp); + pp1 = pp2; + } else { + while (cnt <= 254 && pp2 < pp3) { + cnt++; + pp2++; + byte2 = pc2nc[*pp2]; + if (byte1 != byte2 || cnt >= 254 || pp2 + 1 > pp3) { + if (pp2 + 1 > pp3) cnt--; + putc((int)cnt, fp); + putc(byte1, fp); + break; + } + } + pp1 = pp2; + } + } + putc(0x00, fp); + putc(0x00, fp); + + if (BMP_FERROR(fp)) return FALSE; + + return TRUE; } /*---------------------------------------------------------------------------*/ static int writeBMP24(FILE *fp, UCHAR *pic24, UINT w, UINT h, UCHAR *whence) /*---------------------------------------------------------------------------*/ { - UINT i, j, padb; - LPIXEL *pixel; - UCHAR *pp; + UINT i, j, padb; + LPIXEL *pixel; + UCHAR *pp; - /* pc2nc not used */ + /* pc2nc not used */ - padb = (4 - ((w * 3) % 4)) & 0x03; /* # of pad bytes to write at EOscanline */ + padb = (4 - ((w * 3) % 4)) & 0x03; /* # of pad bytes to write at EOscanline */ - for (i = 0; i < h; i++) { - pp = pic24 + (i * w * 4); - pixel = (LPIXEL *)pp; + for (i = 0; i < h; i++) { + pp = pic24 + (i * w * 4); + pixel = (LPIXEL *)pp; #ifdef BMP_WRITE_LINE_BY_LINE - if (line_writeBMP24(fp, pixel, w, padb) == FALSE) - return FALSE; + if (line_writeBMP24(fp, pixel, w, padb) == FALSE) return FALSE; #else - for (j = 0; j < w; j++) { - putc(pixel->b, fp); - putc(pixel->g, fp); - putc(pixel->r, fp); - - pixel++; - } - for (j = 0; j < padb; j++) - putc(0, fp); + for (j = 0; j < w; j++) { + putc(pixel->b, fp); + putc(pixel->g, fp); + putc(pixel->r, fp); + + pixel++; + } + for (j = 0; j < padb; j++) putc(0, fp); #endif - } - if (BMP_FERROR(fp)) - return FALSE; + } + if (BMP_FERROR(fp)) return FALSE; - return TRUE; + return TRUE; } /*---------------------------------------------------------------------------*/ static int line_writeBMP24(FILE *fp, LPIXEL *pp, UINT w, UINT padb) /*---------------------------------------------------------------------------*/ { - UINT j; + UINT j; - for (j = 0; j < w; j++) { - putc(pp->b, fp); - putc(pp->g, fp); - putc(pp->r, fp); + for (j = 0; j < w; j++) { + putc(pp->b, fp); + putc(pp->g, fp); + putc(pp->r, fp); - pp++; - } - for (j = 0; j < padb; j++) - putc(0, fp); - if (BMP_FERROR(fp)) - return FALSE; + pp++; + } + for (j = 0; j < padb; j++) putc(0, fp); + if (BMP_FERROR(fp)) return FALSE; - return TRUE; + return TRUE; } #ifndef __LIBSIMAGE__ #ifndef UNUSED_REDUCE_COLORS /*---------------------------------------------------------------------------*/ -static UCHAR *reduce_colors(UCHAR *buffin, int xsize, int ysize, - UCHAR *rmap, UCHAR *gmap, UCHAR *bmap, int nc) +static UCHAR *reduce_colors(UCHAR *buffin, int xsize, int ysize, UCHAR *rmap, + UCHAR *gmap, UCHAR *bmap, int nc) /*---------------------------------------------------------------------------*/ { - LPIXEL *curr_pix, *next_pix, *prev_pix, *buffer; - static LPIXEL *mbuffer = NULL; - static UCHAR *ret_buf = NULL; - static int outbuf_size = 0; - static int buffin_size = 0; - int r1, g1, b1, dim; - int i, j, tmp; - int imax, jmax; - UCHAR *outbuf; - USHORT val; - - dim = xsize * ysize; - - if (dim > outbuf_size) { - if (!ret_buf) - TCALLOC(ret_buf, dim) - else - TREALLOC(ret_buf, dim); - if (!ret_buf) - return NULL; - outbuf_size = dim; - } - - if (dim > buffin_size) { - if (!mbuffer) - TCALLOC(mbuffer, dim) - else - TREALLOC(mbuffer, dim); - if (!ret_buf) - return NULL; - buffin_size = dim; - } - - memcpy(mbuffer, buffin, dim * sizeof(LPIXEL)); - buffer = mbuffer; - outbuf = ret_buf; - - imax = ysize - 1; - jmax = xsize - 1; - - for (i = 0; i < ysize; i++) { - curr_pix = buffer; - buffer += xsize; - next_pix = buffer; - prev_pix = NIL; - - for (j = 0; j < xsize; j++) { - r1 = curr_pix->r; - g1 = curr_pix->g; - b1 = curr_pix->b; - - val = BMP_REDUCE_COLORS(r1, g1, b1); - - *(outbuf++) = (unsigned char)val; - - /* errors on colors */ - r1 -= rmap[val]; - g1 -= gmap[val]; - b1 -= bmap[val]; - - if (j != jmax) - BMP_ADD_ERROR(curr_pix[1], 7) /* RIGHT */ - if (i != imax) /* UP */ - { - BMP_ADD_ERROR(*next_pix, 5) - if (j > 0) - BMP_ADD_ERROR(*prev_pix, 3) /* UP LEFT */ - if (j != jmax) - BMP_ADD_ERROR(next_pix[1], 1) /* UP RIGHT */ - prev_pix = next_pix; - next_pix++; - } - curr_pix++; - } - } - - return ret_buf; + LPIXEL *curr_pix, *next_pix, *prev_pix, *buffer; + static LPIXEL *mbuffer = NULL; + static UCHAR *ret_buf = NULL; + static int outbuf_size = 0; + static int buffin_size = 0; + int r1, g1, b1, dim; + int i, j, tmp; + int imax, jmax; + UCHAR *outbuf; + USHORT val; + + dim = xsize * ysize; + + if (dim > outbuf_size) { + if (!ret_buf) + TCALLOC(ret_buf, dim) + else + TREALLOC(ret_buf, dim); + if (!ret_buf) return NULL; + outbuf_size = dim; + } + + if (dim > buffin_size) { + if (!mbuffer) + TCALLOC(mbuffer, dim) + else + TREALLOC(mbuffer, dim); + if (!ret_buf) return NULL; + buffin_size = dim; + } + + memcpy(mbuffer, buffin, dim * sizeof(LPIXEL)); + buffer = mbuffer; + outbuf = ret_buf; + + imax = ysize - 1; + jmax = xsize - 1; + + for (i = 0; i < ysize; i++) { + curr_pix = buffer; + buffer += xsize; + next_pix = buffer; + prev_pix = NIL; + + for (j = 0; j < xsize; j++) { + r1 = curr_pix->r; + g1 = curr_pix->g; + b1 = curr_pix->b; + + val = BMP_REDUCE_COLORS(r1, g1, b1); + + *(outbuf++) = (unsigned char)val; + + /* errors on colors */ + r1 -= rmap[val]; + g1 -= gmap[val]; + b1 -= bmap[val]; + + if (j != jmax) BMP_ADD_ERROR(curr_pix[1], 7) /* RIGHT */ + if (i != imax) /* UP */ + { + BMP_ADD_ERROR(*next_pix, 5) + if (j > 0) BMP_ADD_ERROR(*prev_pix, 3) /* UP LEFT */ + if (j != jmax) BMP_ADD_ERROR(next_pix[1], 1) /* UP RIGHT */ + prev_pix = next_pix; + next_pix++; + } + curr_pix++; + } + } + + return ret_buf; } #endif @@ -2320,178 +2246,163 @@ static UCHAR *reduce_colors(UCHAR *buffin, int xsize, int ysize, int make_bmp_palette(int colors, int grey, UCHAR *r, UCHAR *g, UCHAR *b) /*---------------------------------------------------------------------------*/ { - int i, j, ind, val; - - switch (colors) { - case 2: - for (i = 0; i < 2; i++) - r[i] = g[i] = b[i] = i * 255; - break; - case 16: - for (i = 0; i < 16; i++) { - for (j = 0; j < 16; j++) { - ind = i * 16 + j; - val = i * 16; - r[ind] = g[ind] = b[ind] = val; - } - } - break; - case 256: - if (grey) { - for (i = 0; i < 256; i++) - r[i] = g[i] = b[i] = i; - } - else { - for (i = 0; i < 256; i++) { - r[i] = BMP_RMAP(i); - g[i] = BMP_GMAP(i); - b[i] = BMP_BMAP(i); - } - } - break; - default: - return FALSE; - } - - return TRUE; + int i, j, ind, val; + + switch (colors) { + case 2: + for (i = 0; i < 2; i++) r[i] = g[i] = b[i] = i * 255; + break; + case 16: + for (i = 0; i < 16; i++) { + for (j = 0; j < 16; j++) { + ind = i * 16 + j; + val = i * 16; + r[ind] = g[ind] = b[ind] = val; + } + } + break; + case 256: + if (grey) { + for (i = 0; i < 256; i++) r[i] = g[i] = b[i] = i; + } else { + for (i = 0; i < 256; i++) { + r[i] = BMP_RMAP(i); + g[i] = BMP_GMAP(i); + b[i] = BMP_BMAP(i); + } + } + break; + default: + return FALSE; + } + + return TRUE; } /*---------------------------------------------------------------------------*/ static UINT getshort(FILE *fp) /*---------------------------------------------------------------------------*/ { - int c = getc(fp), - c1 = getc(fp); + int c = getc(fp), c1 = getc(fp); - return ((UINT)c) + (((UINT)c1) << 8); + return ((UINT)c) + (((UINT)c1) << 8); } /*---------------------------------------------------------------------------*/ static UINT getint(FILE *fp) /*---------------------------------------------------------------------------*/ { - int c = getc(fp), - c1 = getc(fp), - c2 = getc(fp), - c3 = getc(fp); - - return (((UINT)c) << 0) + - (((UINT)c1) << 8) + - (((UINT)c2) << 16) + - (((UINT)c3) << 24); + int c = getc(fp), c1 = getc(fp), c2 = getc(fp), c3 = getc(fp); + + return (((UINT)c) << 0) + (((UINT)c1) << 8) + (((UINT)c2) << 16) + + (((UINT)c3) << 24); } /*---------------------------------------------------------------------------*/ static void putshort(FILE *fp, int i) /*---------------------------------------------------------------------------*/ { - int c = (((UINT)i)) & 0xff, - c1 = (((UINT)i) >> 8) & 0xff; + int c = (((UINT)i)) & 0xff, c1 = (((UINT)i) >> 8) & 0xff; - putc(c, fp); - putc(c1, fp); + putc(c, fp); + putc(c1, fp); } /*---------------------------------------------------------------------------*/ static void putint(FILE *fp, int i) /*---------------------------------------------------------------------------*/ { - int c = ((UINT)i) & 0xff, - c1 = (((UINT)i) >> 8) & 0xff, - c2 = (((UINT)i) >> 16) & 0xff, - c3 = (((UINT)i) >> 24) & 0xff; - - putc(c, fp); - putc(c1, fp); - putc(c2, fp); - putc(c3, fp); + int c = ((UINT)i) & 0xff, c1 = (((UINT)i) >> 8) & 0xff, + c2 = (((UINT)i) >> 16) & 0xff, c3 = (((UINT)i) >> 24) & 0xff; + + putc(c, fp); + putc(c1, fp); + putc(c2, fp); + putc(c3, fp); } /*---------------------------------------------------------------------------*/ -int writebmp(const MYSTRING filename, int xsize, int ysize, void *buffer, int bpp) -{ - IMAGE img; - img.xsize = xsize; - img.ysize = ysize; - img.buffer = buffer; - switch (bpp) { - case 8: - img.type = BMP_GREY256C; - break; - case 32: - img.type = BMP_RGB; - break; - } - return img_write_bmp(filename, &img); +int writebmp(const MYSTRING filename, int xsize, int ysize, void *buffer, + int bpp) { + IMAGE img; + img.xsize = xsize; + img.ysize = ysize; + img.buffer = buffer; + switch (bpp) { + case 8: + img.type = BMP_GREY256C; + break; + case 32: + img.type = BMP_RGB; + break; + } + return img_write_bmp(filename, &img); } /*---------------------------------------------------------------------------*/ #ifdef CICCIO -int readbmp(const MYSTRING filename, int *xsize, int *ysize, void **buffer) -{ - IMAGE *img; - int retCode = img_read_bmp(filename, &img); - if (retCode != OK) { - *xsize = *ysize = 0; - *buffer = 0; - } else { - *xsize = img->xsize; - *ysize = img->ysize; - *buffer = img->buffer; - img->buffer = 0; - free_img(img); - } - return retCode; +int readbmp(const MYSTRING filename, int *xsize, int *ysize, void **buffer) { + IMAGE *img; + int retCode = img_read_bmp(filename, &img); + if (retCode != OK) { + *xsize = *ysize = 0; + *buffer = 0; + } else { + *xsize = img->xsize; + *ysize = img->ysize; + *buffer = img->buffer; + img->buffer = 0; + free_img(img); + } + return retCode; } /*---------------------------------------------------------------------------*/ -int readbmpregion(const MYSTRING filename, void **pimg, int x1, int y1, int x2, int y2, int scale) -{ - IMAGE *img; +int readbmpregion(const MYSTRING filename, void **pimg, int x1, int y1, int x2, + int y2, int scale) { + IMAGE *img; - int retCode = img_read_bmp_region(filename, &img, x1, y1, x2, y2, scale); + int retCode = img_read_bmp_region(filename, &img, x1, y1, x2, y2, scale); - if (retCode != OK) { - *pimg = 0; - } else { - *pimg = img->buffer; - free(img); - } - return retCode; + if (retCode != OK) { + *pimg = 0; + } else { + *pimg = img->buffer; + free(img); + } + return retCode; } /*---------------------------------------------------------------------------*/ -int readbmp_size(const MYSTRING fname, int *lx, int *ly) -{ - IMAGE *img; - int retCode = img_read_bmp_generic(fname, BMP_READ_INFO, &img); - if (retCode == OK) { - *lx = img->xsize; - *ly = img->ysize; - free(img); - } - return retCode; +int readbmp_size(const MYSTRING fname, int *lx, int *ly) { + IMAGE *img; + int retCode = img_read_bmp_generic(fname, BMP_READ_INFO, &img); + if (retCode == OK) { + *lx = img->xsize; + *ly = img->ysize; + free(img); + } + return retCode; } /*---------------------------------------------------------------------------*/ -int readbmp_bbox(const MYSTRING fname, int *x0, int *y0, int *x1, int *y1) -{ - IMAGE *img; - int retCode = img_read_bmp_generic(fname, BMP_READ_INFO, &img); - if (retCode == OK) { - *x0 = 0; - *x1 = 0; - *x1 = img->xsize - 1; - *y1 = img->ysize - 1; - free(img); - } - return retCode; +int readbmp_bbox(const MYSTRING fname, int *x0, int *y0, int *x1, int *y1) { + IMAGE *img; + int retCode = img_read_bmp_generic(fname, BMP_READ_INFO, &img); + if (retCode == OK) { + *x0 = 0; + *x1 = 0; + *x1 = img->xsize - 1; + *y1 = img->ysize - 1; + free(img); + } + return retCode; } #endif diff --git a/toonz/sources/common/tiio/bmp/filebmp.h b/toonz/sources/common/tiio/bmp/filebmp.h index 4d8f4bb..d6911ff 100644 --- a/toonz/sources/common/tiio/bmp/filebmp.h +++ b/toonz/sources/common/tiio/bmp/filebmp.h @@ -18,55 +18,56 @@ typedef struct { unsigned char r,g,b,m; } LPIXEL; #endif */ enum BMP_ERROR_CODE { - OK, - UNSUPPORTED_BMP_FORMAT = -1, - OUT_OF_MEMORY = -2, - UNEXPECTED_EOF = -3, - CANT_OPEN_FILE = -4, - WRITE_ERROR = -5 + OK, + UNSUPPORTED_BMP_FORMAT = -1, + OUT_OF_MEMORY = -2, + UNEXPECTED_EOF = -3, + CANT_OPEN_FILE = -4, + WRITE_ERROR = -5 }; typedef const wchar_t *MYSTRING; -int writebmp(const MYSTRING filename, int xsize, int ysize, void *buffer, int bpp); +int writebmp(const MYSTRING filename, int xsize, int ysize, void *buffer, + int bpp); int readbmp(const MYSTRING filename, int *xsize, int *ysize, void **buffer); -int readbmpregion(const MYSTRING fname, void **pimg, int x1, int y1, int x2, int y2, int scale); +int readbmpregion(const MYSTRING fname, void **pimg, int x1, int y1, int x2, + int y2, int scale); int readbmp_size(const MYSTRING fname, int *lx, int *ly); int readbmp_bbox(const MYSTRING fname, int *x0, int *y0, int *x1, int *y1); typedef enum { - BMP_NONE, - BMP_BW, - BMP_GREY16, - BMP_GREY16C, - BMP_GREY256, - BMP_GREY256C, - BMP_CMAPPED16, - BMP_CMAPPED16C, - BMP_CMAPPED256, - BMP_CMAPPED256C, - BMP_RGB + BMP_NONE, + BMP_BW, + BMP_GREY16, + BMP_GREY16C, + BMP_GREY256, + BMP_GREY256C, + BMP_CMAPPED16, + BMP_CMAPPED16C, + BMP_CMAPPED256, + BMP_CMAPPED256C, + BMP_RGB } BMP_SUBTYPE; -typedef struct - { - UINT bfSize; - UINT bfOffBits; - UINT biSize; - UINT biWidth; - UINT biHeight; - UINT biPlanes; - UINT biBitCount; - UINT biCompression; - UINT biSizeImage; - UINT biXPelsPerMeter; - UINT biYPelsPerMeter; - UINT biClrUsed; - UINT biClrImportant; - UINT biFilesize; - UINT biPad; +typedef struct { + UINT bfSize; + UINT bfOffBits; + UINT biSize; + UINT biWidth; + UINT biHeight; + UINT biPlanes; + UINT biBitCount; + UINT biCompression; + UINT biSizeImage; + UINT biXPelsPerMeter; + UINT biYPelsPerMeter; + UINT biClrUsed; + UINT biClrImportant; + UINT biFilesize; + UINT biPad; } BMP_HEADER; @@ -77,14 +78,14 @@ void release_bmp_header(BMP_HEADER *hd); int write_bmp_palette(FILE *fp, int nc, UCHAR *b, UCHAR *g, UCHAR *r); int make_bmp_palette(int colors, int grey, UCHAR *r, UCHAR *g, UCHAR *b); -/*BMP_SUBTYPE +/*BMP_SUBTYPE bmp_get_colorstyle(IMAGE *img);*/ int error_checking_bmp(BMP_HEADER *hd); -int read_bmp_line(FILE *fp, void *line, - UINT w, UINT h, UCHAR **mp, BMP_SUBTYPE type); -int write_bmp_line(FILE *fp, void *line_buffer, - UINT w, UINT row, UCHAR *mp, BMP_SUBTYPE type); +int read_bmp_line(FILE *fp, void *line, UINT w, UINT h, UCHAR **mp, + BMP_SUBTYPE type); +int write_bmp_line(FILE *fp, void *line_buffer, UINT w, UINT row, UCHAR *mp, + BMP_SUBTYPE type); int skip_bmp_lines(FILE *fp, UINT w, UINT rows, int whence, BMP_SUBTYPE type); #define BMP_WIN_OS2_OLD 12 diff --git a/toonz/sources/common/tiio/compatibility/tfile_io.c b/toonz/sources/common/tiio/compatibility/tfile_io.c index 11c0cb5..20ca6b8 100644 --- a/toonz/sources/common/tiio/compatibility/tfile_io.c +++ b/toonz/sources/common/tiio/compatibility/tfile_io.c @@ -7,93 +7,87 @@ #include #include -LPSTR AtlW2AHelper(LPSTR lpa, LPCWSTR lpw, int nChars, UINT acp) -{ - assert(lpw != NULL); - assert(lpa != NULL); - /* - verify that no illegal character present - since lpa was allocated based on the size of lpw - don t worry about the number of chars +LPSTR AtlW2AHelper(LPSTR lpa, LPCWSTR lpw, int nChars, UINT acp) { + assert(lpw != NULL); + assert(lpa != NULL); + /* + verify that no illegal character present + since lpa was allocated based on the size of lpw +don t worry about the number of chars */ - lpa[0] = '\0'; - WideCharToMultiByte(acp, 0, lpw, -1, lpa, nChars, NULL, NULL); - return lpa; + lpa[0] = '\0'; + WideCharToMultiByte(acp, 0, lpw, -1, lpa, nChars, NULL, NULL); + return lpa; } -char *convertWCHAR2CHAR(const wchar_t *fname) -{ - int size = 0; - LPCWSTR lpw = fname; - char *name = NULL; - char *outName = 0; - if (lpw) { - LPSTR pStr = 0; - size = (lstrlenW(lpw) + 1) * 2; - pStr = (LPSTR)malloc(size * sizeof(char)); - name = AtlW2AHelper(pStr, lpw, size, 0); - } - return name; +char *convertWCHAR2CHAR(const wchar_t *fname) { + int size = 0; + LPCWSTR lpw = fname; + char *name = NULL; + char *outName = 0; + if (lpw) { + LPSTR pStr = 0; + size = (lstrlenW(lpw) + 1) * 2; + pStr = (LPSTR)malloc(size * sizeof(char)); + name = AtlW2AHelper(pStr, lpw, size, 0); + } + return name; } #else #include -char *convertWCHAR2CHAR(const wchar_t *wc) -{ - int count = 0; - const wchar_t *ptr = wc; - char *c = 0; - char *buff; - while ((*ptr) != '\0') { - ++count; - ++ptr; - } - c = (char *)malloc((count + 1) * sizeof(char)); - buff = c; - ptr = wc; - while ((*ptr) != '\0') { - *c = *ptr; - ++c; - ++ptr; - } - *c = 0; - return buff; +char *convertWCHAR2CHAR(const wchar_t *wc) { + int count = 0; + const wchar_t *ptr = wc; + char *c = 0; + char *buff; + while ((*ptr) != '\0') { + ++count; + ++ptr; + } + c = (char *)malloc((count + 1) * sizeof(char)); + buff = c; + ptr = wc; + while ((*ptr) != '\0') { + *c = *ptr; + ++c; + ++ptr; + } + *c = 0; + return buff; } #endif /*-----------------------------------*/ #if defined(MACOSX) || defined(LINUX) -FILE *_wfopen(const wchar_t *fname, const wchar_t *mode) -{ - char *cfname = convertWCHAR2CHAR(fname); - char *cmode = convertWCHAR2CHAR(mode); +FILE *_wfopen(const wchar_t *fname, const wchar_t *mode) { + char *cfname = convertWCHAR2CHAR(fname); + char *cmode = convertWCHAR2CHAR(mode); - FILE *f = fopen(cfname, cmode); - free(cfname); - free(cmode); - return f; + FILE *f = fopen(cfname, cmode); + free(cfname); + free(cmode); + return f; } /*-----------------------------------*/ -int _wstat(const wchar_t *fname, struct stat *buf) -{ - char *cfname = convertWCHAR2CHAR(fname); - int rc = stat(cfname, buf); +int _wstat(const wchar_t *fname, struct stat *buf) { + char *cfname = convertWCHAR2CHAR(fname); + int rc = stat(cfname, buf); - free(cfname); - return rc; + free(cfname); + return rc; } /*-----------------------------------*/ -int _wremove(const wchar_t *fname) -{ - char *cfname = convertWCHAR2CHAR(fname); - int rc = remove(cfname); +int _wremove(const wchar_t *fname) { + char *cfname = convertWCHAR2CHAR(fname); + int rc = remove(cfname); - free(cfname); - return rc; + free(cfname); + return rc; } #endif diff --git a/toonz/sources/common/tiio/movsettings.cpp b/toonz/sources/common/tiio/movsettings.cpp index 6f6da8b..9fe24f8 100644 --- a/toonz/sources/common/tiio/movsettings.cpp +++ b/toonz/sources/common/tiio/movsettings.cpp @@ -61,23 +61,32 @@ #endif /* -questo file gestisce il salvataggio in un .tnz e il caricamento dei setting dei mov. -viene usato il popup fornito da quicktime, con tutti i suoi setting e i sotto settings. -i setting sono memorizzati da quicktime in un componentInstance. Da qui, possono essere convertiti in un atomContainer, -che e' una struttura simile alla nostra propertyGroup, ma con gli atomi strutturati ad albero. -sono state scritte due funzioni di conversione da atomContainer a propertygroup e viceversa -ogni atom ha un type, id, e numero figli. se numero figli=0 allora l'atomo e'una foglia, +questo file gestisce il salvataggio in un .tnz e il caricamento dei setting dei +mov. +viene usato il popup fornito da quicktime, con tutti i suoi setting e i sotto +settings. +i setting sono memorizzati da quicktime in un componentInstance. Da qui, possono +essere convertiti in un atomContainer, +che e' una struttura simile alla nostra propertyGroup, ma con gli atomi +strutturati ad albero. +sono state scritte due funzioni di conversione da atomContainer a propertygroup +e viceversa +ogni atom ha un type, id, e numero figli. se numero figli=0 allora l'atomo e'una +foglia, e quindi ha un buffer di dati di valori char. -ogni atomo viene trasformato in una stringProperty. il nome della stringProperty e' +ogni atomo viene trasformato in una stringProperty. il nome della stringProperty +e' "type id numeroFigli" -se numerofigli>0, allora la stringProperty ha un valore nullo, e le prossime -numerofigli property contengono i figli; -se numerofigli==0, allora il valore della property contiene il buffer di dati, +se numerofigli>0, allora la stringProperty ha un valore nullo, e le prossime +numerofigli property contengono i figli; +se numerofigli==0, allora il valore della property contiene il buffer di dati, convertito in stringa. ecco coem viene convertito il buffer in stringa: -se ad esempio il buffer e' composto di 3 bytes, buf[0] = 13 buf[1]=0 buf[2]=231 allora la strnga valore sara' "13 0 231" -se ci sono piu 0 consecutivi, vengono memorizzati per salvare spazio come "z count" in cui count e' il numero di 0. +se ad esempio il buffer e' composto di 3 bytes, buf[0] = 13 buf[1]=0 buf[2]=231 +allora la strnga valore sara' "13 0 231" +se ci sono piu 0 consecutivi, vengono memorizzati per salvare spazio come "z +count" in cui count e' il numero di 0. esempio: buf[0] = 13 buf[1]=0 buf[2]=0 buf[3]=0 buf[4]=0 buf5]=231 allora str = "13 z 4 231" */ @@ -86,184 +95,174 @@ allora str = "13 z 4 231" //------------------------------------------------ -void visitAtoms(const QTAtomContainer &atoms, const QTAtom &parent, TPropertyGroup &pg) -{ - QTAtom curr = 0; - - do { - - if (QTNextChildAnyType(atoms, parent, curr, &curr) != noErr) - assert(false); - - if (curr == 0) - break; - QTAtomType atomType; - QTAtomID id; - - QTGetAtomTypeAndID(atoms, curr, &atomType, &id); - int sonCount = QTCountChildrenOfType(atoms, curr, 0); - - char buffer[1024]; - sprintf(buffer, "%d %d %d", (int)atomType, (int)id, sonCount); - string str(buffer); - - if (sonCount > 0) { - pg.add(new TStringProperty(str, TString())); - visitAtoms(atoms, curr, pg); - } - - else { - long size; - UCHAR *atomData; - if (QTGetAtomDataPtr(atoms, curr, &size, (char **)&atomData) != noErr) - assert(false); - - string strapp; - for (int i = 0; i < size; i++) { - string num; - if (atomData[i] == 0) { - int count = 1; - while ((i + 1) < size && atomData[i + 1] == 0) - i++, count++; - if (count > 1) { - num = std::to_string(count); - strapp = strapp + "z " + num + " "; - continue; - } - } - num = std::to_string(atomData[i]); - - strapp = strapp + string(num) + " "; - } - - //unsigned short*buffer = new unsigned short[size]; - //buffer[size]=0; - //for (i=0; i 0) { + pg.add(new TStringProperty(str, TString())); + visitAtoms(atoms, curr, pg); + } + + else { + long size; + UCHAR *atomData; + if (QTGetAtomDataPtr(atoms, curr, &size, (char **)&atomData) != noErr) + assert(false); + + string strapp; + for (int i = 0; i < size; i++) { + string num; + if (atomData[i] == 0) { + int count = 1; + while ((i + 1) < size && atomData[i + 1] == 0) i++, count++; + if (count > 1) { + num = std::to_string(count); + strapp = strapp + "z " + num + " "; + continue; + } + } + num = std::to_string(atomData[i]); + + strapp = strapp + string(num) + " "; + } + + // unsigned short*buffer = new unsigned short[size]; + // buffer[size]=0; + // for (i=0; i 0) - compareAtoms(atoms1, curr1, atoms2, curr2); - else { - long size1; - UCHAR *atomData1; - long size2; - UCHAR *atomData2; - if (QTGetAtomDataPtr(atoms1, curr1, &size1, (char **)&atomData1) != noErr) - assert(false); - if (QTGetAtomDataPtr(atoms2, curr2, &size2, (char **)&atomData2) != noErr) - assert(false); - assert(size1 == size2); - for (int i = 0; i < size1; i++) - assert(atomData1[i] == atomData2[i]); - } - } while (curr1 != 0 && curr2 != 0); +namespace { +void compareAtoms(const QTAtomContainer &atoms1, QTAtom parent1, + const QTAtomContainer &atoms2, QTAtom parent2) { + QTAtom curr1 = 0, curr2 = 0; + + assert(QTCountChildrenOfType(atoms1, parent1, 0) == + QTCountChildrenOfType(atoms2, parent2, 0)); + + do { + if (QTNextChildAnyType(atoms1, parent1, curr1, &curr1) != noErr) + assert(false); + + if (QTNextChildAnyType(atoms2, parent2, curr2, &curr2) != noErr) + assert(false); + assert((curr1 != 0 && curr2 != 0) || (curr1 == 0 && curr2 == 0)); + + if (curr1 == 0 || curr2 == 0) break; + + QTAtomType atomType1, atomType2; + QTAtomID id1, id2; + + QTGetAtomTypeAndID(atoms1, curr1, &atomType1, &id1); + QTGetAtomTypeAndID(atoms2, curr2, &atomType2, &id2); + assert(atomType1 == atomType2); + + int sonCount1 = QTCountChildrenOfType(atoms1, curr1, 0); + int sonCount2 = QTCountChildrenOfType(atoms2, curr2, 0); + assert(sonCount1 == sonCount2); + if (sonCount1 > 0) + compareAtoms(atoms1, curr1, atoms2, curr2); + else { + long size1; + UCHAR *atomData1; + long size2; + UCHAR *atomData2; + if (QTGetAtomDataPtr(atoms1, curr1, &size1, (char **)&atomData1) != noErr) + assert(false); + if (QTGetAtomDataPtr(atoms2, curr2, &size2, (char **)&atomData2) != noErr) + assert(false); + assert(size1 == size2); + for (int i = 0; i < size1; i++) assert(atomData1[i] == atomData2[i]); + } + } while (curr1 != 0 && curr2 != 0); } } //------------------------------------------------ -void fromAtomsToProperties(const QTAtomContainer &atoms, TPropertyGroup &pg) -{ - pg.clear(); - visitAtoms(atoms, kParentAtomIsContainer, pg); +void fromAtomsToProperties(const QTAtomContainer &atoms, TPropertyGroup &pg) { + pg.clear(); + visitAtoms(atoms, kParentAtomIsContainer, pg); } //------------------------------------------------ -void visitprops(TPropertyGroup &pg, int &index, QTAtomContainer &atoms, QTAtom parent) -{ - int count = pg.getPropertyCount(); - while (index < count) { - TStringProperty *p = (TStringProperty *)pg.getProperty(index++); - string str0 = p->getName(); - const char *buf = str0.c_str(); - int atomType, id, sonCount; - sscanf(buf, "%d %d %d", &atomType, &id, &sonCount); - QTAtom newAtom; - if (sonCount == 0) { - wstring appow = p->getValue(); - string appo = ::to_string(appow); - const char *str = appo.c_str(); - - vector buf; - while (strlen(str) > 0) { - if (str[0] == 'z') { - int count = atoi(str + 1); - str += (count < 10) ? 4 : ((count < 100) ? 5 : 6); - while (count--) - buf.push_back(0); - } else { - int val = atoi(str); - assert(val >= 0 && val < 256); - - str += (val < 10) ? 2 : ((val < 100) ? 3 : 4); - buf.push_back(val); - } - } - //const unsigned short*bufs = str1.c_str(); - //UCHAR *bufc = new UCHAR[size]; - //for (int i=0; igetName(); + const char *buf = str0.c_str(); + int atomType, id, sonCount; + sscanf(buf, "%d %d %d", &atomType, &id, &sonCount); + QTAtom newAtom; + if (sonCount == 0) { + wstring appow = p->getValue(); + string appo = ::to_string(appow); + const char *str = appo.c_str(); + + vector buf; + while (strlen(str) > 0) { + if (str[0] == 'z') { + int count = atoi(str + 1); + str += (count < 10) ? 4 : ((count < 100) ? 5 : 6); + while (count--) buf.push_back(0); + } else { + int val = atoi(str); + assert(val >= 0 && val < 256); + + str += (val < 10) ? 2 : ((val < 100) ? 3 : 4); + buf.push_back(val); + } + } + // const unsigned short*bufs = str1.c_str(); + // UCHAR *bufc = new UCHAR[size]; + // for (int i=0; iwhat) { case updateEvt: myEventWindow = (WindowRef)theEvent->message; - // Change the window class + // Change the window class HIWindowChangeClass(myEventWindow,kUtilityWindowClass); - // Activate the window scope - SetWindowActivationScope(myEventWindow,kWindowActivationScopeAll); - // Set the brushed metal theme on the window - SetThemeWindowBackground(myEventWindow,kThemeBrushUtilityWindowBackgroundActive,true); - - break; + // Activate the window scope + SetWindowActivationScope(myEventWindow,kWindowActivationScopeAll); + // Set the brushed metal theme on the window + SetThemeWindowBackground(myEventWindow,kThemeBrushUtilityWindowBackgroundActive,true); + + break; } - + return(myEventHandled); } @@ -303,41 +302,43 @@ static Boolean QTCmpr_FilterProc */ //------------------------------------------------ -void openMovSettingsPopup(TPropertyGroup *props, bool macBringToFront) -{ +void openMovSettingsPopup(TPropertyGroup *props, bool macBringToFront) { #ifdef _WIN32 - if (InitializeQTML(0) != noErr) - return; + if (InitializeQTML(0) != noErr) return; #endif - ComponentInstance ci = OpenDefaultComponent(StandardCompressionType, StandardCompressionSubType); + ComponentInstance ci = + OpenDefaultComponent(StandardCompressionType, StandardCompressionSubType); - QTAtomContainer atoms; - QTNewAtomContainer(&atoms); + QTAtomContainer atoms; + QTNewAtomContainer(&atoms); - fromPropertiesToAtoms(*props, atoms); + fromPropertiesToAtoms(*props, atoms); - ComponentResult err; + ComponentResult err; - if ((err = SCSetSettingsFromAtomContainer(ci, atoms)) != noErr) { - CloseComponent(ci); - ci = OpenDefaultComponent(StandardCompressionType, StandardCompressionSubType); - assert(false); - } + if ((err = SCSetSettingsFromAtomContainer(ci, atoms)) != noErr) { + CloseComponent(ci); + ci = OpenDefaultComponent(StandardCompressionType, + StandardCompressionSubType); + assert(false); + } - QTDisposeAtomContainer(atoms); + QTDisposeAtomContainer(atoms); #ifdef MACOSX -// Install an external procedure to use a callback filter on the request settings dialog -// On MACOSX we need to change the dialog appearance in order to pop-up in front of the +// Install an external procedure to use a callback filter on the request +// settings dialog +// On MACOSX we need to change the dialog appearance in order to pop-up in front +// of the // toonz main window. /* gProcStruct.filterProc = NewSCModalFilterUPP(QTCmpr_FilterProc); // I don't install any hook gProcStruct.hookProc = NULL; gProcStruct.customName[0] = 0; -// I don't use refcon +// I don't use refcon gProcStruct.refcon = 0; // set the current extended procs @@ -345,52 +346,50 @@ SCSetInfo(ci, scExtendedProcsType, &gProcStruct); */ #endif - err = SCRequestSequenceSettings(ci); - //assert(err==noErr); - QTAtomContainer atomsOut; + err = SCRequestSequenceSettings(ci); + // assert(err==noErr); + QTAtomContainer atomsOut; - if (SCGetSettingsAsAtomContainer(ci, &atomsOut) != noErr) - assert(false); + if (SCGetSettingsAsAtomContainer(ci, &atomsOut) != noErr) assert(false); - fromAtomsToProperties(atomsOut, *props); + fromAtomsToProperties(atomsOut, *props); - QTDisposeAtomContainer(atomsOut); - CloseComponent(ci); + QTDisposeAtomContainer(atomsOut); + CloseComponent(ci); - //int dataSize=0, numChildren = 0, numLevels=0; - //retrieveData(settings, kParentAtomIsContainer, dataSize, numChildren, numLevels); + // int dataSize=0, numChildren = 0, numLevels=0; + // retrieveData(settings, kParentAtomIsContainer, dataSize, numChildren, + // numLevels); } -bool Tiio::isQuicktimeInstalled() -{ +bool Tiio::isQuicktimeInstalled() { #ifdef MACOSX - return true; + return true; #else - static int ret = -1; - if (ret == -1) - ret = (InitializeQTML(0) == noErr) ? 1 : 0; + static int ret = -1; + if (ret == -1) ret = (InitializeQTML(0) == noErr) ? 1 : 0; - return (ret == 1); + return (ret == 1); #endif } -#else //x64 +#else // x64 //******************************************************************************* // 64-bit proxied version //******************************************************************************* -//Toonz includes +// Toonz includes #include "tfilepath.h" #include "tstream.h" -//tipc includes +// tipc includes #include "tipc.h" #include "t32bitsrv_wrap.h" -//MAC-Specific includes +// MAC-Specific includes #ifdef MACOSX #include #endif @@ -399,69 +398,70 @@ bool Tiio::isQuicktimeInstalled() //--------------------------------------------------------------------------- -//Using 32-bit background server correspondence to achieve the same result -void openMovSettingsPopup(TPropertyGroup *props, bool unused) -{ - QLocalSocket socket; - if (!tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), 3000, t32bitsrv::srvCmdline(), "_main")) - return; - - //Send the appropriate commands to the server - tipc::Stream stream(&socket); - tipc::Message msg; - - //We'll communicate through temporary files. - stream << (msg << QString("$tmpfile_request") << QString("openMovSets")); - QString res(tipc::readMessage(stream, msg)); - - QString fp; - msg >> fp; - assert(res == "ok" && !fp.isEmpty()); - - TFilePath tfp(fp.toStdWString()); - { - //Save the input props to the temporary file - TOStream os(tfp); - props->saveData(os); - } - - //Invoke the settings popup - stream << (msg << tipc::clr << QString("$openMovSettingsPopup") << fp); - res = tipc::readMessageNB(stream, msg, -1, QEventLoop::ExcludeUserInputEvents); - assert(res == "ok"); +// Using 32-bit background server correspondence to achieve the same result +void openMovSettingsPopup(TPropertyGroup *props, bool unused) { + QLocalSocket socket; + if (!tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), 3000, + t32bitsrv::srvCmdline(), "_main")) + return; + + // Send the appropriate commands to the server + tipc::Stream stream(&socket); + tipc::Message msg; + + // We'll communicate through temporary files. + stream << (msg << QString("$tmpfile_request") << QString("openMovSets")); + QString res(tipc::readMessage(stream, msg)); + + QString fp; + msg >> fp; + assert(res == "ok" && !fp.isEmpty()); + + TFilePath tfp(fp.toStdWString()); + { + // Save the input props to the temporary file + TOStream os(tfp); + props->saveData(os); + } + + // Invoke the settings popup + stream << (msg << tipc::clr << QString("$openMovSettingsPopup") << fp); + res = + tipc::readMessageNB(stream, msg, -1, QEventLoop::ExcludeUserInputEvents); + assert(res == "ok"); #ifdef MACOSX - //Bring this application back to front - ProcessSerialNumber psn = {0, kCurrentProcess}; - SetFrontProcess(&psn); + // Bring this application back to front + ProcessSerialNumber psn = {0, kCurrentProcess}; + SetFrontProcess(&psn); -#endif //MACOSX +#endif // MACOSX - props->clear(); - { - //Save the input props to the temporary file - TIStream is(tfp); - props->loadData(is); - } + props->clear(); + { + // Save the input props to the temporary file + TIStream is(tfp); + props->loadData(is); + } - //Release the temporary file - stream << (msg << tipc::clr << QString("$tmpfile_release") << QString("openMovSets")); - res = tipc::readMessage(stream, msg); - assert(res == "ok"); + // Release the temporary file + stream << (msg << tipc::clr << QString("$tmpfile_release") + << QString("openMovSets")); + res = tipc::readMessage(stream, msg); + assert(res == "ok"); } //--------------------------------------------------------------------------- -bool Tiio::isQuicktimeInstalled() -{ - //NOTE: This is *NOT* the same function as IsQuickTimeInstalled(), which is - //implemented locally in the image lib and used there. This function here is - //actually NEVER USED throughout Toonz, so we're placing a dummy - //implementation here. +bool Tiio::isQuicktimeInstalled() { + // NOTE: This is *NOT* the same function as IsQuickTimeInstalled(), which is + // implemented locally in the image lib and used there. This function here is + // actually NEVER USED throughout Toonz, so we're placing a dummy + // implementation here. - assert(false); - return false; + assert(false); + return false; } -#endif //else +#endif // else diff --git a/toonz/sources/common/tiio/tiio.cpp b/toonz/sources/common/tiio/tiio.cpp index 4c3fe02..9c7b4f4 100644 --- a/toonz/sources/common/tiio/tiio.cpp +++ b/toonz/sources/common/tiio/tiio.cpp @@ -21,187 +21,161 @@ #include //-------------------- -namespace -{ +namespace { -class TiioTable -{ // singleton +class TiioTable { // singleton public: - typedef std::map - ReaderTable; - - typedef std::map> - WriterTable; - - typedef std::map - VectorReaderTable; - - typedef std::map> - VectorWriterTable; - - typedef std::map - PropertiesTable; - - ReaderTable m_readers; - WriterTable m_writers; - VectorReaderTable m_vectorReaders; - VectorWriterTable m_vectorWriters; - PropertiesTable m_writerProperties; - - TiioTable() { initialize(); } - - static TiioTable *instance() - { - static TiioTable theTable; - return &theTable; - } - ~TiioTable() - { - for (PropertiesTable::iterator it = m_writerProperties.begin(); - it != m_writerProperties.end(); ++it) - delete it->second; - } - - void add(std::string ext, Tiio::ReaderMaker *fn) - { - m_readers[ext] = fn; - } - void add(std::string ext, Tiio::WriterMaker *fn, bool isRenderFormat) - { - m_writers[ext] = std::pair(fn, isRenderFormat); - } - void add(std::string ext, Tiio::VectorReaderMaker *fn) - { - m_vectorReaders[ext] = fn; - } - void add(std::string ext, Tiio::VectorWriterMaker *fn, bool isRenderFormat) - { - m_vectorWriters[ext] = std::pair(fn, isRenderFormat); - } - void addWriterProperties(std::string ext, TPropertyGroup *prop) - { - m_writerProperties[ext] = prop; - } - - Tiio::ReaderMaker *findReader(std::string ext) const - { - ReaderTable::const_iterator it = m_readers.find(ext); - if (it == m_readers.end()) - return 0; - else - return it->second; - } - Tiio::WriterMaker *findWriter(std::string ext) const - { - WriterTable::const_iterator it = m_writers.find(ext); - if (it == m_writers.end()) - return 0; - else - return it->second.first; - } - Tiio::VectorReaderMaker *findVectorReader(std::string ext) const - { - VectorReaderTable::const_iterator it = m_vectorReaders.find(ext); - if (it == m_vectorReaders.end()) - return 0; - else - return it->second; - } - Tiio::VectorWriterMaker *findVectorWriter(std::string ext) const - { - VectorWriterTable::const_iterator it = m_vectorWriters.find(ext); - if (it == m_vectorWriters.end()) - return 0; - else - return it->second.first; - } - TPropertyGroup *findWriterProperties(std::string ext) const - { - PropertiesTable::const_iterator it = m_writerProperties.find(ext); - if (it == m_writerProperties.end()) - return 0; - else - return it->second; - } - - void initialize(); + typedef std::map ReaderTable; + + typedef std::map> + WriterTable; + + typedef std::map VectorReaderTable; + + typedef std::map> + VectorWriterTable; + + typedef std::map PropertiesTable; + + ReaderTable m_readers; + WriterTable m_writers; + VectorReaderTable m_vectorReaders; + VectorWriterTable m_vectorWriters; + PropertiesTable m_writerProperties; + + TiioTable() { initialize(); } + + static TiioTable *instance() { + static TiioTable theTable; + return &theTable; + } + ~TiioTable() { + for (PropertiesTable::iterator it = m_writerProperties.begin(); + it != m_writerProperties.end(); ++it) + delete it->second; + } + + void add(std::string ext, Tiio::ReaderMaker *fn) { m_readers[ext] = fn; } + void add(std::string ext, Tiio::WriterMaker *fn, bool isRenderFormat) { + m_writers[ext] = std::pair(fn, isRenderFormat); + } + void add(std::string ext, Tiio::VectorReaderMaker *fn) { + m_vectorReaders[ext] = fn; + } + void add(std::string ext, Tiio::VectorWriterMaker *fn, bool isRenderFormat) { + m_vectorWriters[ext] = + std::pair(fn, isRenderFormat); + } + void addWriterProperties(std::string ext, TPropertyGroup *prop) { + m_writerProperties[ext] = prop; + } + + Tiio::ReaderMaker *findReader(std::string ext) const { + ReaderTable::const_iterator it = m_readers.find(ext); + if (it == m_readers.end()) + return 0; + else + return it->second; + } + Tiio::WriterMaker *findWriter(std::string ext) const { + WriterTable::const_iterator it = m_writers.find(ext); + if (it == m_writers.end()) + return 0; + else + return it->second.first; + } + Tiio::VectorReaderMaker *findVectorReader(std::string ext) const { + VectorReaderTable::const_iterator it = m_vectorReaders.find(ext); + if (it == m_vectorReaders.end()) + return 0; + else + return it->second; + } + Tiio::VectorWriterMaker *findVectorWriter(std::string ext) const { + VectorWriterTable::const_iterator it = m_vectorWriters.find(ext); + if (it == m_vectorWriters.end()) + return 0; + else + return it->second.first; + } + TPropertyGroup *findWriterProperties(std::string ext) const { + PropertiesTable::const_iterator it = m_writerProperties.find(ext); + if (it == m_writerProperties.end()) + return 0; + else + return it->second; + } + + void initialize(); }; -} // namespace +} // namespace //========================================================= -void TiioTable::initialize() -{ -} +void TiioTable::initialize() {} -Tiio::Reader *Tiio::makeReader(std::string ext) -{ - Tiio::ReaderMaker *reader = TiioTable::instance()->findReader(ext); - if (!reader) - return 0; - else - return reader(); +Tiio::Reader *Tiio::makeReader(std::string ext) { + Tiio::ReaderMaker *reader = TiioTable::instance()->findReader(ext); + if (!reader) + return 0; + else + return reader(); } -Tiio::Writer *Tiio::makeWriter(std::string ext) -{ - Tiio::WriterMaker *writer = TiioTable::instance()->findWriter(ext); - if (!writer) - return 0; - else - return writer(); +Tiio::Writer *Tiio::makeWriter(std::string ext) { + Tiio::WriterMaker *writer = TiioTable::instance()->findWriter(ext); + if (!writer) + return 0; + else + return writer(); } -Tiio::VectorReader *Tiio::makeVectorReader(std::string ext) -{ - Tiio::VectorReaderMaker *reader = TiioTable::instance()->findVectorReader(ext); - if (!reader) - return 0; - else - return reader(); +Tiio::VectorReader *Tiio::makeVectorReader(std::string ext) { + Tiio::VectorReaderMaker *reader = + TiioTable::instance()->findVectorReader(ext); + if (!reader) + return 0; + else + return reader(); } -Tiio::VectorWriter *Tiio::makeVectorWriter(std::string ext) -{ - Tiio::VectorWriterMaker *writer = TiioTable::instance()->findVectorWriter(ext); - if (!writer) - return 0; - else - return writer(); +Tiio::VectorWriter *Tiio::makeVectorWriter(std::string ext) { + Tiio::VectorWriterMaker *writer = + TiioTable::instance()->findVectorWriter(ext); + if (!writer) + return 0; + else + return writer(); } -TPropertyGroup *Tiio::makeWriterProperties(std::string ext) -{ - TPropertyGroup *prop = TiioTable::instance()->findWriterProperties(ext); - if (!prop) - return new TPropertyGroup(); - return prop->clone(); +TPropertyGroup *Tiio::makeWriterProperties(std::string ext) { + TPropertyGroup *prop = TiioTable::instance()->findWriterProperties(ext); + if (!prop) return new TPropertyGroup(); + return prop->clone(); } -void Tiio::defineReaderMaker(const char *ext, Tiio::ReaderMaker *fn) -{ - TiioTable::instance()->add(ext, fn); +void Tiio::defineReaderMaker(const char *ext, Tiio::ReaderMaker *fn) { + TiioTable::instance()->add(ext, fn); } -void Tiio::defineWriterMaker(const char *ext, Tiio::WriterMaker *fn, bool isRenderFormat) -{ - TiioTable::instance()->add(ext, fn, isRenderFormat); +void Tiio::defineWriterMaker(const char *ext, Tiio::WriterMaker *fn, + bool isRenderFormat) { + TiioTable::instance()->add(ext, fn, isRenderFormat); } -void Tiio::defineVectorReaderMaker(const char *ext, Tiio::VectorReaderMaker *fn) -{ - TiioTable::instance()->add(ext, fn); +void Tiio::defineVectorReaderMaker(const char *ext, + Tiio::VectorReaderMaker *fn) { + TiioTable::instance()->add(ext, fn); } -void Tiio::defineVectorWriterMaker(const char *ext, Tiio::VectorWriterMaker *fn, bool isRenderFormat) -{ - TiioTable::instance()->add(ext, fn, isRenderFormat); +void Tiio::defineVectorWriterMaker(const char *ext, Tiio::VectorWriterMaker *fn, + bool isRenderFormat) { + TiioTable::instance()->add(ext, fn, isRenderFormat); } -void Tiio::defineWriterProperties(const char *ext, TPropertyGroup *prop) -{ - TiioTable::instance()->addWriterProperties(ext, prop); +void Tiio::defineWriterProperties(const char *ext, TPropertyGroup *prop) { + TiioTable::instance()->addWriterProperties(ext, prop); } /* @@ -214,7 +188,7 @@ int Tiio::openForReading(char *fn) fprintf(stderr, "File not found\n"); exit(1); } - return fd; + return fd; } void* Tiio::openForReading2(char *fn) @@ -232,7 +206,7 @@ void* Tiio::openForReading2(char *fn) int Tiio::openForWriting(char *fn) { int fd = _open( - fn, + fn, _O_BINARY | _O_WRONLY | _O_CREAT | _O_TRUNC, _S_IREAD | _S_IWRITE); if(fd == -1) @@ -240,48 +214,42 @@ int Tiio::openForWriting(char *fn) fprintf(stderr, "Can't open file\n"); exit(1); } - return fd; + return fd; } #endif */ -Tiio::Reader::Reader() -{ -} +Tiio::Reader::Reader() {} -Tiio::Reader::~Reader() -{ -} +Tiio::Reader::~Reader() {} int Tiio::Writer::m_bwThreshold = 128; -Tiio::Writer::Writer() - : m_properties(0) -{ -} +Tiio::Writer::Writer() : m_properties(0) {} -Tiio::Writer::~Writer() -{ -} +Tiio::Writer::~Writer() {} -void Tiio::Writer::getSupportedFormats(QStringList &formats, bool onlyRenderFormats) -{ - TiioTable::VectorWriterTable::const_iterator vit = TiioTable::instance()->m_vectorWriters.begin(); - TiioTable::VectorWriterTable::const_iterator vit_e = TiioTable::instance()->m_vectorWriters.end(); - for (; vit != vit_e; ++vit) - if (onlyRenderFormats && vit->second.second) - formats.push_back(QString::fromStdString(vit->first)); - TiioTable::WriterTable::const_iterator it = TiioTable::instance()->m_writers.begin(); - TiioTable::WriterTable::const_iterator it_e = TiioTable::instance()->m_writers.end(); - for (; it != it_e; ++it) - if (onlyRenderFormats && it->second.second) - formats.push_back(QString::fromStdString(it->first)); +void Tiio::Writer::getSupportedFormats(QStringList &formats, + bool onlyRenderFormats) { + TiioTable::VectorWriterTable::const_iterator vit = + TiioTable::instance()->m_vectorWriters.begin(); + TiioTable::VectorWriterTable::const_iterator vit_e = + TiioTable::instance()->m_vectorWriters.end(); + for (; vit != vit_e; ++vit) + if (onlyRenderFormats && vit->second.second) + formats.push_back(QString::fromStdString(vit->first)); + TiioTable::WriterTable::const_iterator it = + TiioTable::instance()->m_writers.begin(); + TiioTable::WriterTable::const_iterator it_e = + TiioTable::instance()->m_writers.end(); + for (; it != it_e; ++it) + if (onlyRenderFormats && it->second.second) + formats.push_back(QString::fromStdString(it->first)); } //----------------------------------------------------- -void Tiio::Writer::setProperties(TPropertyGroup *properties) -{ - m_properties = properties ? properties->clone() : 0; +void Tiio::Writer::setProperties(TPropertyGroup *properties) { + m_properties = properties ? properties->clone() : 0; } diff --git a/toonz/sources/common/tiio/tiio_bmp.cpp b/toonz/sources/common/tiio/tiio_bmp.cpp index adf4639..1c98680 100644 --- a/toonz/sources/common/tiio/tiio_bmp.cpp +++ b/toonz/sources/common/tiio/tiio_bmp.cpp @@ -14,818 +14,736 @@ //========================================================= -namespace -{ +namespace { //========================================================= -typedef struct - { - UINT bfSize; - UINT bfOffBits; - UINT biSize; - UINT biWidth; - UINT biHeight; - UINT biPlanes; - UINT biBitCount; - UINT biCompression; - UINT biSizeImage; - UINT biXPelsPerMeter; - UINT biYPelsPerMeter; - UINT biClrUsed; - UINT biClrImportant; - UINT biFilesize; - UINT biPad; +typedef struct { + UINT bfSize; + UINT bfOffBits; + UINT biSize; + UINT biWidth; + UINT biHeight; + UINT biPlanes; + UINT biBitCount; + UINT biCompression; + UINT biSizeImage; + UINT biXPelsPerMeter; + UINT biYPelsPerMeter; + UINT biClrUsed; + UINT biClrImportant; + UINT biFilesize; + UINT biPad; } BMP_HEADER; const int BMP_WIN_SIZE = 40; const int BMP_OS2_SIZE = 64; -const int BMP_BI_RGB = 0; +const int BMP_BI_RGB = 0; const int BMP_BI_RLE8 = 1; const int BMP_BI_RLE4 = 2; //========================================================= -UINT getshort(FILE *fp) -{ - int c = getc(fp), - c1 = getc(fp); +UINT getshort(FILE *fp) { + int c = getc(fp), c1 = getc(fp); - return ((UINT)c) + (((UINT)c1) << 8); + return ((UINT)c) + (((UINT)c1) << 8); } //--------------------------------------------------------- -UINT getint(FILE *fp) -{ - int c = getc(fp), - c1 = getc(fp), - c2 = getc(fp), - c3 = getc(fp); - - return (((UINT)c) << 0) + - (((UINT)c1) << 8) + - (((UINT)c2) << 16) + - (((UINT)c3) << 24); +UINT getint(FILE *fp) { + int c = getc(fp), c1 = getc(fp), c2 = getc(fp), c3 = getc(fp); + + return (((UINT)c) << 0) + (((UINT)c1) << 8) + (((UINT)c2) << 16) + + (((UINT)c3) << 24); } //--------------------------------------------------------- -void putshort(FILE *fp, int i) -{ - int c = (((UINT)i)) & 0xff, - c1 = (((UINT)i) >> 8) & 0xff; +void putshort(FILE *fp, int i) { + int c = (((UINT)i)) & 0xff, c1 = (((UINT)i) >> 8) & 0xff; - putc(c, fp); - putc(c1, fp); + putc(c, fp); + putc(c1, fp); } //--------------------------------------------------------- -void putint(FILE *fp, int i) -{ - int c = ((UINT)i) & 0xff, - c1 = (((UINT)i) >> 8) & 0xff, - c2 = (((UINT)i) >> 16) & 0xff, - c3 = (((UINT)i) >> 24) & 0xff; - - putc(c, fp); - putc(c1, fp); - putc(c2, fp); - putc(c3, fp); +void putint(FILE *fp, int i) { + int c = ((UINT)i) & 0xff, c1 = (((UINT)i) >> 8) & 0xff, + c2 = (((UINT)i) >> 16) & 0xff, c3 = (((UINT)i) >> 24) & 0xff; + + putc(c, fp); + putc(c1, fp); + putc(c2, fp); + putc(c3, fp); } //========================================================= -} // namespace +} // namespace //========================================================= -class BmpReader : public Tiio::Reader -{ - FILE *m_chan; - BMP_HEADER m_header; - char *m_line; - int m_lineSize; - std::unique_ptr m_cmap; - bool m_corrupted; - typedef int (BmpReader::*ReadLineMethod)(char *buffer, int x0, int x1, int shrink); - ReadLineMethod m_readLineMethod; +class BmpReader : public Tiio::Reader { + FILE *m_chan; + BMP_HEADER m_header; + char *m_line; + int m_lineSize; + std::unique_ptr m_cmap; + bool m_corrupted; + typedef int (BmpReader::*ReadLineMethod)(char *buffer, int x0, int x1, + int shrink); + ReadLineMethod m_readLineMethod; public: - BmpReader(); - ~BmpReader(); - - void open(FILE *file); - - int readNoLine(char *buffer, int x0, int x1, int shrink); - - void skipBytes(int count) - { - //fseek(m_chan, count, SEEK_CUR); //inefficiente se count è piccolo - for (int i = 0; i < count; i++) { - getc(m_chan); - } - } - - int read1Line(char *buffer, int x0, int x1, int shrink); - int read4Line(char *buffer, int x0, int x1, int shrink); - int read8Line(char *buffer, int x0, int x1, int shrink); - int read8LineRle(char *buffer, int x0, int x1, int shrink); - int read16m555Line(char *buffer, int x0, int x1, int shrink); - int read16m565Line(char *buffer, int x0, int x1, int shrink); - int read24Line(char *buffer, int x0, int x1, int shrink); - int read32Line(char *buffer, int x0, int x1, int shrink); - - void readLine(char *buffer, int x0, int x1, int shrink); - int skipLines(int lineCount) - { - fseek(m_chan, lineCount * m_lineSize, SEEK_CUR); - /* for(int i=0;ibiSize != BMP_WIN_OS2_OLD) { - if (!m_chan) - return; - - fseek(m_chan, 0L, SEEK_END); - m_header.biFilesize = ftell(m_chan); - fseek(m_chan, 0L, 0); - - /* read the file type (first two bytes) */ - char signature[2]; - signature[0] = fgetc(m_chan); - signature[1] = fgetc(m_chan); - if (signature[0] != 'B' || signature[1] != 'M') { - m_corrupted = true; - return; - } - - m_header.bfSize = getint(m_chan); - - /* reserved and ignored */ - getshort(m_chan); - getshort(m_chan); - - m_header.bfOffBits = getint(m_chan); - m_header.biSize = getint(m_chan); - - if ((int)m_header.biSize == BMP_WIN_SIZE || - (int)m_header.biSize == BMP_OS2_SIZE) { - m_header.biWidth = getint(m_chan); - m_header.biHeight = getint(m_chan); - m_header.biPlanes = getshort(m_chan); - m_header.biBitCount = getshort(m_chan); - m_header.biCompression = getint(m_chan); - m_header.biSizeImage = getint(m_chan); - m_header.biXPelsPerMeter = getint(m_chan); - m_header.biYPelsPerMeter = getint(m_chan); - m_header.biClrUsed = getint(m_chan); - m_header.biClrImportant = getint(m_chan); - } else // old bitmap format - { - m_header.biWidth = getshort(m_chan); - m_header.biHeight = getshort(m_chan); - m_header.biPlanes = getshort(m_chan); - m_header.biBitCount = getshort(m_chan); - - /* Not in old versions so have to compute them */ - m_header.biSizeImage = - (((m_header.biPlanes * m_header.biBitCount * - m_header.biWidth) + - 31) / - 32) * - 4 * m_header.biHeight; - - m_header.biCompression = BMP_BI_RGB; - m_header.biXPelsPerMeter = 0; - m_header.biYPelsPerMeter = 0; - m_header.biClrUsed = 0; - m_header.biClrImportant = 0; - } - m_header.biPad = 0; - - m_info.m_lx = m_header.biWidth; - m_info.m_ly = m_header.biHeight; - - /* - BMP_HEADER *hd = m_header; - if ((int)hd->biSize != BMP_WIN_OS2_OLD) - { - // skip ahead to colormap, using biSize - int c = hd->biSize - 40; // 40 bytes read from biSize to biClrImportant - for (int i=0; ibiPad = hd->bfOffBits - (hd->biSize + 14); - } - else - hd->biPad = 0; +// skip ahead to colormap, using biSize +int c = hd->biSize - 40; // 40 bytes read from biSize to biClrImportant +for (int i=0; ibiPad = hd->bfOffBits - (hd->biSize + 14); +} +else +hd->biPad = 0; */ - // load up colormap, if any - if (m_header.biBitCount < 16) { - int cmaplen = (m_header.biClrUsed) - ? m_header.biClrUsed - : 1 << m_header.biBitCount; - assert(cmaplen <= 256); - m_cmap.reset(new TPixel[256]); - TPixel32 *pix = m_cmap.get(); - for (int i = 0; i < cmaplen; i++) { - pix->b = getc(m_chan); - pix->g = getc(m_chan); - pix->r = getc(m_chan); - pix->m = 255; - getc(m_chan); - ++pix; - } - } - - /* - if (hd->biSize != BMP_WIN_OS2_OLD) - { - // Waste any unused bytes between the colour map (if present) - // and the start of the actual bitmap data. - while (hd->biPad > 0) - { - (void) getc(m_chan); - hd->biPad--; - } - } - */ - // get information about the portion of the image to load - //get_info_region(&info, x1, y1, x2, y2, scale, - // (int)hd->biWidth, (int)hd->biHeight, TNZ_BOTLEFT); - - // skip_bmp_lines(fp, hd->biWidth, (unsigned int)(info.startScanRow-1), (unsigned int)SEEK_CUR, subtype); - - int lx = m_info.m_lx; - - switch (m_header.biBitCount) { - case 1: - m_info.m_samplePerPixel = 1; - m_readLineMethod = &BmpReader::read1Line; - m_lineSize = (lx + 7) / 8; - break; - case 4: - m_info.m_samplePerPixel = 1; - if (m_header.biCompression == 0) - m_readLineMethod = &BmpReader::read4Line; - m_lineSize = (lx + 1) / 2; - break; - case 8: - m_info.m_samplePerPixel = 1; - if (m_header.biCompression == 0) - m_readLineMethod = &BmpReader::read8Line; - else if (m_header.biCompression == 1) - m_readLineMethod = &BmpReader::read8LineRle; - m_lineSize = lx; - break; - case 16: - m_info.m_samplePerPixel = 3; - if (m_header.biCompression == 0) // BI_RGB - m_readLineMethod = &BmpReader::read16m555Line; - else if (m_header.biCompression == 3) // BI_BITFIELDS - { - unsigned int rmask = 0, gmask = 0, bmask = 0; - rmask = getint(m_chan); - gmask = getint(m_chan); - bmask = getint(m_chan); - if (gmask == 0x7E0) - m_readLineMethod = &BmpReader::read16m565Line; - else - m_readLineMethod = &BmpReader::read16m555Line; - } - m_lineSize = lx * 2; - break; - case 24: - m_info.m_samplePerPixel = 3; - m_readLineMethod = &BmpReader::read24Line; - m_lineSize = lx * 3; - break; - case 32: - m_info.m_samplePerPixel = 3; - m_readLineMethod = &BmpReader::read32Line; - m_lineSize = lx * 4; - break; - } - m_lineSize += 3 - ((m_lineSize + 3) & 3); - fseek(m_chan, m_header.bfOffBits, SEEK_SET); + // load up colormap, if any + if (m_header.biBitCount < 16) { + int cmaplen = + (m_header.biClrUsed) ? m_header.biClrUsed : 1 << m_header.biBitCount; + assert(cmaplen <= 256); + m_cmap.reset(new TPixel[256]); + TPixel32 *pix = m_cmap.get(); + for (int i = 0; i < cmaplen; i++) { + pix->b = getc(m_chan); + pix->g = getc(m_chan); + pix->r = getc(m_chan); + pix->m = 255; + getc(m_chan); + ++pix; + } + } + + /* +if (hd->biSize != BMP_WIN_OS2_OLD) +{ +// Waste any unused bytes between the colour map (if present) +// and the start of the actual bitmap data. +while (hd->biPad > 0) +{ + (void) getc(m_chan); + hd->biPad--; +} +} +*/ + // get information about the portion of the image to load + // get_info_region(&info, x1, y1, x2, y2, scale, + // (int)hd->biWidth, (int)hd->biHeight, TNZ_BOTLEFT); + + // skip_bmp_lines(fp, hd->biWidth, (unsigned int)(info.startScanRow-1), + // (unsigned int)SEEK_CUR, subtype); + + int lx = m_info.m_lx; + + switch (m_header.biBitCount) { + case 1: + m_info.m_samplePerPixel = 1; + m_readLineMethod = &BmpReader::read1Line; + m_lineSize = (lx + 7) / 8; + break; + case 4: + m_info.m_samplePerPixel = 1; + if (m_header.biCompression == 0) m_readLineMethod = &BmpReader::read4Line; + m_lineSize = (lx + 1) / 2; + break; + case 8: + m_info.m_samplePerPixel = 1; + if (m_header.biCompression == 0) + m_readLineMethod = &BmpReader::read8Line; + else if (m_header.biCompression == 1) + m_readLineMethod = &BmpReader::read8LineRle; + m_lineSize = lx; + break; + case 16: + m_info.m_samplePerPixel = 3; + if (m_header.biCompression == 0) // BI_RGB + m_readLineMethod = &BmpReader::read16m555Line; + else if (m_header.biCompression == 3) // BI_BITFIELDS + { + unsigned int rmask = 0, gmask = 0, bmask = 0; + rmask = getint(m_chan); + gmask = getint(m_chan); + bmask = getint(m_chan); + if (gmask == 0x7E0) + m_readLineMethod = &BmpReader::read16m565Line; + else + m_readLineMethod = &BmpReader::read16m555Line; + } + m_lineSize = lx * 2; + break; + case 24: + m_info.m_samplePerPixel = 3; + m_readLineMethod = &BmpReader::read24Line; + m_lineSize = lx * 3; + break; + case 32: + m_info.m_samplePerPixel = 3; + m_readLineMethod = &BmpReader::read32Line; + m_lineSize = lx * 4; + break; + } + m_lineSize += 3 - ((m_lineSize + 3) & 3); + fseek(m_chan, m_header.bfOffBits, SEEK_SET); } //--------------------------------------------------------- -void BmpReader::readLine(char *buffer, int x0, int x1, int shrink) -{ - (this->*m_readLineMethod)(buffer, x0, x1, shrink); +void BmpReader::readLine(char *buffer, int x0, int x1, int shrink) { + (this->*m_readLineMethod)(buffer, x0, x1, shrink); } //--------------------------------------------------------- -int BmpReader::readNoLine(char *buffer, int x0, int x1, int shrink) -{ - skipBytes(m_lineSize); - return 0; +int BmpReader::readNoLine(char *buffer, int x0, int x1, int shrink) { + skipBytes(m_lineSize); + return 0; } //--------------------------------------------------------- -int BmpReader::read1Line(char *buffer, int x0, int x1, int shrink) +int BmpReader::read1Line(char *buffer, int x0, int x1, int shrink) { + TPixel32 *pix = (TPixel32 *)buffer; + + // pix += x0; + if (x0 > 0) skipBytes(x0 / 8); + + TPixel32 *endPix = pix + x1 + 1; + + int value = 0; + int index = x0; + + if (x0 % 8 != 0) { + value = getc(m_chan); + for (index = x0; index < x0 + 8 - (x0 % 8); index += shrink) { + pix[index] = m_cmap[(value >> (7 - ((index) % 8))) & 1]; + } + } + value = getc(m_chan); + int prevBlock = index / 8; + for (int j = index; pix + j < endPix; j += shrink) { + if (j / 8 > prevBlock) value = getc(m_chan); + prevBlock = j / 8; + pix[j] = m_cmap[(value >> (7 - (j % 8))) & 1]; + } + + /* +while(pix+8<=endPix) { - TPixel32 *pix = (TPixel32 *)buffer; - - //pix += x0; - if (x0 > 0) - skipBytes(x0 / 8); - - TPixel32 *endPix = pix + x1 + 1; - - int value = 0; - int index = x0; - - if (x0 % 8 != 0) { - value = getc(m_chan); - for (index = x0; index < x0 + 8 - (x0 % 8); index += shrink) { - pix[index] = m_cmap[(value >> (7 - ((index) % 8))) & 1]; - } - } - value = getc(m_chan); - int prevBlock = index / 8; - for (int j = index; pix + j < endPix; j += shrink) { - if (j / 8 > prevBlock) - value = getc(m_chan); - prevBlock = j / 8; - pix[j] = m_cmap[(value >> (7 - (j % 8))) & 1]; - } - - /* - while(pix+8<=endPix) - { - value = getc(m_chan); - pix[0] = m_cmap[(value>>7)&1]; - pix[1] = m_cmap[(value>>6)&1]; - pix[2] = m_cmap[(value>>5)&1]; - pix[3] = m_cmap[(value>>4)&1]; - pix[4] = m_cmap[(value>>3)&1]; - pix[5] = m_cmap[(value>>2)&1]; - pix[6] = m_cmap[(value>>1)&1]; - pix[7] = m_cmap[(value>>0)&1]; - pix +=8*shrink; - if(shrink>1) value = getc(m_chan); - //pix+=8*shrink; - //if(pix+81) skipBytes(shrink-1); - } - if(pix=endPix); - for(int j=0; pix+j>(7-j))&1]; - } */ - if ((m_info.m_lx - x1) / 8 > 0) { - skipBytes((m_info.m_lx - x1) / 8); - } - - int bytes = (m_info.m_lx + 7) / 8; - if (m_lineSize - bytes > 0) - skipBytes(m_lineSize - bytes); - return 0; +value = getc(m_chan); +pix[0] = m_cmap[(value>>7)&1]; +pix[1] = m_cmap[(value>>6)&1]; +pix[2] = m_cmap[(value>>5)&1]; +pix[3] = m_cmap[(value>>4)&1]; +pix[4] = m_cmap[(value>>3)&1]; +pix[5] = m_cmap[(value>>2)&1]; +pix[6] = m_cmap[(value>>1)&1]; +pix[7] = m_cmap[(value>>0)&1]; + pix +=8*shrink; + if(shrink>1) value = getc(m_chan); +//pix+=8*shrink; + //if(pix+81) skipBytes(shrink-1); +} +if(pix=endPix); +for(int j=0; pix+j>(7-j))&1]; +} */ + if ((m_info.m_lx - x1) / 8 > 0) { + skipBytes((m_info.m_lx - x1) / 8); + } + + int bytes = (m_info.m_lx + 7) / 8; + if (m_lineSize - bytes > 0) skipBytes(m_lineSize - bytes); + return 0; } //--------------------------------------------------------- -int BmpReader::read4Line(char *buffer, int x0, int x1, int shrink) -{ - TPixel32 *pix = (TPixel32 *)buffer; - pix += 2 * x0; - if (x0 > 0) - skipBytes(x0 / 2); - TPixel32 *endPix = pix + x1 - x0 + 1; - - int value; - while (pix + 2 <= endPix) { - value = getc(m_chan); - pix[0] = m_cmap[value & 0xF]; - pix[1] = m_cmap[(value >> 4) & 0xF]; - //pix+=2*shrink; - pix++; - //if(pix+2<=endPix && shrink>1) skipBytes(shrink-1); - } - if (pix < endPix) { - value = getc(m_chan); - pix[0] = m_cmap[value & 0xF]; - } - if ((m_info.m_lx - x1) / 2 > 0) { - skipBytes((m_info.m_lx - x1) / 2); - } - - int bytes = (m_info.m_lx + 1) / 2; - if (m_lineSize - bytes) - skipBytes(m_lineSize - bytes); - return 0; +int BmpReader::read4Line(char *buffer, int x0, int x1, int shrink) { + TPixel32 *pix = (TPixel32 *)buffer; + pix += 2 * x0; + if (x0 > 0) skipBytes(x0 / 2); + TPixel32 *endPix = pix + x1 - x0 + 1; + + int value; + while (pix + 2 <= endPix) { + value = getc(m_chan); + pix[0] = m_cmap[value & 0xF]; + pix[1] = m_cmap[(value >> 4) & 0xF]; + // pix+=2*shrink; + pix++; + // if(pix+2<=endPix && shrink>1) skipBytes(shrink-1); + } + if (pix < endPix) { + value = getc(m_chan); + pix[0] = m_cmap[value & 0xF]; + } + if ((m_info.m_lx - x1) / 2 > 0) { + skipBytes((m_info.m_lx - x1) / 2); + } + + int bytes = (m_info.m_lx + 1) / 2; + if (m_lineSize - bytes) skipBytes(m_lineSize - bytes); + return 0; } //--------------------------------------------------------- -int BmpReader::read8Line(char *buffer, int x0, int x1, int shrink) -{ - TPixel32 *pix = (TPixel32 *)buffer; - - if (x0 > 0) - skipBytes(x0); - pix += x0; - TPixel32 *endPix = pix + x1 - x0 + 1; - - while (pix < endPix) { - int value = getc(m_chan); - *pix++ = m_cmap[value]; - if (pix < endPix && shrink > 1) { - skipBytes(shrink - 1); - pix += (shrink - 1); - } - } - - if (m_info.m_lx - x1 - 1 > 0) { - skipBytes(m_info.m_lx - x1 - 1); - } - - if (m_lineSize - m_info.m_lx > 0) - skipBytes(m_lineSize - m_info.m_lx); - return 0; +int BmpReader::read8Line(char *buffer, int x0, int x1, int shrink) { + TPixel32 *pix = (TPixel32 *)buffer; + + if (x0 > 0) skipBytes(x0); + pix += x0; + TPixel32 *endPix = pix + x1 - x0 + 1; + + while (pix < endPix) { + int value = getc(m_chan); + *pix++ = m_cmap[value]; + if (pix < endPix && shrink > 1) { + skipBytes(shrink - 1); + pix += (shrink - 1); + } + } + + if (m_info.m_lx - x1 - 1 > 0) { + skipBytes(m_info.m_lx - x1 - 1); + } + + if (m_lineSize - m_info.m_lx > 0) skipBytes(m_lineSize - m_info.m_lx); + return 0; } //--------------------------------------------------------- -int BmpReader::read8LineRle(char *buffer, int x0, int x1, int shrink) -{ - TPixel32 *pix = (TPixel32 *)buffer; - if (x0 > 0) - skipBytes(x0); - pix += x0; - TPixel32 *endPix = pix + (x1 - x0 + 1); - - while (pix < endPix) { - int i, count = getc(m_chan); - assert(count >= 0); - if (count == 0) { - int pixels = getc(m_chan); - - assert(pixels >= 0 && pixels != 2); - if (pixels < 3) - return 0; - for (i = 0; i < pixels; i++) - *pix++ = m_cmap[getc(m_chan)]; - if ((1 + 1 + pixels) & 0x1) - getc(m_chan); - } else { - int value = getc(m_chan); - assert(value >= 0); - for (i = 0; i < count; i++) - *pix++ = m_cmap[value]; - } - if (pix < endPix && shrink > 1) { - skipBytes(shrink - 1); - pix += (shrink - 1); - } - } - - if (m_info.m_lx - x1 - 1 > 0) { - skipBytes(m_info.m_lx - x1 - 1); - } - - if (m_lineSize - m_info.m_lx > 0) - skipBytes(m_lineSize - m_info.m_lx); - int val = getc(m_chan); - assert(val == 0); //end scanline or end bmp - val = getc(m_chan); - assert(val == 0 || val == 1); - return 0; +int BmpReader::read8LineRle(char *buffer, int x0, int x1, int shrink) { + TPixel32 *pix = (TPixel32 *)buffer; + if (x0 > 0) skipBytes(x0); + pix += x0; + TPixel32 *endPix = pix + (x1 - x0 + 1); + + while (pix < endPix) { + int i, count = getc(m_chan); + assert(count >= 0); + if (count == 0) { + int pixels = getc(m_chan); + + assert(pixels >= 0 && pixels != 2); + if (pixels < 3) return 0; + for (i = 0; i < pixels; i++) *pix++ = m_cmap[getc(m_chan)]; + if ((1 + 1 + pixels) & 0x1) getc(m_chan); + } else { + int value = getc(m_chan); + assert(value >= 0); + for (i = 0; i < count; i++) *pix++ = m_cmap[value]; + } + if (pix < endPix && shrink > 1) { + skipBytes(shrink - 1); + pix += (shrink - 1); + } + } + + if (m_info.m_lx - x1 - 1 > 0) { + skipBytes(m_info.m_lx - x1 - 1); + } + + if (m_lineSize - m_info.m_lx > 0) skipBytes(m_lineSize - m_info.m_lx); + int val = getc(m_chan); + assert(val == 0); // end scanline or end bmp + val = getc(m_chan); + assert(val == 0 || val == 1); + return 0; } //--------------------------------------------------------- -int BmpReader::read16m555Line(char *buffer, int x0, int x1, int shrink) -{ - TPixel32 *pix = (TPixel32 *)buffer; - if (x0 > 0) - skipBytes(2 * x0); - pix += x0; - TPixel32 *endPix = pix + x1 - x0 + 1; - - while (pix < endPix) { - int v = getshort(m_chan); - int r = (v >> 10) & 0x1F; - int g = (v >> 5) & 0x1F; - int b = v & 0x1F; - pix->r = r << 3 | r >> 2; - pix->g = g << 3 | g >> 2; - pix->b = b << 3 | b >> 2; - pix->m = 255; - pix += shrink; - if (pix < endPix && shrink > 1) - skipBytes(2 * (shrink - 1)); - } - if (m_info.m_lx - x1 - 1 > 0) - skipBytes(2 * (m_info.m_lx - x1 - 1)); - - if (m_lineSize - 2 * m_info.m_lx > 0) - skipBytes(m_lineSize - 2 * m_info.m_lx); - return 0; +int BmpReader::read16m555Line(char *buffer, int x0, int x1, int shrink) { + TPixel32 *pix = (TPixel32 *)buffer; + if (x0 > 0) skipBytes(2 * x0); + pix += x0; + TPixel32 *endPix = pix + x1 - x0 + 1; + + while (pix < endPix) { + int v = getshort(m_chan); + int r = (v >> 10) & 0x1F; + int g = (v >> 5) & 0x1F; + int b = v & 0x1F; + pix->r = r << 3 | r >> 2; + pix->g = g << 3 | g >> 2; + pix->b = b << 3 | b >> 2; + pix->m = 255; + pix += shrink; + if (pix < endPix && shrink > 1) skipBytes(2 * (shrink - 1)); + } + if (m_info.m_lx - x1 - 1 > 0) skipBytes(2 * (m_info.m_lx - x1 - 1)); + + if (m_lineSize - 2 * m_info.m_lx > 0) skipBytes(m_lineSize - 2 * m_info.m_lx); + return 0; } //--------------------------------------------------------- -int BmpReader::read16m565Line(char *buffer, int x0, int x1, int shrink) -{ - TPixel32 *pix = (TPixel32 *)buffer; - if (x0 > 0) - skipBytes(2 * x0); - pix += x0; - TPixel32 *endPix = pix + x1 - x0 + 1; - - while (pix < endPix) { - int v = getshort(m_chan); - int r = (v >> 11) & 0x1F; - int g = (v >> 5) & 0x3F; - int b = v & 0x1F; - pix->r = r << 3 | r >> 2; - pix->g = g << 2 | g >> 4; - pix->b = b << 3 | b >> 2; - pix->m = 255; - pix += shrink; - if (pix < endPix && shrink > 1) - skipBytes(2 * (shrink - 1)); - } - if (m_info.m_lx - x1 - 1 > 0) - skipBytes(2 * (m_info.m_lx - x1 - 1)); - - if (m_lineSize - 2 * m_info.m_lx > 0) - skipBytes(m_lineSize - 2 * m_info.m_lx); - return 0; +int BmpReader::read16m565Line(char *buffer, int x0, int x1, int shrink) { + TPixel32 *pix = (TPixel32 *)buffer; + if (x0 > 0) skipBytes(2 * x0); + pix += x0; + TPixel32 *endPix = pix + x1 - x0 + 1; + + while (pix < endPix) { + int v = getshort(m_chan); + int r = (v >> 11) & 0x1F; + int g = (v >> 5) & 0x3F; + int b = v & 0x1F; + pix->r = r << 3 | r >> 2; + pix->g = g << 2 | g >> 4; + pix->b = b << 3 | b >> 2; + pix->m = 255; + pix += shrink; + if (pix < endPix && shrink > 1) skipBytes(2 * (shrink - 1)); + } + if (m_info.m_lx - x1 - 1 > 0) skipBytes(2 * (m_info.m_lx - x1 - 1)); + + if (m_lineSize - 2 * m_info.m_lx > 0) skipBytes(m_lineSize - 2 * m_info.m_lx); + return 0; } //--------------------------------------------------------- -int BmpReader::read24Line(char *buffer, int x0, int x1, int shrink) -{ - TPixel32 *pix = (TPixel32 *)buffer; - if (x0 > 0) - skipBytes(3 * x0); - pix += x0; - TPixel32 *endPix = pix + x1 - x0 + 1; - - while (pix < endPix) { - pix->b = getc(m_chan); - pix->g = getc(m_chan); - pix->r = getc(m_chan); - pix->m = 255; - pix += shrink; - if (pix < endPix && shrink > 1) - skipBytes(3 * (shrink - 1)); - } - if (m_info.m_lx - x1 - 1 > 0) - skipBytes(3 * (m_info.m_lx - x1 - 1)); - - if (m_lineSize - 3 * m_info.m_lx > 0) - skipBytes(m_lineSize - 3 * m_info.m_lx); - return 0; +int BmpReader::read24Line(char *buffer, int x0, int x1, int shrink) { + TPixel32 *pix = (TPixel32 *)buffer; + if (x0 > 0) skipBytes(3 * x0); + pix += x0; + TPixel32 *endPix = pix + x1 - x0 + 1; + + while (pix < endPix) { + pix->b = getc(m_chan); + pix->g = getc(m_chan); + pix->r = getc(m_chan); + pix->m = 255; + pix += shrink; + if (pix < endPix && shrink > 1) skipBytes(3 * (shrink - 1)); + } + if (m_info.m_lx - x1 - 1 > 0) skipBytes(3 * (m_info.m_lx - x1 - 1)); + + if (m_lineSize - 3 * m_info.m_lx > 0) skipBytes(m_lineSize - 3 * m_info.m_lx); + return 0; } //--------------------------------------------------------- -int BmpReader::read32Line(char *buffer, int x0, int x1, int shrink) -{ - TPixel32 *pix = (TPixel32 *)buffer; - if (x0 > 0) - skipBytes(4 * x0); - pix += x0; - TPixel32 *endPix = pix + x1 - x0 + 1; - - while (pix < endPix) { - pix->b = getc(m_chan); - pix->g = getc(m_chan); - pix->r = getc(m_chan); - pix->m = getc(m_chan); - pix += shrink; - if (pix < endPix && shrink > 1) - skipBytes(4 * (shrink - 1)); - } - if (m_info.m_lx - x1 - 1 > 0) - skipBytes(4 * (m_info.m_lx - x1 - 1)); - if (m_lineSize - 4 * m_info.m_lx > 0) - skipBytes(m_lineSize - 4 * m_info.m_lx); - return 0; +int BmpReader::read32Line(char *buffer, int x0, int x1, int shrink) { + TPixel32 *pix = (TPixel32 *)buffer; + if (x0 > 0) skipBytes(4 * x0); + pix += x0; + TPixel32 *endPix = pix + x1 - x0 + 1; + + while (pix < endPix) { + pix->b = getc(m_chan); + pix->g = getc(m_chan); + pix->r = getc(m_chan); + pix->m = getc(m_chan); + pix += shrink; + if (pix < endPix && shrink > 1) skipBytes(4 * (shrink - 1)); + } + if (m_info.m_lx - x1 - 1 > 0) skipBytes(4 * (m_info.m_lx - x1 - 1)); + if (m_lineSize - 4 * m_info.m_lx > 0) skipBytes(m_lineSize - 4 * m_info.m_lx); + return 0; } //========================================================= -class BmpWriter : public Tiio::Writer -{ - FILE *m_chan; - int m_bitPerPixel; - int m_compression; +class BmpWriter : public Tiio::Writer { + FILE *m_chan; + int m_bitPerPixel; + int m_compression; public: - BmpWriter(); - ~BmpWriter(); + BmpWriter(); + ~BmpWriter(); - void open(FILE *file, const TImageInfo &info); + void open(FILE *file, const TImageInfo &info); - void flush() { fflush(m_chan); } + void flush() { fflush(m_chan); } - void writeLine(char *buffer); + void writeLine(char *buffer); }; //--------------------------------------------------------- -BmpWriter::BmpWriter() - : m_chan(0) -{ -} +BmpWriter::BmpWriter() : m_chan(0) {} //--------------------------------------------------------- -BmpWriter::~BmpWriter() -{ - delete m_properties; -} +BmpWriter::~BmpWriter() { delete m_properties; } //--------------------------------------------------------- -void BmpWriter::open(FILE *file, const TImageInfo &info) -{ - m_chan = file; - - m_info = info; - int lx = m_info.m_lx; - int ly = m_info.m_ly; - - if (!m_properties) - m_properties = new Tiio::BmpWriterProperties(); - - TEnumProperty *p = (TEnumProperty *)(m_properties->getProperty("Bits Per Pixel")); - assert(p); - std::string str = ::to_string(p->getValue()); - m_bitPerPixel = atoi(str.c_str()); - - int cmapSize = 0; - std::vector *colormap = 0; - - if (m_bitPerPixel == 8) { - TPointerProperty *colormapProp = (TPointerProperty *)(m_properties->getProperty("Colormap")); - if (colormapProp) { - colormap = (std::vector *)colormapProp->getValue(); - cmapSize = colormap->size(); - } else - cmapSize = 256; - } - - assert(m_bitPerPixel == 8 || m_bitPerPixel == 24); - - int bytePerLine = ((lx * m_bitPerPixel + 31) / 32) * (m_bitPerPixel == 8 ? 1 : 4); - - int fileSize = - 14 // file header - + 40 // info header - + cmapSize * 4 // colormap size - + bytePerLine * ly // image size - ; - int offset = 14 + 40 + cmapSize * 4; - int compression = 0; - int imageSize = bytePerLine * ly; - - putc('B', m_chan); - putc('M', m_chan); // BMP file magic number - - putint(m_chan, fileSize); - putshort(m_chan, 0); // reserved1 - putshort(m_chan, 0); // reserved2 - - putint(m_chan, offset); // offset from BOfile to BObitmap - - putint(m_chan, 40); // size of bitmap info header - putint(m_chan, m_info.m_lx); // width - putint(m_chan, m_info.m_ly); // height - putshort(m_chan, 1); // must be '1' - putshort(m_chan, m_bitPerPixel); // 1,4,8, or 24 - putint(m_chan, compression); // BMP_BI_RGB, BMP_BI_RLE8 or BMP_BI_RLE4 - putint(m_chan, imageSize); // size of raw image data - putint(m_chan, 0); // dpi * 39" per meter - putint(m_chan, 0); // dpi * 39" per meter - putint(m_chan, cmapSize); // colors used in cmap - putint(m_chan, 0); // same as above - - if (colormap) - for (int i = 0; i < (int)colormap->size(); i++) { - putc((*colormap)[i].b, m_chan); - putc((*colormap)[i].g, m_chan); - putc((*colormap)[i].r, m_chan); - putc(0, m_chan); - } - else - for (int i = 0; i < cmapSize; i++) //palette!! - { - putc(i, m_chan); - putc(i, m_chan); - putc(i, m_chan); - putc(0, m_chan); - } +void BmpWriter::open(FILE *file, const TImageInfo &info) { + m_chan = file; + + m_info = info; + int lx = m_info.m_lx; + int ly = m_info.m_ly; + + if (!m_properties) m_properties = new Tiio::BmpWriterProperties(); + + TEnumProperty *p = + (TEnumProperty *)(m_properties->getProperty("Bits Per Pixel")); + assert(p); + std::string str = ::to_string(p->getValue()); + m_bitPerPixel = atoi(str.c_str()); + + int cmapSize = 0; + std::vector *colormap = 0; + + if (m_bitPerPixel == 8) { + TPointerProperty *colormapProp = + (TPointerProperty *)(m_properties->getProperty("Colormap")); + if (colormapProp) { + colormap = (std::vector *)colormapProp->getValue(); + cmapSize = colormap->size(); + } else + cmapSize = 256; + } + + assert(m_bitPerPixel == 8 || m_bitPerPixel == 24); + + int bytePerLine = + ((lx * m_bitPerPixel + 31) / 32) * (m_bitPerPixel == 8 ? 1 : 4); + + int fileSize = 14 // file header + + 40 // info header + + cmapSize * 4 // colormap size + + bytePerLine * ly // image size + ; + int offset = 14 + 40 + cmapSize * 4; + int compression = 0; + int imageSize = bytePerLine * ly; + + putc('B', m_chan); + putc('M', m_chan); // BMP file magic number + + putint(m_chan, fileSize); + putshort(m_chan, 0); // reserved1 + putshort(m_chan, 0); // reserved2 + + putint(m_chan, offset); // offset from BOfile to BObitmap + + putint(m_chan, 40); // size of bitmap info header + putint(m_chan, m_info.m_lx); // width + putint(m_chan, m_info.m_ly); // height + putshort(m_chan, 1); // must be '1' + putshort(m_chan, m_bitPerPixel); // 1,4,8, or 24 + putint(m_chan, compression); // BMP_BI_RGB, BMP_BI_RLE8 or BMP_BI_RLE4 + putint(m_chan, imageSize); // size of raw image data + putint(m_chan, 0); // dpi * 39" per meter + putint(m_chan, 0); // dpi * 39" per meter + putint(m_chan, cmapSize); // colors used in cmap + putint(m_chan, 0); // same as above + + if (colormap) + for (int i = 0; i < (int)colormap->size(); i++) { + putc((*colormap)[i].b, m_chan); + putc((*colormap)[i].g, m_chan); + putc((*colormap)[i].r, m_chan); + putc(0, m_chan); + } + else + for (int i = 0; i < cmapSize; i++) // palette!! + { + putc(i, m_chan); + putc(i, m_chan); + putc(i, m_chan); + putc(0, m_chan); + } } //--------------------------------------------------------- -void BmpWriter::writeLine(char *buffer) -{ - int lx = m_info.m_lx; - - int j; - - switch (m_bitPerPixel) { - case 24: { - TPixel32 *pix = (TPixel32 *)buffer; - for (j = 0; j < lx; j++) { - putc(pix->b, m_chan); - putc(pix->g, m_chan); - putc(pix->r, m_chan); - ++pix; - } - int bytes = lx * 3; - while (bytes & 3) { - putc(0, m_chan); - bytes++; - } - break; - } - case 8: { - TPixelGR8 *pix = (TPixelGR8 *)buffer; - for (j = 0; j < lx; j++) { - putc(pix->value, m_chan); - ++pix; - } - while (lx & 3) { - putc(0, m_chan); - lx++; - } - break; - } - default: - assert(false); - } - ftell(m_chan); +void BmpWriter::writeLine(char *buffer) { + int lx = m_info.m_lx; + + int j; + + switch (m_bitPerPixel) { + case 24: { + TPixel32 *pix = (TPixel32 *)buffer; + for (j = 0; j < lx; j++) { + putc(pix->b, m_chan); + putc(pix->g, m_chan); + putc(pix->r, m_chan); + ++pix; + } + int bytes = lx * 3; + while (bytes & 3) { + putc(0, m_chan); + bytes++; + } + break; + } + case 8: { + TPixelGR8 *pix = (TPixelGR8 *)buffer; + for (j = 0; j < lx; j++) { + putc(pix->value, m_chan); + ++pix; + } + while (lx & 3) { + putc(0, m_chan); + lx++; + } + break; + } + default: + assert(false); + } + ftell(m_chan); } //========================================================= -Tiio::Reader *Tiio::makeBmpReader() -{ - return new BmpReader(); -} +Tiio::Reader *Tiio::makeBmpReader() { return new BmpReader(); } //========================================================= -Tiio::Writer *Tiio::makeBmpWriter() -{ - return new BmpWriter(); -} +Tiio::Writer *Tiio::makeBmpWriter() { return new BmpWriter(); } //========================================================= Tiio::BmpWriterProperties::BmpWriterProperties() - : m_pixelSize("Bits Per Pixel") -{ - m_pixelSize.addValue(L"24 bits"); - m_pixelSize.addValue(L"8 bits (Greyscale)"); - bind(m_pixelSize); + : m_pixelSize("Bits Per Pixel") { + m_pixelSize.addValue(L"24 bits"); + m_pixelSize.addValue(L"8 bits (Greyscale)"); + bind(m_pixelSize); } diff --git a/toonz/sources/common/tiio/tiio_jpg.cpp b/toonz/sources/common/tiio/tiio_jpg.cpp index 5200d35..8d00b3a 100644 --- a/toonz/sources/common/tiio/tiio_jpg.cpp +++ b/toonz/sources/common/tiio/tiio_jpg.cpp @@ -29,9 +29,8 @@ const std::string Tiio::JpgWriterProperties::QUALITY("Quality"); //========================================================= -extern "C" void tnz_error_exit(j_common_ptr cinfo) -{ - // throw "merda"; +extern "C" void tnz_error_exit(j_common_ptr cinfo) { + // throw "merda"; } #ifdef CICCIO @@ -49,190 +48,170 @@ JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo)); using namespace Tiio; -JpgReader::JpgReader() : m_chan(0), m_isOpen(false) -{ - memset(&m_cinfo, 0, sizeof m_cinfo); - memset(&m_jerr, 0, sizeof m_jerr); - memset(&m_buffer, 0, sizeof m_buffer); +JpgReader::JpgReader() : m_chan(0), m_isOpen(false) { + memset(&m_cinfo, 0, sizeof m_cinfo); + memset(&m_jerr, 0, sizeof m_jerr); + memset(&m_buffer, 0, sizeof m_buffer); } -JpgReader::~JpgReader() -{ - if (m_isOpen) { - try { - jpeg_finish_decompress(&m_cinfo); - jpeg_destroy_decompress(&m_cinfo); - } catch (...) { - } - } - if (m_chan) { - m_chan = 0; - } +JpgReader::~JpgReader() { + if (m_isOpen) { + try { + jpeg_finish_decompress(&m_cinfo); + jpeg_destroy_decompress(&m_cinfo); + } catch (...) { + } + } + if (m_chan) { + m_chan = 0; + } } Tiio::RowOrder JpgReader::getRowOrder() const { return Tiio::TOP2BOTTOM; } -void JpgReader::open(FILE *file) -{ - m_cinfo.err = jpeg_std_error(&m_jerr); - m_cinfo.err->error_exit = tnz_error_exit; - - jpeg_create_decompress(&m_cinfo); - m_chan = file; - jpeg_stdio_src(&m_cinfo, m_chan); - bool ret = jpeg_read_header(&m_cinfo, TRUE); - ret = ret && jpeg_start_decompress(&m_cinfo); - if (!ret) - return; - - int row_stride = m_cinfo.output_width * m_cinfo.output_components; - m_buffer = (*m_cinfo.mem->alloc_sarray)((j_common_ptr)&m_cinfo, JPOOL_IMAGE, row_stride, 1); - - m_info.m_lx = m_cinfo.output_width; - m_info.m_ly = m_cinfo.output_height; - m_info.m_samplePerPixel = 3; - m_info.m_valid = true; - m_isOpen = true; +void JpgReader::open(FILE *file) { + m_cinfo.err = jpeg_std_error(&m_jerr); + m_cinfo.err->error_exit = tnz_error_exit; + + jpeg_create_decompress(&m_cinfo); + m_chan = file; + jpeg_stdio_src(&m_cinfo, m_chan); + bool ret = jpeg_read_header(&m_cinfo, TRUE); + ret = ret && jpeg_start_decompress(&m_cinfo); + if (!ret) return; + + int row_stride = m_cinfo.output_width * m_cinfo.output_components; + m_buffer = (*m_cinfo.mem->alloc_sarray)((j_common_ptr)&m_cinfo, JPOOL_IMAGE, + row_stride, 1); + + m_info.m_lx = m_cinfo.output_width; + m_info.m_ly = m_cinfo.output_height; + m_info.m_samplePerPixel = 3; + m_info.m_valid = true; + m_isOpen = true; } -void JpgReader::readLine(char *buffer, int x0, int x1, int shrink) -{ - if (m_cinfo.out_color_space == JCS_RGB && m_cinfo.out_color_components == 3) { - int ret = jpeg_read_scanlines(&m_cinfo, m_buffer, 1); - assert(ret == 1); - unsigned char *src = m_buffer[0]; - TPixel32 *dst = (TPixel32 *)buffer; - dst += x0; - src += 3 * x0; - - int width = (m_cinfo.output_width - 1) / shrink + 1; - if (x1 >= x0) - width = (x1 - x0) / shrink + 1; - - while (--width >= 0) { - dst->r = src[0]; - dst->g = src[1]; - dst->b = src[2]; - dst->m = (char)255; - src += 3 * shrink; - dst += shrink; - } - } else if (m_cinfo.out_color_components == 1) { - int ret = jpeg_read_scanlines(&m_cinfo, m_buffer, 1); - assert(ret == 1); - unsigned char *src = m_buffer[0]; - TPixel32 *dst = (TPixel32 *)buffer; - - dst += x0; - src += x0; - - int width = (m_cinfo.output_width - 1) / shrink + 1; - if (x1 >= x0) - width = (x1 - x0) / shrink + 1; - - while (--width >= 0) { - dst->r = *src; - dst->g = *src; - dst->b = *src; - dst->m = (char)255; - src += shrink; - dst += shrink; - } - } +void JpgReader::readLine(char *buffer, int x0, int x1, int shrink) { + if (m_cinfo.out_color_space == JCS_RGB && m_cinfo.out_color_components == 3) { + int ret = jpeg_read_scanlines(&m_cinfo, m_buffer, 1); + assert(ret == 1); + unsigned char *src = m_buffer[0]; + TPixel32 *dst = (TPixel32 *)buffer; + dst += x0; + src += 3 * x0; + + int width = (m_cinfo.output_width - 1) / shrink + 1; + if (x1 >= x0) width = (x1 - x0) / shrink + 1; + + while (--width >= 0) { + dst->r = src[0]; + dst->g = src[1]; + dst->b = src[2]; + dst->m = (char)255; + src += 3 * shrink; + dst += shrink; + } + } else if (m_cinfo.out_color_components == 1) { + int ret = jpeg_read_scanlines(&m_cinfo, m_buffer, 1); + assert(ret == 1); + unsigned char *src = m_buffer[0]; + TPixel32 *dst = (TPixel32 *)buffer; + + dst += x0; + src += x0; + + int width = (m_cinfo.output_width - 1) / shrink + 1; + if (x1 >= x0) width = (x1 - x0) / shrink + 1; + + while (--width >= 0) { + dst->r = *src; + dst->g = *src; + dst->b = *src; + dst->m = (char)255; + src += shrink; + dst += shrink; + } + } } -int JpgReader::skipLines(int lineCount) -{ - for (int i = 0; i < lineCount; i++) { - int ret = jpeg_read_scanlines(&m_cinfo, m_buffer, 1); - assert(ret == 1); - } - return lineCount; +int JpgReader::skipLines(int lineCount) { + for (int i = 0; i < lineCount; i++) { + int ret = jpeg_read_scanlines(&m_cinfo, m_buffer, 1); + assert(ret == 1); + } + return lineCount; } -class JpgWriter : public Tiio::Writer -{ - - struct jpeg_compress_struct m_cinfo; - struct jpeg_error_mgr m_jerr; - FILE *m_chan; - JSAMPARRAY m_buffer; - bool m_headerWritten; +class JpgWriter : public Tiio::Writer { + struct jpeg_compress_struct m_cinfo; + struct jpeg_error_mgr m_jerr; + FILE *m_chan; + JSAMPARRAY m_buffer; + bool m_headerWritten; public: - JpgWriter() - : m_chan(0), m_headerWritten(false) - { - } - - void open(FILE *file, const TImageInfo &info) - { - m_cinfo.err = jpeg_std_error(&m_jerr); - jpeg_create_compress(&m_cinfo); - - m_cinfo.image_width = info.m_lx; - m_cinfo.image_height = info.m_ly; - m_cinfo.input_components = 3; - m_cinfo.in_color_space = JCS_RGB; - - jpeg_set_defaults(&m_cinfo); - if (!m_properties) - m_properties = new Tiio::JpgWriterProperties(); - - jpeg_set_quality(&m_cinfo, ((TIntProperty *)(m_properties->getProperty("Quality")))->getValue(), TRUE); - m_cinfo.smoothing_factor = ((TIntProperty *)(m_properties->getProperty("Smoothing")))->getValue(); - - int row_stride = m_cinfo.image_width * m_cinfo.input_components; - m_buffer = (*m_cinfo.mem->alloc_sarray)((j_common_ptr)&m_cinfo, JPOOL_IMAGE, row_stride, 1); - - m_chan = file; - jpeg_stdio_dest(&m_cinfo, m_chan); - } - - ~JpgWriter() - { - jpeg_finish_compress(&m_cinfo); - jpeg_destroy_compress(&m_cinfo); - delete m_properties; - } - - void flush() - { - fflush(m_chan); - } - - Tiio::RowOrder getRowOrder() const { return Tiio::TOP2BOTTOM; } - - void writeLine(char *buffer) - { - if (!m_headerWritten) { - m_headerWritten = true; - jpeg_start_compress(&m_cinfo, TRUE); - } - TPixel32 *src = (TPixel32 *)buffer; - unsigned char *dst = m_buffer[0]; - int lx = m_cinfo.image_width; - while (--lx >= 0) { - dst[0] = src->r; - dst[1] = src->g; - dst[2] = src->b; - dst += 3; - ++src; - } - jpeg_write_scanlines(&m_cinfo, m_buffer, 1); - } + JpgWriter() : m_chan(0), m_headerWritten(false) {} + + void open(FILE *file, const TImageInfo &info) { + m_cinfo.err = jpeg_std_error(&m_jerr); + jpeg_create_compress(&m_cinfo); + + m_cinfo.image_width = info.m_lx; + m_cinfo.image_height = info.m_ly; + m_cinfo.input_components = 3; + m_cinfo.in_color_space = JCS_RGB; + + jpeg_set_defaults(&m_cinfo); + if (!m_properties) m_properties = new Tiio::JpgWriterProperties(); + + jpeg_set_quality( + &m_cinfo, + ((TIntProperty *)(m_properties->getProperty("Quality")))->getValue(), + TRUE); + m_cinfo.smoothing_factor = + ((TIntProperty *)(m_properties->getProperty("Smoothing")))->getValue(); + + int row_stride = m_cinfo.image_width * m_cinfo.input_components; + m_buffer = (*m_cinfo.mem->alloc_sarray)((j_common_ptr)&m_cinfo, JPOOL_IMAGE, + row_stride, 1); + + m_chan = file; + jpeg_stdio_dest(&m_cinfo, m_chan); + } + + ~JpgWriter() { + jpeg_finish_compress(&m_cinfo); + jpeg_destroy_compress(&m_cinfo); + delete m_properties; + } + + void flush() { fflush(m_chan); } + + Tiio::RowOrder getRowOrder() const { return Tiio::TOP2BOTTOM; } + + void writeLine(char *buffer) { + if (!m_headerWritten) { + m_headerWritten = true; + jpeg_start_compress(&m_cinfo, TRUE); + } + TPixel32 *src = (TPixel32 *)buffer; + unsigned char *dst = m_buffer[0]; + int lx = m_cinfo.image_width; + while (--lx >= 0) { + dst[0] = src->r; + dst[1] = src->g; + dst[2] = src->b; + dst += 3; + ++src; + } + jpeg_write_scanlines(&m_cinfo, m_buffer, 1); + } }; //---- //---- //---- -Tiio::Reader *Tiio::makeJpgReader() -{ - return new JpgReader(); -} +Tiio::Reader *Tiio::makeJpgReader() { return new JpgReader(); } -Tiio::Writer *Tiio::makeJpgWriter() -{ - return new JpgWriter(); -} +Tiio::Writer *Tiio::makeJpgWriter() { return new JpgWriter(); } diff --git a/toonz/sources/common/tiio/tiio_jpg_util.cpp b/toonz/sources/common/tiio/tiio_jpg_util.cpp index 5d3af09..599f028 100644 --- a/toonz/sources/common/tiio/tiio_jpg_util.cpp +++ b/toonz/sources/common/tiio/tiio_jpg_util.cpp @@ -12,64 +12,60 @@ #include "tfilepath_io.h" #include "tsystem.h" -void Tiio::createJpg( - std::vector &buffer, - const TRaster32P &ras, - int quality) -{ - //FILE *chan = tmpfile(); - TFilePath fname = TSystem::getUniqueFile(); - FILE *chan = fopen(fname, "w+b"); - if (chan == 0) - throw TException(L". Can not create " + fname.getWideString()); +void Tiio::createJpg(std::vector &buffer, const TRaster32P &ras, + int quality) { + // FILE *chan = tmpfile(); + TFilePath fname = TSystem::getUniqueFile(); + FILE *chan = fopen(fname, "w+b"); + if (chan == 0) throw TException(L". Can not create " + fname.getWideString()); - assert(chan); - assert(ras); - assert(0 <= quality && quality <= 100); - fflush(chan); - Tiio::Writer *writer = Tiio::makeJpgWriter(); - assert(writer); - TPropertyGroup *pg = writer->getProperties(); - if (!pg) { - writer->setProperties(new JpgWriterProperties()); - pg = writer->getProperties(); - } + assert(chan); + assert(ras); + assert(0 <= quality && quality <= 100); + fflush(chan); + Tiio::Writer *writer = Tiio::makeJpgWriter(); + assert(writer); + TPropertyGroup *pg = writer->getProperties(); + if (!pg) { + writer->setProperties(new JpgWriterProperties()); + pg = writer->getProperties(); + } - TProperty *qualityProp = pg->getProperty(JpgWriterProperties::QUALITY); - assert(qualityProp); - TIntProperty *ip = dynamic_cast(qualityProp); - assert(ip); - ip->setValue(quality); - int lx = ras->getLx(); - int ly = ras->getLy(); - assert(lx > 0 && ly > 0); - writer->open(chan, TImageInfo(lx, ly)); + TProperty *qualityProp = pg->getProperty(JpgWriterProperties::QUALITY); + assert(qualityProp); + TIntProperty *ip = dynamic_cast(qualityProp); + assert(ip); + ip->setValue(quality); + int lx = ras->getLx(); + int ly = ras->getLy(); + assert(lx > 0 && ly > 0); + writer->open(chan, TImageInfo(lx, ly)); - ras->lock(); - for (int y = 0; y < ly; y++) - writer->writeLine((char *)ras->getRawData(0, ly - 1 - y)); - ras->unlock(); - writer->flush(); - delete writer; - fclose(chan); + ras->lock(); + for (int y = 0; y < ly; y++) + writer->writeLine((char *)ras->getRawData(0, ly - 1 - y)); + ras->unlock(); + writer->flush(); + delete writer; + fclose(chan); - //lo chiudo e lo riapro: altrimenti, gettava male la filesize. boh. - FILE *chan1 = fopen(fname, "rb"); - if (chan1 == 0) - throw TException(L". Can not create " + fname.getWideString()); - int ret = fseek(chan1, 0, SEEK_END); - assert(ret == 0); - int fileSize = ftell(chan1); + // lo chiudo e lo riapro: altrimenti, gettava male la filesize. boh. + FILE *chan1 = fopen(fname, "rb"); + if (chan1 == 0) + throw TException(L". Can not create " + fname.getWideString()); + int ret = fseek(chan1, 0, SEEK_END); + assert(ret == 0); + int fileSize = ftell(chan1); - buffer.resize(fileSize); - ret = fseek(chan1, 0, SEEK_SET); - assert(ret == 0); - for (int i = 0; i < fileSize; i++) { - int c = fgetc(chan1); - assert(!feof(chan1)); - buffer[i] = c; - } + buffer.resize(fileSize); + ret = fseek(chan1, 0, SEEK_SET); + assert(ret == 0); + for (int i = 0; i < fileSize; i++) { + int c = fgetc(chan1); + assert(!feof(chan1)); + buffer[i] = c; + } - fclose(chan1); - TSystem::deleteFile(fname); + fclose(chan1); + TSystem::deleteFile(fname); } diff --git a/toonz/sources/common/tiio/tiio_std.cpp b/toonz/sources/common/tiio/tiio_std.cpp index fa9064d..50c5273 100644 --- a/toonz/sources/common/tiio/tiio_std.cpp +++ b/toonz/sources/common/tiio/tiio_std.cpp @@ -9,15 +9,14 @@ using namespace Tiio; using namespace TFileType; -void Tiio::defineStd() -{ - defineReaderMaker("jpg", Tiio::makeJpgReader); - defineWriterMaker("jpg", Tiio::makeJpgWriter, true); - declare("jpg", TFileType::RASTER_IMAGE); - defineWriterProperties("jpg", new JpgWriterProperties()); +void Tiio::defineStd() { + defineReaderMaker("jpg", Tiio::makeJpgReader); + defineWriterMaker("jpg", Tiio::makeJpgWriter, true); + declare("jpg", TFileType::RASTER_IMAGE); + defineWriterProperties("jpg", new JpgWriterProperties()); - defineReaderMaker("bmp", Tiio::makeBmpReader); - defineWriterMaker("bmp", Tiio::makeBmpWriter, true); - declare("bmp", TFileType::RASTER_IMAGE); - defineWriterProperties("bmp", new BmpWriterProperties()); + defineReaderMaker("bmp", Tiio::makeBmpReader); + defineWriterMaker("bmp", Tiio::makeBmpWriter, true); + declare("bmp", TFileType::RASTER_IMAGE); + defineWriterProperties("bmp", new BmpWriterProperties()); } diff --git a/toonz/sources/common/timage/timage.cpp b/toonz/sources/common/timage/timage.cpp index 810307c..af66f54 100644 --- a/toonz/sources/common/timage/timage.cpp +++ b/toonz/sources/common/timage/timage.cpp @@ -6,37 +6,24 @@ #include "tpalette.h" -void TImage::setPalette(TPalette *palette) -{ - if (m_palette == palette) - return; - if (palette) - palette->addRef(); - if (m_palette) - m_palette->release(); - m_palette = palette; +void TImage::setPalette(TPalette *palette) { + if (m_palette == palette) return; + if (palette) palette->addRef(); + if (m_palette) m_palette->release(); + m_palette = palette; } -TImage::~TImage() -{ - if (m_palette) - m_palette->release(); +TImage::~TImage() { + if (m_palette) m_palette->release(); } #else -class TPalette -{ -}; +class TPalette {}; -void TImage::setPalette(TPalette *palette) -{ - assert(false); -} +void TImage::setPalette(TPalette *palette) { assert(false); } -TImage::~TImage() -{ -} +TImage::~TImage() {} #endif @@ -44,7 +31,4 @@ TImage::~TImage() DEFINE_CLASS_CODE(TImage, 4) -TImage::TImage() - : TSmartObject(m_classCode), m_palette(0) -{ -} +TImage::TImage() : TSmartObject(m_classCode), m_palette(0) {} diff --git a/toonz/sources/common/timage/tlevel.cpp b/toonz/sources/common/timage/tlevel.cpp index 66094c5..9bc5f7e 100644 --- a/toonz/sources/common/timage/tlevel.cpp +++ b/toonz/sources/common/timage/tlevel.cpp @@ -8,54 +8,44 @@ DEFINE_CLASS_CODE(TLevel, 7) //------------------------------------------------- TLevel::TLevel() - : TSmartObject(m_classCode), m_name(""), m_table(new Table()), m_palette(0) -{ -} + : TSmartObject(m_classCode) + , m_name("") + , m_table(new Table()) + , m_palette(0) {} //------------------------------------------------- -TLevel::~TLevel() -{ - if (m_palette) - m_palette->release(); - delete m_table; +TLevel::~TLevel() { + if (m_palette) m_palette->release(); + delete m_table; } //------------------------------------------------- -std::string TLevel::getName() const -{ - return m_name; -} +std::string TLevel::getName() const { return m_name; } //------------------------------------------------- -void TLevel::setName(std::string name) -{ - m_name = name; -} +void TLevel::setName(std::string name) { m_name = name; } //------------------------------------------------- -const TImageP &TLevel::frame(const TFrameId fid) -{ - const static TImageP none; - assert(m_table); - Iterator it = m_table->find(fid); - if (it == m_table->end()) - return none; // (*m_table)[fid]; - else - return it->second; +const TImageP &TLevel::frame(const TFrameId fid) { + const static TImageP none; + assert(m_table); + Iterator it = m_table->find(fid); + if (it == m_table->end()) + return none; // (*m_table)[fid]; + else + return it->second; } //------------------------------------------------- -void TLevel::setFrame(const TFrameId &fid, const TImageP &img) -{ - assert(m_table); - if (img) - img->setPalette(getPalette()); - (*m_table)[fid] = img; +void TLevel::setFrame(const TFrameId &fid, const TImageP &img) { + assert(m_table); + if (img) img->setPalette(getPalette()); + (*m_table)[fid] = img; } //------------------------------------------------- @@ -74,27 +64,19 @@ int TLevel::getIndex(const TFrameId fid) //------------------------------------------------- -TPalette *TLevel::getPalette() -{ - return m_palette; -} +TPalette *TLevel::getPalette() { return m_palette; } //------------------------------------------------- -void TLevel::setPalette(TPalette *palette) -{ - if (m_palette == palette) - return; - if (palette) - palette->addRef(); - if (m_palette) - m_palette->release(); - m_palette = palette; - for (Iterator it = begin(); it != end(); ++it) { - TImageP &img = it->second; - if (img) - img->setPalette(m_palette); - } +void TLevel::setPalette(TPalette *palette) { + if (m_palette == palette) return; + if (palette) palette->addRef(); + if (m_palette) m_palette->release(); + m_palette = palette; + for (Iterator it = begin(); it != end(); ++it) { + TImageP &img = it->second; + if (img) img->setPalette(m_palette); + } } //------------------------------------------------- diff --git a/toonz/sources/common/timage_io/timage_io.cpp b/toonz/sources/common/timage_io/timage_io.cpp index 9d01059..f703aa7 100644 --- a/toonz/sources/common/timage_io/timage_io.cpp +++ b/toonz/sources/common/timage_io/timage_io.cpp @@ -25,8 +25,8 @@ #endif // System V includes -#include // didn't even know Windows had them :D -#include // btw, why are they here? +#include // didn't even know Windows had them :D +#include // btw, why are they here? DEFINE_CLASS_CODE(TImageReader, 5) DEFINE_CLASS_CODE(TImageWriter, 6) @@ -43,48 +43,46 @@ bool TImageReader::m_safeMode = false; //----------------------------------------------------------- TImageReader::TImageReader(const TFilePath &path) - : TSmartObject(m_classCode), m_path(path), m_reader(0), m_vectorReader(0), m_readGreytones(true), m_file(NULL), m_is64BitEnabled(false), m_shrink(1), m_region(TRect()) -{ -} + : TSmartObject(m_classCode) + , m_path(path) + , m_reader(0) + , m_vectorReader(0) + , m_readGreytones(true) + , m_file(NULL) + , m_is64BitEnabled(false) + , m_shrink(1) + , m_region(TRect()) {} //----------------------------------------------------------- -void TImageReader::doReadGraytones(bool readThem) -{ - m_readGreytones = readThem; +void TImageReader::doReadGraytones(bool readThem) { + m_readGreytones = readThem; } //----------------------------------------------------------- -TImageReader::~TImageReader() -{ - close(); -} +TImageReader::~TImageReader() { close(); } //----------------------------------------------------------- -bool TImageReader::isOpen() const -{ - return m_file != NULL; -} +bool TImageReader::isOpen() const { return m_file != NULL; } //----------------------------------------------------------- -void TImageReader::close() -{ - delete m_reader; - delete m_vectorReader; +void TImageReader::close() { + delete m_reader; + delete m_vectorReader; - if (m_file != NULL) { - int err = 0; - err = fclose(m_file); + if (m_file != NULL) { + int err = 0; + err = fclose(m_file); - assert(err == 0); //il file e' stato chiuso senza errori - } + assert(err == 0); // il file e' stato chiuso senza errori + } - m_file = NULL; - m_reader = 0; - m_vectorReader = 0; + m_file = NULL; + m_reader = 0; + m_vectorReader = 0; } //----------------------------------------------------------- @@ -92,591 +90,588 @@ void TImageReader::close() /*! Opens for reading using \b fopen(). */ -void TImageReader::getTzpPaletteColorNames(std::map> &pltColorNames) -{ - if (!m_file) - open(); +void TImageReader::getTzpPaletteColorNames( + std::map> &pltColorNames) { + if (!m_file) open(); - if (!m_file) - return; + if (!m_file) return; - assert(m_reader); - m_reader->getTzpPaletteColorNames(pltColorNames); + assert(m_reader); + m_reader->getTzpPaletteColorNames(pltColorNames); } //----------------------------------------------------------- -void TImageReader::open() -{ - assert(m_file == NULL); - - std::string type = toLower(m_path.getType()); - m_file = fopen(m_path, "rb"); //Opens for reading. If the file does not exist or cannot be found, the fopen_s call fails - - if (m_file == NULL) //Non dovrebbe mai andarci! - close(); //close() chiude il file se e' aperto e setta m_file a NULL. - else { - try { - m_reader = Tiio::makeReader(type); - if (m_reader) - m_reader->open(m_file); - else { - m_vectorReader = Tiio::makeVectorReader(type); - if (m_vectorReader) - m_vectorReader->open(m_file); - else - throw TImageException(m_path, "Image format not supported"); - } - } catch (TException &e) { - close(); //close() chiude il file e setta m_file a NULL. - QString msg = QString::fromStdWString(e.getMessage()); - if (msg == QString("Old 4.1 Palette")) - throw e; - } catch (std::string str) { - if (str == "Tiff file closed") - m_file = NULL; - } - } +void TImageReader::open() { + assert(m_file == NULL); + + std::string type = toLower(m_path.getType()); + m_file = fopen(m_path, "rb"); // Opens for reading. If the file does not + // exist or cannot be found, the fopen_s call + // fails + + if (m_file == NULL) // Non dovrebbe mai andarci! + close(); // close() chiude il file se e' aperto e setta m_file a NULL. + else { + try { + m_reader = Tiio::makeReader(type); + if (m_reader) + m_reader->open(m_file); + else { + m_vectorReader = Tiio::makeVectorReader(type); + if (m_vectorReader) + m_vectorReader->open(m_file); + else + throw TImageException(m_path, "Image format not supported"); + } + } catch (TException &e) { + close(); // close() chiude il file e setta m_file a NULL. + QString msg = QString::fromStdWString(e.getMessage()); + if (msg == QString("Old 4.1 Palette")) throw e; + } catch (std::string str) { + if (str == "Tiff file closed") m_file = NULL; + } + } } //=========================================================== -void TImageReader::setShrink(int shrink) -{ - m_shrink = shrink; -} +void TImageReader::setShrink(int shrink) { m_shrink = shrink; } //----------------------------------------------------------- -TImageReaderP::TImageReaderP(const TFilePath &path) -{ - m_pointer = new TImageReader(path); - m_pointer->addRef(); - m_pointer->open(); +TImageReaderP::TImageReaderP(const TFilePath &path) { + m_pointer = new TImageReader(path); + m_pointer->addRef(); + m_pointer->open(); } //----------------------------------------------------------- -TImageP TImageReader::load() -{ - - TImageP image = load0(); - if (!image) - return TImageP(); +TImageP TImageReader::load() { + TImageP image = load0(); + if (!image) return TImageP(); - TImageInfo info = m_reader->getImageInfo(); - if (info.m_lx <= 0 || info.m_ly <= 0) - return TImageP(); + TImageInfo info = m_reader->getImageInfo(); + if (info.m_lx <= 0 || info.m_ly <= 0) return TImageP(); - return image; + return image; } //============================================================ template -struct pixel_traits { -}; +struct pixel_traits {}; template <> struct pixel_traits { - typedef TPixel32 rgbm_pixel_type; - typedef char buffer_type; + typedef TPixel32 rgbm_pixel_type; + typedef char buffer_type; }; template <> struct pixel_traits { - typedef TPixel64 rgbm_pixel_type; - typedef short buffer_type; + typedef TPixel64 rgbm_pixel_type; + typedef short buffer_type; }; template <> struct pixel_traits { - typedef TPixel32 rgbm_pixel_type; - typedef char buffer_type; + typedef TPixel32 rgbm_pixel_type; + typedef char buffer_type; }; template <> struct pixel_traits { - typedef TPixel64 rgbm_pixel_type; - typedef short buffer_type; + typedef TPixel64 rgbm_pixel_type; + typedef short buffer_type; }; template <> struct pixel_traits { - typedef TPixel32 rgbm_pixel_type; - typedef char buffer_type; + typedef TPixel32 rgbm_pixel_type; + typedef char buffer_type; }; //------------------------------------------------------------------------------------ template -void copyLine(typename pixel_traits::rgbm_pixel_type *lineIn, Pix *lineOut, int x0, int length, int shrink) -{ - lineIn += x0; +void copyLine(typename pixel_traits::rgbm_pixel_type *lineIn, Pix *lineOut, + int x0, int length, int shrink) { + lineIn += x0; - for (int i = 0; i < length; ++i, lineIn += shrink, ++lineOut) - memcpy(lineOut, lineIn, sizeof(Pix)); + for (int i = 0; i < length; ++i, lineIn += shrink, ++lineOut) + memcpy(lineOut, lineIn, sizeof(Pix)); } template <> -void copyLine(TPixel32 *lineIn, TPixelGR8 *lineOut, int x0, int length, int shrink) -{ - lineIn += x0; +void copyLine(TPixel32 *lineIn, TPixelGR8 *lineOut, int x0, + int length, int shrink) { + lineIn += x0; - for (int i = 0; i < length; ++i, lineIn += shrink, ++lineOut) - lineOut->value = lineIn->r; + for (int i = 0; i < length; ++i, lineIn += shrink, ++lineOut) + lineOut->value = lineIn->r; } template <> -void copyLine(TPixel64 *lineIn, TPixelGR16 *lineOut, int x0, int length, int shrink) -{ - lineIn += x0; +void copyLine(TPixel64 *lineIn, TPixelGR16 *lineOut, int x0, + int length, int shrink) { + lineIn += x0; - for (int i = 0; i < length; ++i, lineIn += shrink, ++lineOut) - lineOut->value = lineIn->r; + for (int i = 0; i < length; ++i, lineIn += shrink, ++lineOut) + lineOut->value = lineIn->r; } //------------------------------------------------------------------------------------ template void readRaster_copyLines(const TRasterPT &ras, Tiio::Reader *reader, - int x0, int y0, int x1, int y1, - int inLx, int inLy, int shrink) -{ - typedef typename pixel_traits::buffer_type buffer_type; - typedef typename pixel_traits::rgbm_pixel_type rgbm_pixel_type; + int x0, int y0, int x1, int y1, int inLx, int inLy, + int shrink) { + typedef typename pixel_traits::buffer_type buffer_type; + typedef typename pixel_traits::rgbm_pixel_type rgbm_pixel_type; - int linesToSkip = shrink - 1; + int linesToSkip = shrink - 1; - buffer_type *lineBuffer = (buffer_type *)malloc(inLx * sizeof(rgbm_pixel_type)); - if (!lineBuffer) - return; + buffer_type *lineBuffer = + (buffer_type *)malloc(inLx * sizeof(rgbm_pixel_type)); + if (!lineBuffer) return; - rgbm_pixel_type *lineIn = (rgbm_pixel_type *)lineBuffer; + rgbm_pixel_type *lineIn = (rgbm_pixel_type *)lineBuffer; - if (reader->getRowOrder() == Tiio::BOTTOM2TOP) { - int start = reader->skipLines(y0); - int stop = y1 + 1; + if (reader->getRowOrder() == Tiio::BOTTOM2TOP) { + int start = reader->skipLines(y0); + int stop = y1 + 1; - for (int y = start; y < stop; ++y) { - reader->readLine(lineBuffer, x0, x1, shrink); + for (int y = start; y < stop; ++y) { + reader->readLine(lineBuffer, x0, x1, shrink); - if (y >= y0 && y <= y1 && (y - y0) % shrink == 0) { - Pix *line = (Pix *)ras->getRawData(0, (y - y0) / shrink); - copyLine(lineIn, line, x0, ras->getLx(), shrink); - } + if (y >= y0 && y <= y1 && (y - y0) % shrink == 0) { + Pix *line = (Pix *)ras->getRawData(0, (y - y0) / shrink); + copyLine(lineIn, line, x0, ras->getLx(), shrink); + } - if (linesToSkip > 0 && y + linesToSkip < inLy) - y += reader->skipLines(linesToSkip); - } - } else // TOP2BOTTOM - { - reader->skipLines(inLy - y1 - 1); + if (linesToSkip > 0 && y + linesToSkip < inLy) + y += reader->skipLines(linesToSkip); + } + } else // TOP2BOTTOM + { + reader->skipLines(inLy - y1 - 1); - for (int y = y1; y >= y0; --y) { - reader->readLine(lineBuffer, x0, x1, shrink); + for (int y = y1; y >= y0; --y) { + reader->readLine(lineBuffer, x0, x1, shrink); - if ((y - y0) % shrink == 0) { - Pix *line = (Pix *)ras->getRawData(0, (y - y0) / shrink); - copyLine(lineIn, line, x0, ras->getLx(), shrink); - } + if ((y - y0) % shrink == 0) { + Pix *line = (Pix *)ras->getRawData(0, (y - y0) / shrink); + copyLine(lineIn, line, x0, ras->getLx(), shrink); + } - if (linesToSkip > 0 && y - linesToSkip > 0) - y -= reader->skipLines(linesToSkip); - } - } + if (linesToSkip > 0 && y - linesToSkip > 0) + y -= reader->skipLines(linesToSkip); + } + } - free(lineBuffer); + free(lineBuffer); } //------------------------------------------------------------------------------------ template -void readRaster(const TRasterPT &ras, Tiio::Reader *reader, - int x0, int y0, int x1, int y1, - int inLx, int inLy, int shrink) -{ - typedef typename pixel_traits::buffer_type buffer_type; - - if (shrink == 1) { - // Direct read - ras->lock(); - - ptrdiff_t linePad = -x0 * ras->getPixelSize(); - - if (reader->getRowOrder() == Tiio::BOTTOM2TOP) { - int start = reader->skipLines(y0); - int stop = y1 + 1; - - for (int y = start; y < stop; ++y) - if (y >= y0 && y <= y1) { - buffer_type *line = (buffer_type *)(ras->getRawData(0, y - y0) + linePad); - reader->readLine(line, x0, x1, 1); - } - } else // TOP2BOTTOM - { - reader->skipLines(inLy - y1 - 1); - - for (int y = y1; y >= y0; --y) { - buffer_type *line = (buffer_type *)(ras->getRawData(0, y - y0) + linePad); - reader->readLine(line, x0, x1, 1); - } - } - - ras->unlock(); - } else - readRaster_copyLines(ras, reader, x0, y0, x1, y1, inLx, inLy, shrink); +void readRaster(const TRasterPT &ras, Tiio::Reader *reader, int x0, int y0, + int x1, int y1, int inLx, int inLy, int shrink) { + typedef typename pixel_traits::buffer_type buffer_type; + + if (shrink == 1) { + // Direct read + ras->lock(); + + ptrdiff_t linePad = -x0 * ras->getPixelSize(); + + if (reader->getRowOrder() == Tiio::BOTTOM2TOP) { + int start = reader->skipLines(y0); + int stop = y1 + 1; + + for (int y = start; y < stop; ++y) + if (y >= y0 && y <= y1) { + buffer_type *line = + (buffer_type *)(ras->getRawData(0, y - y0) + linePad); + reader->readLine(line, x0, x1, 1); + } + } else // TOP2BOTTOM + { + reader->skipLines(inLy - y1 - 1); + + for (int y = y1; y >= y0; --y) { + buffer_type *line = + (buffer_type *)(ras->getRawData(0, y - y0) + linePad); + reader->readLine(line, x0, x1, 1); + } + } + + ras->unlock(); + } else + readRaster_copyLines(ras, reader, x0, y0, x1, y1, inLx, inLy, shrink); } //------------------------------------------------------------------------------------ -TImageP TImageReader::load0() -{ - if (!m_reader && !m_vectorReader) - open(); - - if (m_reader) { - TImageInfo info = m_reader->getImageInfo(); - if (info.m_lx <= 0 || info.m_ly <= 0) - return TImageP(); - - // Initialize raster info - assert(m_shrink > 0); +TImageP TImageReader::load0() { + if (!m_reader && !m_vectorReader) open(); + + if (m_reader) { + TImageInfo info = m_reader->getImageInfo(); + if (info.m_lx <= 0 || info.m_ly <= 0) return TImageP(); + + // Initialize raster info + assert(m_shrink > 0); - // Build loading rect - int x0 = 0; - int x1 = info.m_lx - 1; - int y0 = 0; - int y1 = info.m_ly - 1; - - if (!m_region.isEmpty()) { - // Intersect with the externally specified loading region - - x0 = std::max(x0, m_region.x0); - y0 = std::max(y0, m_region.y0); - x1 = std::min(x1, m_region.x1); - y1 = std::min(y1, m_region.y1); - - if (x0 >= x1 || y0 >= y1) - return TImageP(); - } - - if (m_shrink > 1) { - // Crop to shrink multiples - x1 -= (x1 - x0) % m_shrink; - y1 -= (y1 - y0) % m_shrink; - } - - assert(x0 <= x1 && y0 <= y1); - - TDimension imageDimension = TDimension((x1 - x0) / m_shrink + 1, (y1 - y0) / m_shrink + 1); - - if (m_path.getType() == "tzp" || m_path.getType() == "tzu") { - // Colormap case - - TRasterCM32P ras(imageDimension); - readRaster(ras, m_reader, x0, y0, x1, y1, info.m_lx, info.m_ly, m_shrink); - - // Build the savebox - TRect saveBox(info.m_x0, info.m_y0, info.m_x1, info.m_y1); - if (!m_region.isEmpty()) { - // Intersect with the loading rect - if (m_region.overlaps(saveBox)) { - saveBox *= m_region; - - int sbx0 = saveBox.x0 - m_region.x0; - int sby0 = saveBox.y0 - m_region.y0; - int sbx1 = sbx0 + saveBox.getLx() - 1; - int sby1 = sby0 + saveBox.getLy() - 1; - assert(sbx0 >= 0); - assert(sby0 >= 0); - assert(sbx1 >= 0); - assert(sby1 >= 0); - - saveBox = TRect(sbx0, sby0, sbx1, sby1); - } else - saveBox = TRect(0, 0, 1, 1); - } - - if (m_shrink > 1) { - saveBox.x0 = saveBox.x0 / m_shrink; - saveBox.y0 = saveBox.y0 / m_shrink; - saveBox.x1 = saveBox.x1 / m_shrink; - saveBox.y1 = saveBox.y1 / m_shrink; - } - - TToonzImageP ti(ras, ras->getBounds() * saveBox); - ti->setDpi(info.m_dpix, info.m_dpiy); - - return ti; - } else if (info.m_bitsPerSample >= 8) { - // Common byte-based rasters (see below, we have black-and-white bit-based images too) - - if (info.m_samplePerPixel == 1 && m_readGreytones) { - // Greymap case - // NOTE: Uses a full 32-bit raster first, and then copies down to the GR8 - - // Observe that GR16 file images get immediately down-cast to GR8... - // Should we implement that too? - - TRasterGR8P ras(imageDimension); - readRaster_copyLines(ras, m_reader, x0, y0, x1, y1, info.m_lx, info.m_ly, m_shrink); - - TRasterImageP ri(ras); - ri->setDpi(info.m_dpix, info.m_dpiy); - - return ri; - } - - // assert(info.m_samplePerPixel == 3 || info.m_samplePerPixel == 4); - - TRasterP _ras; - if (info.m_bitsPerSample == 16) { - if (m_is64BitEnabled || m_path.getType() != "tif") { - // Standard 64-bit case. - - // Also covers down-casting to 32-bit from a 64-bit image file whenever - // not a tif file (see below). - - TRaster64P ras(imageDimension); - readRaster(ras, m_reader, x0, y0, x1, y1, info.m_lx, info.m_ly, m_shrink); - - _ras = ras; - } else { - // The Tif reader has got an automatically down-casting readLine(char*, ...) - // in case the input file is 64-bit. The advantage is that no intermediate - // 64-bit raster is required in this case. - - TRaster32P ras(imageDimension); - readRaster(ras, m_reader, x0, y0, x1, y1, info.m_lx, info.m_ly, m_shrink); - - _ras = ras; - } - } else if (info.m_bitsPerSample == 8) { - // Standard 32-bit case - TRaster32P ras(imageDimension); - readRaster(ras, m_reader, x0, y0, x1, y1, info.m_lx, info.m_ly, m_shrink); - - _ras = ras; - } else - throw TImageException(m_path, "Image format not supported"); - - // 64-bit to 32-bit conversions if necessary (64 bit images not allowed) - if (!m_is64BitEnabled && (TRaster64P)_ras) { - TRaster32P raux(_ras->getLx(), _ras->getLy()); - TRop::convert(raux, _ras); - _ras = raux; - } - - // Return the image - TRasterImageP ri(_ras); - ri->setDpi(info.m_dpix, info.m_dpiy); - - return ri; - } else if (info.m_samplePerPixel == 1 && info.m_valid == true) { - // Previously dubbed as 'Palette cases'. No clue about what is this... :| - - TRaster32P ras(imageDimension); - readRaster(ras, m_reader, x0, y0, x1, y1, info.m_lx, info.m_ly, m_shrink); - - TRasterImageP ri(ras); - ri->setDpi(info.m_dpix, info.m_dpiy); - - return ri; - } else if (info.m_samplePerPixel == 1 && m_readGreytones) { - // Black-and-White case, I guess. Standard greymaps were considered above... - - TRasterGR8P ras(imageDimension); - readRaster_copyLines(ras, m_reader, x0, y0, x1, y1, info.m_lx, info.m_ly, m_shrink); - - TRasterImageP ri(ras); - ri->setDpi(info.m_dpix, info.m_dpiy); - - if (info.m_bitsPerSample == 1) // I suspect this always evaluates true... - ri->setScanBWFlag(true); - - return ri; - } else - return TImageP(); - } else if (m_vectorReader) { - TVectorImage *vi = m_vectorReader->read(); - return TVectorImageP(vi); - } else - return TImageP(); + // Build loading rect + int x0 = 0; + int x1 = info.m_lx - 1; + int y0 = 0; + int y1 = info.m_ly - 1; + + if (!m_region.isEmpty()) { + // Intersect with the externally specified loading region + + x0 = std::max(x0, m_region.x0); + y0 = std::max(y0, m_region.y0); + x1 = std::min(x1, m_region.x1); + y1 = std::min(y1, m_region.y1); + + if (x0 >= x1 || y0 >= y1) return TImageP(); + } + + if (m_shrink > 1) { + // Crop to shrink multiples + x1 -= (x1 - x0) % m_shrink; + y1 -= (y1 - y0) % m_shrink; + } + + assert(x0 <= x1 && y0 <= y1); + + TDimension imageDimension = + TDimension((x1 - x0) / m_shrink + 1, (y1 - y0) / m_shrink + 1); + + if (m_path.getType() == "tzp" || m_path.getType() == "tzu") { + // Colormap case + + TRasterCM32P ras(imageDimension); + readRaster(ras, m_reader, x0, y0, x1, y1, info.m_lx, info.m_ly, m_shrink); + + // Build the savebox + TRect saveBox(info.m_x0, info.m_y0, info.m_x1, info.m_y1); + if (!m_region.isEmpty()) { + // Intersect with the loading rect + if (m_region.overlaps(saveBox)) { + saveBox *= m_region; + + int sbx0 = saveBox.x0 - m_region.x0; + int sby0 = saveBox.y0 - m_region.y0; + int sbx1 = sbx0 + saveBox.getLx() - 1; + int sby1 = sby0 + saveBox.getLy() - 1; + assert(sbx0 >= 0); + assert(sby0 >= 0); + assert(sbx1 >= 0); + assert(sby1 >= 0); + + saveBox = TRect(sbx0, sby0, sbx1, sby1); + } else + saveBox = TRect(0, 0, 1, 1); + } + + if (m_shrink > 1) { + saveBox.x0 = saveBox.x0 / m_shrink; + saveBox.y0 = saveBox.y0 / m_shrink; + saveBox.x1 = saveBox.x1 / m_shrink; + saveBox.y1 = saveBox.y1 / m_shrink; + } + + TToonzImageP ti(ras, ras->getBounds() * saveBox); + ti->setDpi(info.m_dpix, info.m_dpiy); + + return ti; + } else if (info.m_bitsPerSample >= 8) { + // Common byte-based rasters (see below, we have black-and-white bit-based + // images too) + + if (info.m_samplePerPixel == 1 && m_readGreytones) { + // Greymap case + // NOTE: Uses a full 32-bit raster first, and then copies down to the + // GR8 + + // Observe that GR16 file images get immediately down-cast to GR8... + // Should we implement that too? + + TRasterGR8P ras(imageDimension); + readRaster_copyLines(ras, m_reader, x0, y0, x1, y1, info.m_lx, + info.m_ly, m_shrink); + + TRasterImageP ri(ras); + ri->setDpi(info.m_dpix, info.m_dpiy); + + return ri; + } + + // assert(info.m_samplePerPixel == 3 || info.m_samplePerPixel == 4); + + TRasterP _ras; + if (info.m_bitsPerSample == 16) { + if (m_is64BitEnabled || m_path.getType() != "tif") { + // Standard 64-bit case. + + // Also covers down-casting to 32-bit from a 64-bit image file + // whenever + // not a tif file (see below). + + TRaster64P ras(imageDimension); + readRaster(ras, m_reader, x0, y0, x1, y1, info.m_lx, info.m_ly, + m_shrink); + + _ras = ras; + } else { + // The Tif reader has got an automatically down-casting + // readLine(char*, ...) + // in case the input file is 64-bit. The advantage is that no + // intermediate + // 64-bit raster is required in this case. + + TRaster32P ras(imageDimension); + readRaster(ras, m_reader, x0, y0, x1, y1, info.m_lx, info.m_ly, + m_shrink); + + _ras = ras; + } + } else if (info.m_bitsPerSample == 8) { + // Standard 32-bit case + TRaster32P ras(imageDimension); + readRaster(ras, m_reader, x0, y0, x1, y1, info.m_lx, info.m_ly, + m_shrink); + + _ras = ras; + } else + throw TImageException(m_path, "Image format not supported"); + + // 64-bit to 32-bit conversions if necessary (64 bit images not allowed) + if (!m_is64BitEnabled && (TRaster64P)_ras) { + TRaster32P raux(_ras->getLx(), _ras->getLy()); + TRop::convert(raux, _ras); + _ras = raux; + } + + // Return the image + TRasterImageP ri(_ras); + ri->setDpi(info.m_dpix, info.m_dpiy); + + return ri; + } else if (info.m_samplePerPixel == 1 && info.m_valid == true) { + // Previously dubbed as 'Palette cases'. No clue about what is this... :| + + TRaster32P ras(imageDimension); + readRaster(ras, m_reader, x0, y0, x1, y1, info.m_lx, info.m_ly, m_shrink); + + TRasterImageP ri(ras); + ri->setDpi(info.m_dpix, info.m_dpiy); + + return ri; + } else if (info.m_samplePerPixel == 1 && m_readGreytones) { + // Black-and-White case, I guess. Standard greymaps were considered + // above... + + TRasterGR8P ras(imageDimension); + readRaster_copyLines(ras, m_reader, x0, y0, x1, y1, info.m_lx, info.m_ly, + m_shrink); + + TRasterImageP ri(ras); + ri->setDpi(info.m_dpix, info.m_dpiy); + + if (info.m_bitsPerSample == 1) // I suspect this always evaluates true... + ri->setScanBWFlag(true); + + return ri; + } else + return TImageP(); + } else if (m_vectorReader) { + TVectorImage *vi = m_vectorReader->read(); + return TVectorImageP(vi); + } else + return TImageP(); } //----------------------------------------------------------- TImageWriter::TImageWriter(const TFilePath &path) - : TSmartObject(m_classCode), m_path(path), m_writer(0), m_vectorWriter(0), m_properties(0) -{ -} + : TSmartObject(m_classCode) + , m_path(path) + , m_writer(0) + , m_vectorWriter(0) + , m_properties(0) {} //----------------------------------------------------------- -TImageWriter::~TImageWriter() -{ - delete m_writer; - delete m_vectorWriter; - delete m_properties; +TImageWriter::~TImageWriter() { + delete m_writer; + delete m_vectorWriter; + delete m_properties; } //----------------------------------------------------------- -void TImageWriter::setProperties(const TPropertyGroup *g) -{ - if (m_properties) { - assert(m_properties != g); - delete m_properties; - } - m_properties = g ? g->clone() : 0; +void TImageWriter::setProperties(const TPropertyGroup *g) { + if (m_properties) { + assert(m_properties != g); + delete m_properties; + } + m_properties = g ? g->clone() : 0; } //----------------------------------------------------------- -void convertForWriting(TRasterP &ras, const TRasterP &rin, int bpp) -{ - switch (bpp) { - case 1: - case 8: - ras = TRasterGR8P(rin->getSize()); - TRop::convert(ras, rin); - break; - case 24: - case 32: - ras = TRaster32P(rin->getSize()); - TRop::convert(ras, rin); - break; - case 48: - case 64: - ras = TRaster64P(rin->getSize()); - TRop::convert(ras, rin); - break; - default: - assert(false); - } +void convertForWriting(TRasterP &ras, const TRasterP &rin, int bpp) { + switch (bpp) { + case 1: + case 8: + ras = TRasterGR8P(rin->getSize()); + TRop::convert(ras, rin); + break; + case 24: + case 32: + ras = TRaster32P(rin->getSize()); + TRop::convert(ras, rin); + break; + case 48: + case 64: + ras = TRaster64P(rin->getSize()); + TRop::convert(ras, rin); + break; + default: + assert(false); + } } //----------------------------------------------------------- -void TImageWriter::save(const TImageP &img) -{ - const std::string &type = toLower(m_path.getType()); - - Tiio::Writer *writer = Tiio::makeWriter(type); - if (!writer) - throw TImageException(m_path, "unsupported format for raster images"); - - writer->setProperties(m_properties); - - FILE *file = fopen(m_path, "wb"); - if (file == NULL) - throw TImageException(m_path, "Can't write file"); - - if (TRasterImageP ri = img) { - TImageInfo info; - TRasterP ras; - - TRasterGR8P rasGr = ri->getRaster(); - TRaster32P ras32 = ri->getRaster(); - TRaster64P ras64 = ri->getRaster(); - - TEnumProperty *p = m_properties ? (TEnumProperty *)m_properties->getProperty("Bits Per Pixel") - : 0; - - if (p && ri->isScanBW()) { - const std::vector &range = p->getRange(); - p->setValue(range[2]); // Horrible. See tiio_tif.cpp (732 or near) -.-' - } - - int bpp = p ? std::stoi(p->getValue()) : 32; - - // bpp 1 8 16 24 32 40 48 56 64 - int spp[] = {1, 1, 1, 4, 4, 0, 4, 0, 4}; // 0s are for pixel sizes which are normally unsupported - int bps[] = {1, 8, 16, 8, 8, 0, 16, 0, 16}; // by image formats, let alone by Toonz raster ones. - // The 24 and 48 cases get automatically promoted to 32 and 64. - int bypp = bpp / 8; - assert(bypp < boost::size(spp) && spp[bypp] && bps[bypp]); - - info.m_samplePerPixel = spp[bypp]; - info.m_bitsPerSample = bps[bypp]; - - if (rasGr) { - if (bypp < 2) // Seems 16 bit greymaps are not handled... why? - ras = rasGr; // we do have a Toonz raster for those... >:| - else - convertForWriting(ras, rasGr, bpp); - } else if (ras32) { - if (bpp == 32 || bpp == 24) - ras = ras32; - else - convertForWriting(ras, ras32, bpp); - } else if (ras64) { - if (bpp == 64 || bpp == 48) - ras = ras64; - else - convertForWriting(ras, ras64, bpp); - } else { - fclose(file); - throw TImageException(m_path, "unsupported raster type"); - } - - info.m_lx = ras->getLx(); - info.m_ly = ras->getLy(); - - ri->getDpi(info.m_dpix, info.m_dpiy); - - if (writer->getProperties() && m_properties) - writer->getProperties()->setProperties(m_properties); - - writer->open(file, info); - - ras->lock(); - if (writer->getRowOrder() == Tiio::BOTTOM2TOP) { - if (bpp == 1 || bpp == 8 || bpp == 24 || bpp == 32 || bpp == 16) - for (int i = 0; i < ras->getLy(); i++) - writer->writeLine((char *)ras->getRawData(0, i)); - else - for (int i = 0; i < ras->getLy(); i++) - writer->writeLine((short *)ras->getRawData(0, i)); - } else { - if (bpp == 1 || bpp == 8 || bpp == 24 || bpp == 32 || bpp == 16) - for (int i = ras->getLy() - 1; i >= 0; i--) - writer->writeLine((char *)ras->getRawData(0, i)); - else - for (int i = ras->getLy() - 1; i >= 0; i--) - writer->writeLine((short *)ras->getRawData(0, i)); - } - - ras->unlock(); - - writer->flush(); - delete writer; - } else if (TVectorImageP vi = img) { - Tiio::VectorWriter *writer = Tiio::makeVectorWriter(type); - if (!writer) { - fclose(file); - throw TImageException(m_path, "unsupported format for vector images"); - } - - writer->open(file); - writer->write(vi.getPointer()); - - delete writer; - } else { - fclose(file); - throw TImageException(m_path, "Can't write file"); - } - - fclose(file); +void TImageWriter::save(const TImageP &img) { + const std::string &type = toLower(m_path.getType()); + + Tiio::Writer *writer = Tiio::makeWriter(type); + if (!writer) + throw TImageException(m_path, "unsupported format for raster images"); + + writer->setProperties(m_properties); + + FILE *file = fopen(m_path, "wb"); + if (file == NULL) throw TImageException(m_path, "Can't write file"); + + if (TRasterImageP ri = img) { + TImageInfo info; + TRasterP ras; + + TRasterGR8P rasGr = ri->getRaster(); + TRaster32P ras32 = ri->getRaster(); + TRaster64P ras64 = ri->getRaster(); + + TEnumProperty *p = + m_properties + ? (TEnumProperty *)m_properties->getProperty("Bits Per Pixel") + : 0; + + if (p && ri->isScanBW()) { + const std::vector &range = p->getRange(); + p->setValue(range[2]); // Horrible. See tiio_tif.cpp (732 or near) -.-' + } + + int bpp = p ? std::stoi(p->getValue()) : 32; + + // bpp 1 8 16 24 32 40 48 56 64 + int spp[] = { + 1, 1, 1, 4, 4, + 0, 4, 0, 4}; // 0s are for pixel sizes which are normally unsupported + int bps[] = { + 1, 8, 16, 8, 8, + 0, 16, 0, 16}; // by image formats, let alone by Toonz raster ones. + // The 24 and 48 cases get automatically promoted to 32 and 64. + int bypp = bpp / 8; + assert(bypp < boost::size(spp) && spp[bypp] && bps[bypp]); + + info.m_samplePerPixel = spp[bypp]; + info.m_bitsPerSample = bps[bypp]; + + if (rasGr) { + if (bypp < 2) // Seems 16 bit greymaps are not handled... why? + ras = rasGr; // we do have a Toonz raster for those... >:| + else + convertForWriting(ras, rasGr, bpp); + } else if (ras32) { + if (bpp == 32 || bpp == 24) + ras = ras32; + else + convertForWriting(ras, ras32, bpp); + } else if (ras64) { + if (bpp == 64 || bpp == 48) + ras = ras64; + else + convertForWriting(ras, ras64, bpp); + } else { + fclose(file); + throw TImageException(m_path, "unsupported raster type"); + } + + info.m_lx = ras->getLx(); + info.m_ly = ras->getLy(); + + ri->getDpi(info.m_dpix, info.m_dpiy); + + if (writer->getProperties() && m_properties) + writer->getProperties()->setProperties(m_properties); + + writer->open(file, info); + + ras->lock(); + if (writer->getRowOrder() == Tiio::BOTTOM2TOP) { + if (bpp == 1 || bpp == 8 || bpp == 24 || bpp == 32 || bpp == 16) + for (int i = 0; i < ras->getLy(); i++) + writer->writeLine((char *)ras->getRawData(0, i)); + else + for (int i = 0; i < ras->getLy(); i++) + writer->writeLine((short *)ras->getRawData(0, i)); + } else { + if (bpp == 1 || bpp == 8 || bpp == 24 || bpp == 32 || bpp == 16) + for (int i = ras->getLy() - 1; i >= 0; i--) + writer->writeLine((char *)ras->getRawData(0, i)); + else + for (int i = ras->getLy() - 1; i >= 0; i--) + writer->writeLine((short *)ras->getRawData(0, i)); + } + + ras->unlock(); + + writer->flush(); + delete writer; + } else if (TVectorImageP vi = img) { + Tiio::VectorWriter *writer = Tiio::makeVectorWriter(type); + if (!writer) { + fclose(file); + throw TImageException(m_path, "unsupported format for vector images"); + } + + writer->open(file); + writer->write(vi.getPointer()); + + delete writer; + } else { + fclose(file); + throw TImageException(m_path, "Can't write file"); + } + + fclose(file); } //----------------------------------------------------------- -TImageWriterP::TImageWriterP(const TFilePath &path) -{ - m_pointer = new TImageWriter(path); - m_pointer->addRef(); +TImageWriterP::TImageWriterP(const TFilePath &path) { + m_pointer = new TImageWriter(path); + m_pointer->addRef(); } //============================================================ @@ -685,70 +680,64 @@ TImageWriterP::TImageWriterP(const TFilePath &path) // //============================================================ -bool TImageReader::load(const TFilePath &path, TRasterP &raster) -{ - raster = TRasterP(); - TImageReaderP ir(path); - if (!ir) - return false; - TImageP img = ir->load(); - if (!img) - return false; - - TRasterImageP ri(img); - if (!ri) - return false; - - raster = ri->getRaster(); - return true; +bool TImageReader::load(const TFilePath &path, TRasterP &raster) { + raster = TRasterP(); + TImageReaderP ir(path); + if (!ir) return false; + TImageP img = ir->load(); + if (!img) return false; + + TRasterImageP ri(img); + if (!ri) return false; + + raster = ri->getRaster(); + return true; } //----------------------------------------------------------- //----------------------------------------------------------- -void TImageReader::load(const TRasterP &ras, const TPoint &pos, int shrinkX, int shrinkY) -{ - TImageP srcImage = load(); - TRasterImageP srcRasImage = srcImage; - TRaster32P srcRaster = srcRasImage->getRaster(); - /* +void TImageReader::load(const TRasterP &ras, const TPoint &pos, int shrinkX, + int shrinkY) { + TImageP srcImage = load(); + TRasterImageP srcRasImage = srcImage; + TRaster32P srcRaster = srcRasImage->getRaster(); + /* TRaster32P clippedRas = srcRaster->extractT - (shrinkX*pos.x, shrinkY*pos.y, - (pos.x + ras->getLx()) * shrinkX - 1, (pos.y + ras->getLy()) * shrinkY - 1); + (shrinkX*pos.x, shrinkY*pos.y, + (pos.x + ras->getLx()) * shrinkX - 1, (pos.y + ras->getLy()) * shrinkY - 1); if (shrinkX != 1 || shrinkY != 1) { - TRaster32P ras32 = ras; - if (ras32) - ras32->fill(TPixel32::Transparent); - TRop::resample(ras, clippedRas, TScale(1./shrinkX, 1./shrinkY), TRop::ClosestPixel); +TRaster32P ras32 = ras; +if (ras32) +ras32->fill(TPixel32::Transparent); +TRop::resample(ras, clippedRas, TScale(1./shrinkX, 1./shrinkY), +TRop::ClosestPixel); } else*/ - ras->copy(srcRaster); + ras->copy(srcRaster); } //----------------------------------------------------------- -bool TImageReader::load(const TFilePath &path, TImageP &image) -{ - image = TImageReaderP(path)->load(); - return image; +bool TImageReader::load(const TFilePath &path, TImageP &image) { + image = TImageReaderP(path)->load(); + return image; } //----------------------------------------------------------- -void TImageWriter::save(const TFilePath &path, TRasterP raster) -{ - TRasterImageP rasImage(raster); - TImageWriterP(path)->save(TImageP(rasImage)); +void TImageWriter::save(const TFilePath &path, TRasterP raster) { + TRasterImageP rasImage(raster); + TImageWriterP(path)->save(TImageP(rasImage)); } //----------------------------------------------------------- -void TImageWriter::save(const TFilePath &path, const TImageP &image) -{ - TImageWriterP(path)->save(image); +void TImageWriter::save(const TFilePath &path, const TImageP &image) { + TImageWriterP(path)->save(image); } //=========================================================== @@ -757,53 +746,46 @@ void TImageWriter::save(const TFilePath &path, const TImageP &image) // //=========================================================== -void TImageReader::define( - QString extension, - TImageReaderCreateProc *proc) -{ - ImageReaderTable[extension] = proc; +void TImageReader::define(QString extension, TImageReaderCreateProc *proc) { + ImageReaderTable[extension] = proc; } //----------------------------------------------------------- -void TImageWriter::define( - QString extension, - TImageWriterCreateProc *proc, bool isRenderFormat) -{ - ImageWriterTable[extension] = std::pair(proc, isRenderFormat); +void TImageWriter::define(QString extension, TImageWriterCreateProc *proc, + bool isRenderFormat) { + ImageWriterTable[extension] = + std::pair(proc, isRenderFormat); } //----------------------------------------------------------- -void TImageReader::getSupportedFormats(QStringList &names) -{ - for (std::map::iterator it = ImageReaderTable.begin(); - it != ImageReaderTable.end(); - ++it) { - names.push_back(it->first); - } +void TImageReader::getSupportedFormats(QStringList &names) { + for (std::map::iterator it = + ImageReaderTable.begin(); + it != ImageReaderTable.end(); ++it) { + names.push_back(it->first); + } } //----------------------------------------------------------- -void TImageWriter::getSupportedFormats(QStringList &names, bool onlyRenderFormat) -{ - for (std::map>::iterator it = ImageWriterTable.begin(); - it != ImageWriterTable.end(); - ++it) { - if (!onlyRenderFormat || it->second.second) - names.push_back(it->first); - } +void TImageWriter::getSupportedFormats(QStringList &names, + bool onlyRenderFormat) { + for (std::map>::iterator + it = ImageWriterTable.begin(); + it != ImageWriterTable.end(); ++it) { + if (!onlyRenderFormat || it->second.second) names.push_back(it->first); + } } //----------------------------------------------------------- -const TImageInfo *TImageReader::getImageInfo() const -{ - if (m_reader) - return &(m_reader->getImageInfo()); - else - return 0; +const TImageInfo *TImageReader::getImageInfo() const { + if (m_reader) + return &(m_reader->getImageInfo()); + else + return 0; } //----------------------------------------------------------- @@ -815,22 +797,21 @@ const TImageInfo *TImageReader::getImageInfo() const //=========================================================== TImageException::TImageException(const TFilePath &fp, const std::string &msg) - : TException(msg), m_fp(fp) -{ -} + : TException(msg), m_fp(fp) {} //----------------------------------------------------------- -TString TImageException::getMessage() const -{ - return m_fp.getWideString() + L": " + TException::getMessage(); +TString TImageException::getMessage() const { + return m_fp.getWideString() + L": " + TException::getMessage(); } //=========================================================== -TImageVersionException::TImageVersionException(const TFilePath &fp, int major, int minor) - : TException(L"The file " + fp.getWideString() + - L" was generated by a newer version of Toonz and cannot be loaded."), - m_fp(fp), m_major(major), m_minor(minor) -{ -} +TImageVersionException::TImageVersionException(const TFilePath &fp, int major, + int minor) + : TException( + L"The file " + fp.getWideString() + + L" was generated by a newer version of Toonz and cannot be loaded.") + , m_fp(fp) + , m_major(major) + , m_minor(minor) {} diff --git a/toonz/sources/common/timage_io/tlevel_io.cpp b/toonz/sources/common/timage_io/tlevel_io.cpp index f2a4e38..7d5666b 100644 --- a/toonz/sources/common/timage_io/tlevel_io.cpp +++ b/toonz/sources/common/timage_io/tlevel_io.cpp @@ -18,352 +18,329 @@ using namespace std; DEFINE_CLASS_CODE(TLevelReader, 8) DEFINE_CLASS_CODE(TLevelWriter, 9) -//DEFINE_CLASS_CODE(TLevelReaderWriter, 25) //brutto +// DEFINE_CLASS_CODE(TLevelReaderWriter, 25) //brutto //----------------------------------------------------------- typedef std::pair LevelReaderKey; std::map LevelReaderTable; std::map> LevelWriterTable; -//std::map LevelReaderWriterTable; +// std::map LevelReaderWriterTable; //----------------------------------------------------------- TLevelReader::TLevelReader(const TFilePath &path) - : TSmartObject(m_classCode), m_info(0), m_path(path), m_contentHistory(0), m_frameFormat(TFrameId::FOUR_ZEROS) -{ -} + : TSmartObject(m_classCode) + , m_info(0) + , m_path(path) + , m_contentHistory(0) + , m_frameFormat(TFrameId::FOUR_ZEROS) {} //----------------------------------------------------------- -TLevelReader::~TLevelReader() -{ - delete m_contentHistory; - delete m_info; +TLevelReader::~TLevelReader() { + delete m_contentHistory; + delete m_info; } //----------------------------------------------------------- -TLevelReaderP::TLevelReaderP(const TFilePath &path, int reader) -{ - QString extension = QString::fromStdString(toLower(path.getType())); - LevelReaderKey key(extension, reader); - std::map::iterator it; - it = LevelReaderTable.find(key); - if (it != LevelReaderTable.end()) { - m_pointer = it->second(path); - assert(m_pointer); - } else { - m_pointer = new TLevelReader(path); - } - m_pointer->addRef(); +TLevelReaderP::TLevelReaderP(const TFilePath &path, int reader) { + QString extension = QString::fromStdString(toLower(path.getType())); + LevelReaderKey key(extension, reader); + std::map::iterator it; + it = LevelReaderTable.find(key); + if (it != LevelReaderTable.end()) { + m_pointer = it->second(path); + assert(m_pointer); + } else { + m_pointer = new TLevelReader(path); + } + m_pointer->addRef(); } //----------------------------------------------------------- -namespace -{ -bool myLess(const TFilePath &l, const TFilePath &r) -{ - return l.getFrame() < r.getFrame(); +namespace { +bool myLess(const TFilePath &l, const TFilePath &r) { + return l.getFrame() < r.getFrame(); } } //----------------------------------------------------------- -const TImageInfo *TLevelReader::getImageInfo(TFrameId fid) -{ - if (m_info) - return m_info; - else { - TImageReaderP frameReader = getFrameReader(fid); - if (!frameReader) - return 0; - - const TImageInfo *fInfo = frameReader->getImageInfo(); - if (!fInfo) - return 0; - - m_info = new TImageInfo(*fInfo); - if (m_info->m_properties) - m_info->m_properties = m_info->m_properties->clone(); - - return m_info; - } +const TImageInfo *TLevelReader::getImageInfo(TFrameId fid) { + if (m_info) + return m_info; + else { + TImageReaderP frameReader = getFrameReader(fid); + if (!frameReader) return 0; + + const TImageInfo *fInfo = frameReader->getImageInfo(); + if (!fInfo) return 0; + + m_info = new TImageInfo(*fInfo); + if (m_info->m_properties) + m_info->m_properties = m_info->m_properties->clone(); + + return m_info; + } } //----------------------------------------------------------- -const TImageInfo *TLevelReader::getImageInfo() -{ - if (m_info) - return m_info; - TLevelP level = loadInfo(); - if (level->getFrameCount() == 0) - return 0; - return getImageInfo(level->begin()->first); +const TImageInfo *TLevelReader::getImageInfo() { + if (m_info) return m_info; + TLevelP level = loadInfo(); + if (level->getFrameCount() == 0) return 0; + return getImageInfo(level->begin()->first); } //----------------------------------------------------------- -TLevelP TLevelReader::loadInfo() -{ - TFilePath parentDir = m_path.getParentDir(); - TFilePath levelName(m_path.getLevelName()); - // cout << "Parent dir = '" << parentDir << "'" << endl; - // cout << "Level name = '" << levelName << "'" << endl; - TFilePathSet files; - try { - files = TSystem::readDirectory(parentDir, false, true, true); - } catch (...) { - throw TImageException(m_path, "unable to read directory content"); - } - TLevelP level; - vector data; - for (TFilePathSet::iterator it = files.begin(); it != files.end(); it++) { - TFilePath ln(it->getLevelName()); - // cout << "try " << *it << " " << it->getLevelName() << endl; - if (levelName == TFilePath(it->getLevelName())) { - try { - level->setFrame(it->getFrame(), TImageP()); - data.push_back(*it); - } catch (string msg) { - throw msg; - } - } - } - if (!data.empty()) { - std::vector::iterator it = std::min_element(data.begin(), data.end(), myLess); - TFilePath fr = (*it).withoutParentDir().withName("").withType(""); - wstring ws = fr.getWideString(); - if (ws.length() == 5) { - if (ws.rfind(L'_') == (int)wstring::npos) - m_frameFormat = TFrameId::FOUR_ZEROS; - else - m_frameFormat = TFrameId::UNDERSCORE_FOUR_ZEROS; - } else { - if (ws.rfind(L'_') == (int)wstring::npos) - m_frameFormat = TFrameId::NO_PAD; - else - m_frameFormat = TFrameId::UNDERSCORE_NO_PAD; - } - - } else - m_frameFormat = TFrameId::FOUR_ZEROS; - - return level; +TLevelP TLevelReader::loadInfo() { + TFilePath parentDir = m_path.getParentDir(); + TFilePath levelName(m_path.getLevelName()); + // cout << "Parent dir = '" << parentDir << "'" << endl; + // cout << "Level name = '" << levelName << "'" << endl; + TFilePathSet files; + try { + files = TSystem::readDirectory(parentDir, false, true, true); + } catch (...) { + throw TImageException(m_path, "unable to read directory content"); + } + TLevelP level; + vector data; + for (TFilePathSet::iterator it = files.begin(); it != files.end(); it++) { + TFilePath ln(it->getLevelName()); + // cout << "try " << *it << " " << it->getLevelName() << endl; + if (levelName == TFilePath(it->getLevelName())) { + try { + level->setFrame(it->getFrame(), TImageP()); + data.push_back(*it); + } catch (string msg) { + throw msg; + } + } + } + if (!data.empty()) { + std::vector::iterator it = + std::min_element(data.begin(), data.end(), myLess); + TFilePath fr = (*it).withoutParentDir().withName("").withType(""); + wstring ws = fr.getWideString(); + if (ws.length() == 5) { + if (ws.rfind(L'_') == (int)wstring::npos) + m_frameFormat = TFrameId::FOUR_ZEROS; + else + m_frameFormat = TFrameId::UNDERSCORE_FOUR_ZEROS; + } else { + if (ws.rfind(L'_') == (int)wstring::npos) + m_frameFormat = TFrameId::NO_PAD; + else + m_frameFormat = TFrameId::UNDERSCORE_NO_PAD; + } + + } else + m_frameFormat = TFrameId::FOUR_ZEROS; + + return level; } //----------------------------------------------------------- -TImageReaderP TLevelReader::getFrameReader(TFrameId fid) -{ - return TImageReaderP(m_path.withFrame(fid, m_frameFormat)); +TImageReaderP TLevelReader::getFrameReader(TFrameId fid) { + return TImageReaderP(m_path.withFrame(fid, m_frameFormat)); } //----------------------------------------------------------- -void TLevelReader::getSupportedFormats(QStringList &names) -{ - for (std::map::iterator it = LevelReaderTable.begin(); - it != LevelReaderTable.end(); - ++it) { - names.push_back(it->first.first); - } +void TLevelReader::getSupportedFormats(QStringList &names) { + for (std::map::iterator it = + LevelReaderTable.begin(); + it != LevelReaderTable.end(); ++it) { + names.push_back(it->first.first); + } } //----------------------------------------------------------- -TSoundTrack *TLevelReader::loadSoundTrack() -{ - return 0; -} +TSoundTrack *TLevelReader::loadSoundTrack() { return 0; } //=========================================================== TLevelWriter::TLevelWriter(const TFilePath &path, TPropertyGroup *prop) - : TSmartObject(m_classCode), m_path(path), m_properties(prop), m_contentHistory(0) -{ - string ext = path.getType(); - if (!prop) - m_properties = Tiio::makeWriterProperties(ext); + : TSmartObject(m_classCode) + , m_path(path) + , m_properties(prop) + , m_contentHistory(0) { + string ext = path.getType(); + if (!prop) m_properties = Tiio::makeWriterProperties(ext); } //----------------------------------------------------------- -TLevelWriter::~TLevelWriter() -{ - delete m_properties; - delete m_contentHistory; +TLevelWriter::~TLevelWriter() { + delete m_properties; + delete m_contentHistory; } //----------------------------------------------------------- -TLevelWriterP::TLevelWriterP(const TFilePath &path, TPropertyGroup *winfo) -{ - QString type = QString::fromStdString(toLower(path.getType())); - std::map>::iterator it; - it = LevelWriterTable.find(type); - if (it != LevelWriterTable.end()) - m_pointer = it->second.first(path, winfo ? winfo->clone() : Tiio::makeWriterProperties(path.getType())); - else - m_pointer = new TLevelWriter(path, winfo ? winfo->clone() : Tiio::makeWriterProperties(path.getType())); - - assert(m_pointer); - m_pointer->addRef(); +TLevelWriterP::TLevelWriterP(const TFilePath &path, TPropertyGroup *winfo) { + QString type = QString::fromStdString(toLower(path.getType())); + std::map>::iterator it; + it = LevelWriterTable.find(type); + if (it != LevelWriterTable.end()) + m_pointer = it->second.first( + path, + winfo ? winfo->clone() : Tiio::makeWriterProperties(path.getType())); + else + m_pointer = new TLevelWriter( + path, + winfo ? winfo->clone() : Tiio::makeWriterProperties(path.getType())); + + assert(m_pointer); + m_pointer->addRef(); } //----------------------------------------------------------- -void TLevelWriter::save(const TLevelP &level) -{ - for (TLevel::Iterator it = level->begin(); it != level->end(); it++) { - if (it->second) - getFrameWriter(it->first)->save(it->second); - } +void TLevelWriter::save(const TLevelP &level) { + for (TLevel::Iterator it = level->begin(); it != level->end(); it++) { + if (it->second) getFrameWriter(it->first)->save(it->second); + } } //----------------------------------------------------------- -void TLevelWriter::saveSoundTrack(TSoundTrack *) -{ - return; - throw TException("The level format doesn't support soundtracks"); +void TLevelWriter::saveSoundTrack(TSoundTrack *) { + return; + throw TException("The level format doesn't support soundtracks"); } //----------------------------------------------------------- -void TLevelWriter::setFrameRate(double fps) -{ - m_frameRate = fps; -} +void TLevelWriter::setFrameRate(double fps) { m_frameRate = fps; } //----------------------------------------------------------- -void TLevelWriter::getSupportedFormats(QStringList &names, bool onlyRenderFormats) -{ - for (std::map>::iterator it = LevelWriterTable.begin(); - it != LevelWriterTable.end(); - ++it) { - if (!onlyRenderFormats || it->second.second) - names.push_back(it->first); - } +void TLevelWriter::getSupportedFormats(QStringList &names, + bool onlyRenderFormats) { + for (std::map>::iterator + it = LevelWriterTable.begin(); + it != LevelWriterTable.end(); ++it) { + if (!onlyRenderFormats || it->second.second) names.push_back(it->first); + } } //----------------------------------------------------------- -TImageWriterP TLevelWriter::getFrameWriter(TFrameId fid) -{ - TImageWriterP iw(m_path.withFrame(fid)); - iw->setProperties(m_properties); - return iw; +TImageWriterP TLevelWriter::getFrameWriter(TFrameId fid) { + TImageWriterP iw(m_path.withFrame(fid)); + iw->setProperties(m_properties); + return iw; } //----------------------------------------------------------- -void TLevelWriter::setContentHistory(TContentHistory *contentHistory) -{ - if (contentHistory != m_contentHistory) { - delete m_contentHistory; - m_contentHistory = contentHistory; - } +void TLevelWriter::setContentHistory(TContentHistory *contentHistory) { + if (contentHistory != m_contentHistory) { + delete m_contentHistory; + m_contentHistory = contentHistory; + } } //----------------------------------------------------------- -void TLevelWriter::renumberFids(const std::map &table) -{ - typedef std::map Table; - - struct locals { - static inline QString qstring(const TFilePath &fp) - { - return QString::fromStdWString(fp.getWideString()); - } - static inline QString temp(const QString &str) - { - return str + QString("_"); - } - }; - - if (m_path.getDots() == "..") { - try { - // Extract all image file paths of the level - QDir parentDir(QString::fromStdWString(m_path.getParentDir().getWideString())); - parentDir.setFilter(QDir::Files); - - QStringList nameFilters( - QString::fromStdWString(m_path.getWideName()) + - ".*." + - QString::fromStdString(m_path.getType())); - parentDir.setNameFilters(nameFilters); - - TFilePathSet fpset; - TSystem::readDirectory(fpset, parentDir, false); // Could throw - - // Traverse each file, trying to match it with a table entry - std::vector storedDstPaths; - - TFilePathSet::iterator st, sEnd(fpset.end()); - for (st = fpset.begin(); st != sEnd; ++st) { - const QString &src = locals::qstring(*st); - const TFrameId &fid = st->getFrame(); // Could throw ! (and I'm quite appalled of that o.o') - - Table::const_iterator dt(table.find(fid)); - if (dt == table.end()) { - // The frame must be removed - QFile::remove(src); - } else { - if (fid == dt->second) - continue; - - // The frame must be renumbered - const QString &dst = locals::qstring(st->withFrame(dt->second)); - - if (!QFile::rename(src, dst)) { - // Use a temporary file rename to ensure that other frames to be renumbered - // are not overwritten. - if (QFile::rename(locals::qstring(*st), locals::temp(dst))) - storedDstPaths.push_back(dst); - - // If the second rename did not happen, the problem was not on dst, but on src. - // Alas, it means that rename on source is not possible - skip. - } - } - } - - // At this point, temporaries should be restored to originals. In case the - // rename of one of those files cannot be finalized, leave the temporary - as - // it may be impossible to roll back (another frame could have been renumbered - // to the would-roll-back frame) ! - - std::vector::iterator dt, dEnd(storedDstPaths.end()); - for (dt = storedDstPaths.begin(); dt != dEnd; ++dt) - QFile::rename(locals::temp(*dt), *dt); - } catch (...) { - // Could not read the directory - skip silently - } - } +void TLevelWriter::renumberFids(const std::map &table) { + typedef std::map Table; + + struct locals { + static inline QString qstring(const TFilePath &fp) { + return QString::fromStdWString(fp.getWideString()); + } + static inline QString temp(const QString &str) { + return str + QString("_"); + } + }; + + if (m_path.getDots() == "..") { + try { + // Extract all image file paths of the level + QDir parentDir( + QString::fromStdWString(m_path.getParentDir().getWideString())); + parentDir.setFilter(QDir::Files); + + QStringList nameFilters(QString::fromStdWString(m_path.getWideName()) + + ".*." + QString::fromStdString(m_path.getType())); + parentDir.setNameFilters(nameFilters); + + TFilePathSet fpset; + TSystem::readDirectory(fpset, parentDir, false); // Could throw + + // Traverse each file, trying to match it with a table entry + std::vector storedDstPaths; + + TFilePathSet::iterator st, sEnd(fpset.end()); + for (st = fpset.begin(); st != sEnd; ++st) { + const QString &src = locals::qstring(*st); + const TFrameId &fid = st->getFrame(); // Could throw ! (and I'm quite + // appalled of that o.o') + + Table::const_iterator dt(table.find(fid)); + if (dt == table.end()) { + // The frame must be removed + QFile::remove(src); + } else { + if (fid == dt->second) continue; + + // The frame must be renumbered + const QString &dst = locals::qstring(st->withFrame(dt->second)); + + if (!QFile::rename(src, dst)) { + // Use a temporary file rename to ensure that other frames to be + // renumbered + // are not overwritten. + if (QFile::rename(locals::qstring(*st), locals::temp(dst))) + storedDstPaths.push_back(dst); + + // If the second rename did not happen, the problem was not on dst, + // but on src. + // Alas, it means that rename on source is not possible - skip. + } + } + } + + // At this point, temporaries should be restored to originals. In case the + // rename of one of those files cannot be finalized, leave the temporary - + // as + // it may be impossible to roll back (another frame could have been + // renumbered + // to the would-roll-back frame) ! + + std::vector::iterator dt, dEnd(storedDstPaths.end()); + for (dt = storedDstPaths.begin(); dt != dEnd; ++dt) + QFile::rename(locals::temp(*dt), *dt); + } catch (...) { + // Could not read the directory - skip silently + } + } } //============================================================ -void TLevelReader::define( - QString extension, - int reader, - TLevelReaderCreateProc *proc) -{ - LevelReaderKey key(extension, reader); - LevelReaderTable[key] = proc; - //cout << "LevelReader " << extension << " registred" << endl; +void TLevelReader::define(QString extension, int reader, + TLevelReaderCreateProc *proc) { + LevelReaderKey key(extension, reader); + LevelReaderTable[key] = proc; + // cout << "LevelReader " << extension << " registred" << endl; } //----------------------------------------------------------- -void TLevelWriter::define( - QString extension, - TLevelWriterCreateProc *proc, bool isRenderFormat) -{ - LevelWriterTable[extension] = std::pair(proc, isRenderFormat); - //cout << "LevelWriter " << extension << " registred" << endl; +void TLevelWriter::define(QString extension, TLevelWriterCreateProc *proc, + bool isRenderFormat) { + LevelWriterTable[extension] = + std::pair(proc, isRenderFormat); + // cout << "LevelWriter " << extension << " registred" << endl; } diff --git a/toonz/sources/common/tipc/t32bitsrv_wrap.cpp b/toonz/sources/common/tipc/t32bitsrv_wrap.cpp index 80da092..55dc2bf 100644 --- a/toonz/sources/common/tipc/t32bitsrv_wrap.cpp +++ b/toonz/sources/common/tipc/t32bitsrv_wrap.cpp @@ -6,73 +6,67 @@ //================================================================================ -int t32bitsrv::BufferExchanger::read(const char *srcBuf, int len) -{ - m_data = (UCHAR *)memcpy(m_data, srcBuf, len); - return len; +int t32bitsrv::BufferExchanger::read(const char *srcBuf, int len) { + m_data = (UCHAR *)memcpy(m_data, srcBuf, len); + return len; } //-------------------------------------------------------------------------------- -int t32bitsrv::BufferExchanger::write(char *dstBuf, int len) -{ - memcpy(dstBuf, m_data, len); - m_data += len; +int t32bitsrv::BufferExchanger::write(char *dstBuf, int len) { + memcpy(dstBuf, m_data, len); + m_data += len; - return len; + return len; } //================================================================================ template -int t32bitsrv::RasterExchanger::read(const char *srcBuf, int len) -{ - if (m_ras->getWrap() == m_ras->getLx()) { - memcpy(m_pix, srcBuf, len); - m_pix = (PIXEL *)((UCHAR *)m_pix + len); - } else { - int xStart = (m_pix - m_ras->pixels(0)) % m_ras->getWrap(); - int remainingData = len; - int lineData = m_ras->getLx() * sizeof(PIXEL); - int lineDataToRead = std::min((int)((m_ras->getLx() - xStart) * sizeof(PIXEL)), remainingData); - - for (; remainingData > 0; - m_pix += (m_ras->getWrap() - xStart), - remainingData -= lineDataToRead, - lineDataToRead = std::min(lineData, remainingData), - xStart = 0) - memcpy(m_pix, srcBuf, lineDataToRead); - } - - return len; +int t32bitsrv::RasterExchanger::read(const char *srcBuf, int len) { + if (m_ras->getWrap() == m_ras->getLx()) { + memcpy(m_pix, srcBuf, len); + m_pix = (PIXEL *)((UCHAR *)m_pix + len); + } else { + int xStart = (m_pix - m_ras->pixels(0)) % m_ras->getWrap(); + int remainingData = len; + int lineData = m_ras->getLx() * sizeof(PIXEL); + int lineDataToRead = std::min( + (int)((m_ras->getLx() - xStart) * sizeof(PIXEL)), remainingData); + + for (; remainingData > 0; + m_pix += (m_ras->getWrap() - xStart), remainingData -= lineDataToRead, + lineDataToRead = std::min(lineData, remainingData), xStart = 0) + memcpy(m_pix, srcBuf, lineDataToRead); + } + + return len; } //-------------------------------------------------------------------------------- template -int t32bitsrv::RasterExchanger::write(char *dstBuf, int len) -{ - //We pass entire pixels, not just bytes - len = len - (len % sizeof(PIXEL)); - - if (m_ras->getWrap() == m_ras->getLx()) { - memcpy(dstBuf, m_pix, len); - m_pix = (PIXEL *)((UCHAR *)m_pix + len); - } else { - int xStart = (m_pix - m_ras->pixels(0)) % m_ras->getWrap(); - int remainingData = len; - int lineData = m_ras->getLx() * sizeof(PIXEL); - int lineDataToWrite = std::min((int)((m_ras->getLx() - xStart) * sizeof(PIXEL)), remainingData); - - for (; remainingData > 0; - m_pix += (m_ras->getWrap() - xStart), - remainingData -= lineDataToWrite, - lineDataToWrite = std::min(lineData, remainingData), - xStart = 0) - memcpy(dstBuf, m_pix, lineDataToWrite); - } - - return len; +int t32bitsrv::RasterExchanger::write(char *dstBuf, int len) { + // We pass entire pixels, not just bytes + len = len - (len % sizeof(PIXEL)); + + if (m_ras->getWrap() == m_ras->getLx()) { + memcpy(dstBuf, m_pix, len); + m_pix = (PIXEL *)((UCHAR *)m_pix + len); + } else { + int xStart = (m_pix - m_ras->pixels(0)) % m_ras->getWrap(); + int remainingData = len; + int lineData = m_ras->getLx() * sizeof(PIXEL); + int lineDataToWrite = std::min( + (int)((m_ras->getLx() - xStart) * sizeof(PIXEL)), remainingData); + + for (; remainingData > 0; + m_pix += (m_ras->getWrap() - xStart), remainingData -= lineDataToWrite, + lineDataToWrite = std::min(lineData, remainingData), xStart = 0) + memcpy(dstBuf, m_pix, lineDataToWrite); + } + + return len; } //-------------------------------------------------------------------------------- diff --git a/toonz/sources/common/tipc/tipc.cpp b/toonz/sources/common/tipc/tipc.cpp index 4da83cc..93f77de 100644 --- a/toonz/sources/common/tipc/tipc.cpp +++ b/toonz/sources/common/tipc/tipc.cpp @@ -1,6 +1,6 @@ -//Qt includes +// Qt includes #include #include #include @@ -12,7 +12,7 @@ #include #include -//System-specific includes +// System-specific includes #ifdef _WIN32 #include #elif MACOSX @@ -33,7 +33,8 @@ Please, be careful that: - It seems that, on Windows, QLocalSocket::waitForBytesWritten does not return success unless the data is actually read on the other end. On Unix this is not - the case, presumably because the data is written to a buffer which can be read by + the case, presumably because the data is written to a buffer which can be read +by the other process at some later point. Thus, *BE SURE* that every data written is received on the other side. @@ -42,8 +43,10 @@ Please, be careful that: On a standard machine, the maximum size of a shared segment is 4 MB, exactly the same as the TOTAL size of shared memory available. - Whereas tipc respects the former parameter, there must be a way to circumvent the - latter in order to make the allocation of multiple shared segments of the maximum + Whereas tipc respects the former parameter, there must be a way to circumvent +the + latter in order to make the allocation of multiple shared segments of the +maximum size. */ @@ -67,8 +70,7 @@ Please, be careful that: // Local namespace Stuff //******************************************************** -namespace -{ +namespace { int shm_max = -1; int shm_all = -1; int shm_seg = -1; @@ -79,82 +81,80 @@ int shm_mni = -1; // tipc Stream Implementation //******************************************************** -int tipc::Stream::readSize() -{ - if (m_socket->bytesAvailable() < sizeof(TINT32)) - return -1; +int tipc::Stream::readSize() { + if (m_socket->bytesAvailable() < sizeof(TINT32)) return -1; - TINT32 msgSize = -1; - m_socket->peek((char *)&msgSize, sizeof(TINT32)); + TINT32 msgSize = -1; + m_socket->peek((char *)&msgSize, sizeof(TINT32)); - return msgSize; + return msgSize; } //------------------------------------------------------------- -bool tipc::Stream::messageReady() -{ - TINT32 msgSize; - return (msgSize = readSize()) >= 0 && m_socket->bytesAvailable() >= msgSize; +bool tipc::Stream::messageReady() { + TINT32 msgSize; + return (msgSize = readSize()) >= 0 && m_socket->bytesAvailable() >= msgSize; } //------------------------------------------------------------- -bool tipc::Stream::readData(char *data, qint64 dataSize, int msecs) -{ - tipc_debug(qDebug("tipc::Stream::readData entry")); - qint64 r, dataRead = 0; - char *currData = data; +bool tipc::Stream::readData(char *data, qint64 dataSize, int msecs) { + tipc_debug(qDebug("tipc::Stream::readData entry")); + qint64 r, dataRead = 0; + char *currData = data; - while (dataRead < dataSize) { - if ((m_socket->bytesAvailable() == 0) && !m_socket->waitForReadyRead(msecs)) { - tipc_debug(qDebug("tipc::Stream::readData exit (unexpected loss of data)")); - return false; - } + while (dataRead < dataSize) { + if ((m_socket->bytesAvailable() == 0) && + !m_socket->waitForReadyRead(msecs)) { + tipc_debug( + qDebug("tipc::Stream::readData exit (unexpected loss of data)")); + return false; + } - //Read the supplied data - currData += r = m_socket->read(currData, dataSize - dataRead); - dataRead += r; - } + // Read the supplied data + currData += r = m_socket->read(currData, dataSize - dataRead); + dataRead += r; + } - tipc_debug(qDebug("tipc::Stream::readData exit")); + tipc_debug(qDebug("tipc::Stream::readData exit")); - return true; + return true; } //------------------------------------------------------------- bool tipc::Stream::readDataNB(char *data, qint64 dataSize, int msecs, - QEventLoop::ProcessEventsFlag flag) -{ - tipc_debug(qDebug("tipc::Stream::readDataNB entry")); - qint64 r, dataRead = 0; - char *currData = data; - - QEventLoop loop; - QObject::connect(m_socket, SIGNAL(readyRead()), &loop, SLOT(quit())); - QObject::connect(m_socket, SIGNAL(error(QLocalSocket::LocalSocketError)), &loop, SLOT(quit())); - - if (msecs >= 0) - QTimer::singleShot(msecs, &loop, SLOT(quit())); - - while (dataRead < dataSize) { - if (m_socket->bytesAvailable() == 0) { - loop.exec(flag); - if (m_socket->bytesAvailable() == 0) { - tipc_debug(qDebug("tipc::Stream::readDataNB exit (unexpected loss of data)")); - return false; - } - } - - //Read the supplied data - currData += r = m_socket->read(currData, dataSize - dataRead); - dataRead += r; - } - - tipc_debug(qDebug("tipc::Stream::readDataNB exit")); - - return true; + QEventLoop::ProcessEventsFlag flag) { + tipc_debug(qDebug("tipc::Stream::readDataNB entry")); + qint64 r, dataRead = 0; + char *currData = data; + + QEventLoop loop; + QObject::connect(m_socket, SIGNAL(readyRead()), &loop, SLOT(quit())); + QObject::connect(m_socket, SIGNAL(error(QLocalSocket::LocalSocketError)), + &loop, SLOT(quit())); + + if (msecs >= 0) QTimer::singleShot(msecs, &loop, SLOT(quit())); + + while (dataRead < dataSize) { + if (m_socket->bytesAvailable() == 0) { + loop.exec(flag); + if (m_socket->bytesAvailable() == 0) { + tipc_debug( + qDebug("tipc::Stream::readDataNB exit (unexpected loss of data)")); + return false; + } + } + + // Read the supplied data + currData += r = m_socket->read(currData, dataSize - dataRead); + dataRead += r; + } + + tipc_debug(qDebug("tipc::Stream::readDataNB exit")); + + return true; } //------------------------------------------------------------- @@ -166,17 +166,14 @@ bool tipc::Stream::readDataNB(char *data, qint64 dataSize, int msecs, an inactivity timeout which can be supplied to drop the operation after msecs milliseconds no data has been received. */ -bool tipc::Stream::readMessage(Message &msg, int msecs) -{ - TINT32 msgSize = 0; - if (!readData((char *)&msgSize, sizeof(TINT32), msecs)) - return false; +bool tipc::Stream::readMessage(Message &msg, int msecs) { + TINT32 msgSize = 0; + if (!readData((char *)&msgSize, sizeof(TINT32), msecs)) return false; - msg.ba().resize(msgSize); - if (!readData(msg.ba().data(), msgSize, msecs)) - return false; + msg.ba().resize(msgSize); + if (!readData(msg.ba().data(), msgSize, msecs)) return false; - return true; + return true; } //------------------------------------------------------------- @@ -187,17 +184,14 @@ bool tipc::Stream::readMessage(Message &msg, int msecs) message data has been received. */ bool tipc::Stream::readMessageNB(Message &msg, int msecs, - QEventLoop::ProcessEventsFlag flag) -{ - TINT32 msgSize = 0; - if (!readDataNB((char *)&msgSize, sizeof(TINT32), msecs, flag)) - return false; + QEventLoop::ProcessEventsFlag flag) { + TINT32 msgSize = 0; + if (!readDataNB((char *)&msgSize, sizeof(TINT32), msecs, flag)) return false; - msg.ba().resize(msgSize); - if (!readDataNB(msg.ba().data(), msgSize, msecs, flag)) - return false; + msg.ba().resize(msgSize); + if (!readDataNB(msg.ba().data(), msgSize, msecs, flag)) return false; - return true; + return true; } //------------------------------------------------------------- @@ -209,20 +203,21 @@ bool tipc::Stream::readMessageNB(Message &msg, int msecs, Returns true if the operation was successful, false if it timed out or an error occurred. */ -bool tipc::Stream::flush(int msecs) -{ - tipc_debug(qDebug("tipc:flush entry")); - - while (m_socket->bytesToWrite() > 0) { - tipc_debug(qDebug() << "bytes to write:" << m_socket->bytesToWrite()); - bool ok = m_socket->flush(); - tipc_debug(qDebug() << "flush success:" << ok << "bytes to write:" << m_socket->bytesToWrite()); - if (m_socket->bytesToWrite() > 0 && !m_socket->waitForBytesWritten(msecs)) - return false; - } - - tipc_debug(qDebug() << "tipc:flush exit - bytes to write:" << m_socket->bytesToWrite()); - return (m_socket->bytesToWrite() == 0); +bool tipc::Stream::flush(int msecs) { + tipc_debug(qDebug("tipc:flush entry")); + + while (m_socket->bytesToWrite() > 0) { + tipc_debug(qDebug() << "bytes to write:" << m_socket->bytesToWrite()); + bool ok = m_socket->flush(); + tipc_debug(qDebug() << "flush success:" << ok + << "bytes to write:" << m_socket->bytesToWrite()); + if (m_socket->bytesToWrite() > 0 && !m_socket->waitForBytesWritten(msecs)) + return false; + } + + tipc_debug(qDebug() << "tipc:flush exit - bytes to write:" + << m_socket->bytesToWrite()); + return (m_socket->bytesToWrite() == 0); } //******************************************************** @@ -231,27 +226,25 @@ bool tipc::Stream::flush(int msecs) //! \warning This operation assumes that all the message is available for read. //! Use tipc::stream::readMessage if this cannot be ensured. -tipc::Stream &operator>>(tipc::Stream &stream, tipc::Message &msg) -{ - QLocalSocket *socket = stream.socket(); - msg.clear(); - - TINT32 msgSize; - socket->read((char *)&msgSize, sizeof(TINT32)); - msg.ba().resize(msgSize); - socket->read(msg.ba().data(), msgSize); - return stream; +tipc::Stream &operator>>(tipc::Stream &stream, tipc::Message &msg) { + QLocalSocket *socket = stream.socket(); + msg.clear(); + + TINT32 msgSize; + socket->read((char *)&msgSize, sizeof(TINT32)); + msg.ba().resize(msgSize); + socket->read(msg.ba().data(), msgSize); + return stream; } -tipc::Stream &operator<<(tipc::Stream &stream, tipc::Message &msg) -{ - QLocalSocket *socket = stream.socket(); +tipc::Stream &operator<<(tipc::Stream &stream, tipc::Message &msg) { + QLocalSocket *socket = stream.socket(); - TINT32 size = msg.ba().size(); - socket->write((char *)&size, sizeof(TINT32)); - socket->write(msg.ba().data(), size); + TINT32 size = msg.ba().size(); + socket->write((char *)&size, sizeof(TINT32)); + socket->write(msg.ba().data(), size); - return stream; + return stream; } //******************************************************** @@ -261,29 +254,29 @@ tipc::Stream &operator<<(tipc::Stream &stream, tipc::Message &msg) /*! Appends the invoking process' pid to the passed srvName. */ -QString tipc::applicationSpecificServerName(QString srvName) -{ - return srvName + QString::number(QCoreApplication::applicationPid()); +QString tipc::applicationSpecificServerName(QString srvName) { + return srvName + QString::number(QCoreApplication::applicationPid()); } //------------------------------------------------------------- -bool tipc::startBackgroundProcess(QString cmdline) -{ +bool tipc::startBackgroundProcess(QString cmdline) { #ifdef _WIN32 - QProcess *proc = new QProcess; - proc->start(cmdline); - if (proc->state() == QProcess::NotRunning) { - delete proc; - return false; - } - - QObject::connect(proc, SIGNAL(finished(int, QProcess::ExitStatus)), proc, SLOT(deleteLater())); - QObject::connect(proc, SIGNAL(error(QProcess::ProcessError)), proc, SLOT(deleteLater())); - return true; + QProcess *proc = new QProcess; + proc->start(cmdline); + if (proc->state() == QProcess::NotRunning) { + delete proc; + return false; + } + + QObject::connect(proc, SIGNAL(finished(int, QProcess::ExitStatus)), proc, + SLOT(deleteLater())); + QObject::connect(proc, SIGNAL(error(QProcess::ProcessError)), proc, + SLOT(deleteLater())); + return true; #else - return QProcess::startDetached(cmdline); - ; + return QProcess::startDetached(cmdline); + ; #endif } @@ -302,54 +295,59 @@ bool tipc::startBackgroundProcess(QString cmdline) \warning Please, observe that a correct slave server name should be ensured to be unique to the system. */ -bool tipc::startSlaveServer(QString srvName, QString cmdline) -{ - if (!tipc::startBackgroundProcess(cmdline)) - return false; +bool tipc::startSlaveServer(QString srvName, QString cmdline) { + if (!tipc::startBackgroundProcess(cmdline)) return false; - QString mainSrvName(srvName + "_main"); + QString mainSrvName(srvName + "_main"); - //Establish a dummy socket connection to provide a mean for the process - //to tell whether the calling process exited unexpectedly. - QLocalSocket *dummySock = new QLocalSocket; - dummySock->connectToServer(mainSrvName); + // Establish a dummy socket connection to provide a mean for the process + // to tell whether the calling process exited unexpectedly. + QLocalSocket *dummySock = new QLocalSocket; + dummySock->connectToServer(mainSrvName); - //Wait up to msecs until the socket is connecting. Wait a small amount of time - //until the server is up and listening to connection (there is no other way to tell). - while (dummySock->state() == QLocalSocket::UnconnectedState) { + // Wait up to msecs until the socket is connecting. Wait a small amount of + // time + // until the server is up and listening to connection (there is no other way + // to tell). + while (dummySock->state() == QLocalSocket::UnconnectedState) { #ifdef _WIN32 - Sleep(10); + Sleep(10); #else - usleep(10 << 10); //10.24 msecs + usleep(10 << 10); // 10.24 msecs #endif - dummySock->connectToServer(mainSrvName); - } - - dummySock->waitForConnected(-1); - - tipc::Stream stream(dummySock); - tipc::Message msg; - - //Supply the 'quit if this socket connection fails' command - //This command ensure termination of the child process in case of some errors - //or ending of the program - stream << (msg << QString("$quit_on_error")); - if (tipc::readMessage(stream, msg, 3000) == QString()) { - std::cout << "tipc::startSlaveServer - tipc::readMessage TIMEOUT" << std::endl; - return false; - } - - //The server should die if dummyDock is destroyed. This should happen when the *MAIN* thread - //in *this process* exits. So, if this is not the main thread, we must move the socket there. - if (QThread::currentThread() != QCoreApplication::instance()->thread()) - dummySock->moveToThread(QCoreApplication::instance()->thread()); - - //If a connection error takes place, release the dummy socket. - //Please, observe that this QObject::connect is invoked *AFTER* the connection trials above... - QObject::connect(dummySock, SIGNAL(error(QLocalSocket::LocalSocketError)), dummySock, SLOT(deleteLater())); - - return true; + dummySock->connectToServer(mainSrvName); + } + + dummySock->waitForConnected(-1); + + tipc::Stream stream(dummySock); + tipc::Message msg; + + // Supply the 'quit if this socket connection fails' command + // This command ensure termination of the child process in case of some errors + // or ending of the program + stream << (msg << QString("$quit_on_error")); + if (tipc::readMessage(stream, msg, 3000) == QString()) { + std::cout << "tipc::startSlaveServer - tipc::readMessage TIMEOUT" + << std::endl; + return false; + } + + // The server should die if dummyDock is destroyed. This should happen when + // the *MAIN* thread + // in *this process* exits. So, if this is not the main thread, we must move + // the socket there. + if (QThread::currentThread() != QCoreApplication::instance()->thread()) + dummySock->moveToThread(QCoreApplication::instance()->thread()); + + // If a connection error takes place, release the dummy socket. + // Please, observe that this QObject::connect is invoked *AFTER* the + // connection trials above... + QObject::connect(dummySock, SIGNAL(error(QLocalSocket::LocalSocketError)), + dummySock, SLOT(deleteLater())); + + return true; } //------------------------------------------------------------- @@ -364,48 +362,45 @@ bool tipc::startSlaveServer(QString srvName, QString cmdline) \warning Please, observe that a correct slave server name should be ensured to be unique to the parent process. */ -bool tipc::startSlaveConnection(QLocalSocket *socket, QString srvName, int msecs, - QString cmdline, QString threadName) -{ - QTime time; - time.start(); - - if (msecs == -1) - msecs = (std::numeric_limits::max)(); - - QString fullSrvName(srvName + threadName); - socket->connectToServer(fullSrvName); - - //If the socket is not connecting, the server lookup table returned that the no server with - //the passed name exists. This means that a server must be created. - if (socket->state() == QLocalSocket::UnconnectedState && !cmdline.isEmpty()) { - //Completely serialize the server start - static QMutex mutex; - QMutexLocker locker(&mutex); - - //Retry connection - this is required due to the mutex - socket->connectToServer(fullSrvName); - if (socket->state() != QLocalSocket::UnconnectedState) - goto connecting; - - //Invoke the supplied command line to start the server - if (!tipc::startSlaveServer(srvName, cmdline)) - return false; - - //Reconnect to the server - socket->connectToServer(fullSrvName); - if (socket->state() == QLocalSocket::UnconnectedState) - return false; - } +bool tipc::startSlaveConnection(QLocalSocket *socket, QString srvName, + int msecs, QString cmdline, + QString threadName) { + QTime time; + time.start(); + + if (msecs == -1) msecs = (std::numeric_limits::max)(); + + QString fullSrvName(srvName + threadName); + socket->connectToServer(fullSrvName); + + // If the socket is not connecting, the server lookup table returned that the + // no server with + // the passed name exists. This means that a server must be created. + if (socket->state() == QLocalSocket::UnconnectedState && !cmdline.isEmpty()) { + // Completely serialize the server start + static QMutex mutex; + QMutexLocker locker(&mutex); + + // Retry connection - this is required due to the mutex + socket->connectToServer(fullSrvName); + if (socket->state() != QLocalSocket::UnconnectedState) goto connecting; + + // Invoke the supplied command line to start the server + if (!tipc::startSlaveServer(srvName, cmdline)) return false; + + // Reconnect to the server + socket->connectToServer(fullSrvName); + if (socket->state() == QLocalSocket::UnconnectedState) return false; + } connecting: - //Now, the server is connecting or already connected. Wait until the socket is connected. - socket->waitForConnected(msecs - time.elapsed()); - if (socket->state() != QLocalSocket::ConnectedState) - return false; + // Now, the server is connecting or already connected. Wait until the socket + // is connected. + socket->waitForConnected(msecs - time.elapsed()); + if (socket->state() != QLocalSocket::ConnectedState) return false; - return true; + return true; } //------------------------------------------------------------- @@ -423,16 +418,14 @@ connecting: This function returns an empty QString if the message could not be entirely retrieved from the stream. */ -QString tipc::readMessage(Stream &stream, Message &msg, int msecs) -{ - msg.clear(); - stream.flush(); - if (!stream.readMessage(msg, msecs)) - return QString(); - - QString res; - msg >> res; - return res; +QString tipc::readMessage(Stream &stream, Message &msg, int msecs) { + msg.clear(); + stream.flush(); + if (!stream.readMessage(msg, msecs)) return QString(); + + QString res; + msg >> res; + return res; } //------------------------------------------------------------- @@ -441,15 +434,13 @@ QString tipc::readMessage(Stream &stream, Message &msg, int msecs) The non-blocking equivalent to tipc::readMessage. */ QString tipc::readMessageNB(Stream &stream, Message &msg, int msecs, - QEventLoop::ProcessEventsFlag flag) -{ - msg.clear(); - if (!stream.readMessageNB(msg, msecs, flag)) - return QString(); - - QString res; - msg >> res; - return res; + QEventLoop::ProcessEventsFlag flag) { + msg.clear(); + if (!stream.readMessageNB(msg, msecs, flag)) return QString(); + + QString res; + msg >> res; + return res; } //------------------------------------------------------------- @@ -458,89 +449,86 @@ QString tipc::readMessageNB(Stream &stream, Message &msg, int msecs, Returns an inter-process unique id string; the returned id should be used to create QSharedMemory objects. */ -QString tipc::uniqueId() -{ - static QAtomicInt count; - count.ref(); - return QString::number(QCoreApplication::applicationPid()) + "_" + QString::number((int)count); +QString tipc::uniqueId() { + static QAtomicInt count; + count.ref(); + return QString::number(QCoreApplication::applicationPid()) + "_" + + QString::number((int)count); } //------------------------------------------------------------- //! Returns the maximum size of a shared memory segment allowed by the system -int tipc::shm_maxSegmentSize() -{ - if (shm_max < 0) { +int tipc::shm_maxSegmentSize() { + if (shm_max < 0) { #ifdef MACOSX - //Retrieve it by invoking sysctl - size_t valSize = sizeof(TINT64); - TINT64 val; - sysctlbyname("kern.sysv.shmmax", &val, &valSize, NULL, 0); - shm_max = std::min(val, (TINT64)(std::numeric_limits::max)()); + // Retrieve it by invoking sysctl + size_t valSize = sizeof(TINT64); + TINT64 val; + sysctlbyname("kern.sysv.shmmax", &val, &valSize, NULL, 0); + shm_max = std::min(val, (TINT64)(std::numeric_limits::max)()); #else - //Windows case: no such limit - //Observe that QSharedMemory accepts only an int size - so the num_lim is against int. - shm_max = (std::numeric_limits::max)(); + // Windows case: no such limit + // Observe that QSharedMemory accepts only an int size - so the num_lim is + // against int. + shm_max = (std::numeric_limits::max)(); #endif - } + } - return shm_max; + return shm_max; } //------------------------------------------------------------- //! Returns the maximum number of shared segments allowed by the system -int tipc::shm_maxSegmentCount() -{ - if (shm_seg < 0) { +int tipc::shm_maxSegmentCount() { + if (shm_seg < 0) { #ifdef MACOSX - size_t valSize = sizeof(TINT64); - TINT64 val; - sysctlbyname("kern.sysv.shmseg", &val, &valSize, NULL, 0); - shm_seg = std::min(val, (TINT64)(std::numeric_limits::max)()); + size_t valSize = sizeof(TINT64); + TINT64 val; + sysctlbyname("kern.sysv.shmseg", &val, &valSize, NULL, 0); + shm_seg = std::min(val, (TINT64)(std::numeric_limits::max)()); #else - //Windows case: no such limit - again, using limit against max due to Qt - shm_seg = (std::numeric_limits::max)(); + // Windows case: no such limit - again, using limit against max due to Qt + shm_seg = (std::numeric_limits::max)(); #endif - } + } - return shm_seg; + return shm_seg; } //------------------------------------------------------------- -int tipc::shm_maxSharedPages() -{ - if (shm_all < 0) { +int tipc::shm_maxSharedPages() { + if (shm_all < 0) { #ifdef MACOSX - size_t valSize = sizeof(TINT64); - TINT64 val; - sysctlbyname("kern.sysv.shmall", &val, &valSize, NULL, 0); - shm_all = std::min(val, (TINT64)(std::numeric_limits::max)()); + size_t valSize = sizeof(TINT64); + TINT64 val; + sysctlbyname("kern.sysv.shmall", &val, &valSize, NULL, 0); + shm_all = std::min(val, (TINT64)(std::numeric_limits::max)()); #else - shm_all = (std::numeric_limits::max)(); + shm_all = (std::numeric_limits::max)(); #endif - } + } - return shm_all; + return shm_all; } //------------------------------------------------------------- -int tipc::shm_maxSharedCount() -{ - if (shm_mni < 0) { +int tipc::shm_maxSharedCount() { + if (shm_mni < 0) { #ifdef MACOSX - size_t valSize = sizeof(TINT64); - TINT64 val; - sysctlbyname("kern.sysv.shmmni", &val, &valSize, NULL, 0); - shm_mni = std::min(val, (TINT64)(std::numeric_limits::max)()); + size_t valSize = sizeof(TINT64); + TINT64 val; + sysctlbyname("kern.sysv.shmmni", &val, &valSize, NULL, 0); + shm_mni = std::min(val, (TINT64)(std::numeric_limits::max)()); #else - shm_mni = (std::numeric_limits::max)(); + shm_mni = (std::numeric_limits::max)(); #endif - } + } - return shm_mni; + return shm_mni; } //------------------------------------------------------------- @@ -551,36 +539,32 @@ int tipc::shm_maxSharedCount() This function will fail anyway if the process is not owned by an admin. */ -void tipc::shm_set(int shmmax, int shmseg, int shmall, int shmmni) -{ - tipc_debug(qDebug("shmmax: %i, shmseg: %i, shmall: %i, shmmni: %i", shmmax, shmseg, shmall, shmmni)); +void tipc::shm_set(int shmmax, int shmseg, int shmall, int shmmni) { + tipc_debug(qDebug("shmmax: %i, shmseg: %i, shmall: %i, shmmni: %i", shmmax, + shmseg, shmall, shmmni)); #ifdef MACOSX - TINT64 val; - int err; - if (shmmax > 0) { - val = shmmax; - err = sysctlbyname("kern.sysv.shmmax", NULL, NULL, &val, sizeof(TINT64)); - if (!err) - shm_max = shmmax; - } - if (shmseg > 0) { - val = shmseg; - err = sysctlbyname("kern.sysv.shmseg", NULL, NULL, &val, sizeof(TINT64)); - if (!err) - shm_seg = shmseg; - } - if (shmall > 0) { - val = shmall; - err = sysctlbyname("kern.sysv.shmall", NULL, NULL, &val, sizeof(TINT64)); - if (!err) - shm_all = shmall; - } - if (shmmni > 0) { - val = shmmni; - err = sysctlbyname("kern.sysv.shmmni", NULL, NULL, &val, sizeof(TINT64)); - if (!err) - shm_mni = shmmni; - } + TINT64 val; + int err; + if (shmmax > 0) { + val = shmmax; + err = sysctlbyname("kern.sysv.shmmax", NULL, NULL, &val, sizeof(TINT64)); + if (!err) shm_max = shmmax; + } + if (shmseg > 0) { + val = shmseg; + err = sysctlbyname("kern.sysv.shmseg", NULL, NULL, &val, sizeof(TINT64)); + if (!err) shm_seg = shmseg; + } + if (shmall > 0) { + val = shmall; + err = sysctlbyname("kern.sysv.shmall", NULL, NULL, &val, sizeof(TINT64)); + if (!err) shm_all = shmall; + } + if (shmmni > 0) { + val = shmmni; + err = sysctlbyname("kern.sysv.shmmni", NULL, NULL, &val, sizeof(TINT64)); + if (!err) shm_mni = shmmni; + } #endif } @@ -600,37 +584,38 @@ void tipc::shm_set(int shmmax, int shmseg, int shmall, int shmmni)
  • Unlike QSharedMemory::create, this function attempts to reclaim an already existing memory id before creating a new one. <\LI> */ -int tipc::create(QSharedMemory &shmem, int size, bool strictSize) -{ - bool ok, retried = false; +int tipc::create(QSharedMemory &shmem, int size, bool strictSize) { + bool ok, retried = false; - if (!strictSize) - size = std::min(size, (int)shm_maxSegmentSize()); + if (!strictSize) size = std::min(size, (int)shm_maxSegmentSize()); - tipc_debug(qDebug() << "shMem create: size =" << size); + tipc_debug(qDebug() << "shMem create: size =" << size); retry: - ok = shmem.create(size); - if (!ok) { - tipc_debug(qDebug() << "Error: Shared Segment could not be created: #" << shmem.errorString()); - - //Unix-specific error recovery follows. See Qt's docs about it. - - //Try to recover error #AlreadyExists - supposedly, the server crashed in a previous instance. - //As shared memory segments that happen to go this way are owned by the server process with 1 - //reference count, detaching it now may solve the issue. - if (shmem.error() == QSharedMemory::AlreadyExists && !retried) { - retried = true; // We're trying this only once... for now it works. - shmem.attach(); - shmem.detach(); - goto retry; - } - - return -1; - } - - return size; + ok = shmem.create(size); + if (!ok) { + tipc_debug(qDebug() << "Error: Shared Segment could not be created: #" + << shmem.errorString()); + + // Unix-specific error recovery follows. See Qt's docs about it. + + // Try to recover error #AlreadyExists - supposedly, the server crashed in a + // previous instance. + // As shared memory segments that happen to go this way are owned by the + // server process with 1 + // reference count, detaching it now may solve the issue. + if (shmem.error() == QSharedMemory::AlreadyExists && !retried) { + retried = true; // We're trying this only once... for now it works. + shmem.attach(); + shmem.detach(); + goto retry; + } + + return -1; + } + + return size; } //------------------------------------------------------------- @@ -638,55 +623,54 @@ retry: /*! Writes data through a shared memory segment medium. */ -bool tipc::writeShMemBuffer(Stream &stream, Message &msg, int bufSize, ShMemWriter *dataWriter) -{ - tipc_debug(QTime time; time.start()); - tipc_debug(qDebug("tipc::writeShMemBuffer entry")); - - static QSemaphore sem(tipc::shm_maxSegmentCount()); - sem.acquire(1); - - { - //Create a shared memory segment, possibly of passed size - QSharedMemory shmem(tipc::uniqueId()); - bool ok = (tipc::create(shmem, bufSize) > 0); - if (!ok) - goto err; - - //Communicate the shared memory id and bufSize to the reader - msg << QString("shm") << shmem.key() << bufSize; - - //Fill in data until all the buffer has been sent - int chunkData, remainingData = bufSize; - while (remainingData > 0) { - //Write to the shared memory segment - tipc_debug(QTime xchTime; xchTime.start()); - shmem.lock(); - remainingData -= chunkData = dataWriter->write((char *)shmem.data(), std::min(shmem.size(), remainingData)); - shmem.unlock(); - tipc_debug(qDebug() << "exchange time:" << xchTime.elapsed()); - - stream << (msg << QString("chk") << chunkData); - - if (tipc::readMessage(stream, msg) != "ok") - goto err; - - msg.clear(); - } - } - - sem.release(1); - tipc_debug(qDebug("tipc::writeShMemBuffer exit")); - tipc_debug(qDebug() << "tipc::writeShMemBuffer time:" << time.elapsed()); - return true; +bool tipc::writeShMemBuffer(Stream &stream, Message &msg, int bufSize, + ShMemWriter *dataWriter) { + tipc_debug(QTime time; time.start()); + tipc_debug(qDebug("tipc::writeShMemBuffer entry")); + + static QSemaphore sem(tipc::shm_maxSegmentCount()); + sem.acquire(1); + + { + // Create a shared memory segment, possibly of passed size + QSharedMemory shmem(tipc::uniqueId()); + bool ok = (tipc::create(shmem, bufSize) > 0); + if (!ok) goto err; + + // Communicate the shared memory id and bufSize to the reader + msg << QString("shm") << shmem.key() << bufSize; + + // Fill in data until all the buffer has been sent + int chunkData, remainingData = bufSize; + while (remainingData > 0) { + // Write to the shared memory segment + tipc_debug(QTime xchTime; xchTime.start()); + shmem.lock(); + remainingData -= chunkData = dataWriter->write( + (char *)shmem.data(), std::min(shmem.size(), remainingData)); + shmem.unlock(); + tipc_debug(qDebug() << "exchange time:" << xchTime.elapsed()); + + stream << (msg << QString("chk") << chunkData); + + if (tipc::readMessage(stream, msg) != "ok") goto err; + + msg.clear(); + } + } + + sem.release(1); + tipc_debug(qDebug("tipc::writeShMemBuffer exit")); + tipc_debug(qDebug() << "tipc::writeShMemBuffer time:" << time.elapsed()); + return true; err: - tipc_debug(qDebug("tipc::writeShMemBuffer exit (error)")); + tipc_debug(qDebug("tipc::writeShMemBuffer exit (error)")); - msg.clear(); - sem.release(1); - return false; + msg.clear(); + sem.release(1); + return false; } //------------------------------------------------------------- @@ -694,58 +678,58 @@ err: /*! Reads data through a shared memory segment medium. */ -bool tipc::readShMemBuffer(Stream &stream, Message &msg, ShMemReader *dataReader) -{ - tipc_debug(QTime time; time.start();); - tipc_debug(qDebug("tipc::readShMemBuffer entry")); - - //Read the id from stream - QString res(tipc::readMessage(stream, msg)); - if (res != "shm") { - tipc_debug(qDebug("tipc::readShMemBuffer exit (res != \"shm\")")); - return false; - } - - //Read message and reply - QString id, chkStr; - int bufSize; - msg >> id >> bufSize >> chkStr; - - //Data is ready to be read - attach to the shared memory segment. - QSharedMemory shmem(id); - shmem.attach(); - if (!shmem.isAttached()) { - tipc_debug(qDebug("tipc::readShMemBuffer exit (shmem not attached)")); - return false; - } - - //Start reading from it - int chunkData, remainingData = bufSize; - while (true) { - msg >> chunkData; - - tipc_debug(QTime xchTime; xchTime.start()); - shmem.lock(); - remainingData -= dataReader->read((const char *)shmem.data(), chunkData); - shmem.unlock(); - tipc_debug(qDebug() << "exchange time:" << xchTime.elapsed()); - - //Data was read. Inform the writer - stream << (msg << clr << QString("ok")); - stream.flush(); - - if (remainingData <= 0) - break; - - //Wait for more chunks - if (tipc::readMessage(stream, msg) != "chk") { - tipc_debug(qDebug("tipc::readShMemBuffer exit (unexpected chunk absence)")); - return false; - } - } - - shmem.detach(); - tipc_debug(qDebug("tipc::readShMemBuffer exit")); - tipc_debug(qDebug() << "tipc::readShMemBuffer time:" << time.elapsed()); - return true; +bool tipc::readShMemBuffer(Stream &stream, Message &msg, + ShMemReader *dataReader) { + tipc_debug(QTime time; time.start();); + tipc_debug(qDebug("tipc::readShMemBuffer entry")); + + // Read the id from stream + QString res(tipc::readMessage(stream, msg)); + if (res != "shm") { + tipc_debug(qDebug("tipc::readShMemBuffer exit (res != \"shm\")")); + return false; + } + + // Read message and reply + QString id, chkStr; + int bufSize; + msg >> id >> bufSize >> chkStr; + + // Data is ready to be read - attach to the shared memory segment. + QSharedMemory shmem(id); + shmem.attach(); + if (!shmem.isAttached()) { + tipc_debug(qDebug("tipc::readShMemBuffer exit (shmem not attached)")); + return false; + } + + // Start reading from it + int chunkData, remainingData = bufSize; + while (true) { + msg >> chunkData; + + tipc_debug(QTime xchTime; xchTime.start()); + shmem.lock(); + remainingData -= dataReader->read((const char *)shmem.data(), chunkData); + shmem.unlock(); + tipc_debug(qDebug() << "exchange time:" << xchTime.elapsed()); + + // Data was read. Inform the writer + stream << (msg << clr << QString("ok")); + stream.flush(); + + if (remainingData <= 0) break; + + // Wait for more chunks + if (tipc::readMessage(stream, msg) != "chk") { + tipc_debug( + qDebug("tipc::readShMemBuffer exit (unexpected chunk absence)")); + return false; + } + } + + shmem.detach(); + tipc_debug(qDebug("tipc::readShMemBuffer exit")); + tipc_debug(qDebug() << "tipc::readShMemBuffer time:" << time.elapsed()); + return true; } diff --git a/toonz/sources/common/tipc/tipcmsg.cpp b/toonz/sources/common/tipc/tipcmsg.cpp index b1e7bcb..e579171 100644 --- a/toonz/sources/common/tipc/tipcmsg.cpp +++ b/toonz/sources/common/tipc/tipcmsg.cpp @@ -1,10 +1,10 @@ -//Toonz includes +// Toonz includes #include "traster.h" #include "timage_io.h" -//Qt includes +// Qt includes #include #include #include @@ -12,7 +12,7 @@ #include #include -//tipc includes +// tipc includes #include "tipc.h" #include "tipcmsg.h" @@ -21,44 +21,43 @@ // Local stuff -namespace -{ +namespace { QHash sharedMemories; QHash temporaryFiles; } //--------------------------------------------------------------------- -namespace tipc -{ +namespace tipc { //******************************************************************************* // Shared Memory Request //******************************************************************************* template <> -QString DefaultMessageParser::header() const { return QString("$shmem_request"); } +QString DefaultMessageParser::header() const { + return QString("$shmem_request"); +} //------------------------------------------------------------------ template <> -void DefaultMessageParser::operator()(Message &msg) -{ - int size; - QString id; - msg >> id >> size >> clr; - - QSharedMemory *mem = new QSharedMemory(id); - - bool ok = (tipc::create(*mem, size) > 0); - if (!ok) { - msg << QString("err"); - delete mem; - return; - } - - sharedMemories.insert(id, mem); - msg << QString("ok"); +void DefaultMessageParser::operator()(Message &msg) { + int size; + QString id; + msg >> id >> size >> clr; + + QSharedMemory *mem = new QSharedMemory(id); + + bool ok = (tipc::create(*mem, size) > 0); + if (!ok) { + msg << QString("err"); + delete mem; + return; + } + + sharedMemories.insert(id, mem); + msg << QString("ok"); } //******************************************************************************* @@ -66,19 +65,19 @@ void DefaultMessageParser::operator()(Message &msg) //******************************************************************************* template <> -QString DefaultMessageParser::header() const { return QString("$shmem_release"); } +QString DefaultMessageParser::header() const { + return QString("$shmem_release"); +} //------------------------------------------------------------------ template <> -void DefaultMessageParser::operator()(Message &msg) -{ - QString id; - msg >> id >> clr; - QSharedMemory *mem = sharedMemories.take(id); - if (mem) - delete mem; - msg << QString("ok"); +void DefaultMessageParser::operator()(Message &msg) { + QString id; + msg >> id >> clr; + QSharedMemory *mem = sharedMemories.take(id); + if (mem) delete mem; + msg << QString("ok"); } //******************************************************************************* @@ -86,30 +85,31 @@ void DefaultMessageParser::operator()(Message &msg) //******************************************************************************* template <> -QString DefaultMessageParser::header() const { return QString("$tmpfile_request"); } +QString DefaultMessageParser::header() const { + return QString("$tmpfile_request"); +} //------------------------------------------------------------------ template <> -void DefaultMessageParser::operator()(Message &msg) -{ - QString id; - msg >> id >> clr; - - //Build a temporary file with passed id group. - //The created QTemporaryFile CANNOT be stored directly, as it internally - //keeps the file open until the object is destroyed. Instead, we store its - //filePath and manually remove it upon release. - - QTemporaryFile tmp(QDir::temp().filePath(id)); - tmp.setAutoRemove(false); - if (!tmp.open()) { - msg << QString("err"); - return; - } - - temporaryFiles.insert(id, tmp.fileName()); - msg << QString("ok") << tmp.fileName(); +void DefaultMessageParser::operator()(Message &msg) { + QString id; + msg >> id >> clr; + + // Build a temporary file with passed id group. + // The created QTemporaryFile CANNOT be stored directly, as it internally + // keeps the file open until the object is destroyed. Instead, we store its + // filePath and manually remove it upon release. + + QTemporaryFile tmp(QDir::temp().filePath(id)); + tmp.setAutoRemove(false); + if (!tmp.open()) { + msg << QString("err"); + return; + } + + temporaryFiles.insert(id, tmp.fileName()); + msg << QString("ok") << tmp.fileName(); } //******************************************************************************* @@ -117,23 +117,24 @@ void DefaultMessageParser::operator()(Message &msg) //******************************************************************************* template <> -QString DefaultMessageParser::header() const { return QString("$tmpfile_release"); } +QString DefaultMessageParser::header() const { + return QString("$tmpfile_release"); +} //------------------------------------------------------------------ template <> -void DefaultMessageParser::operator()(Message &msg) -{ - QString id; - msg >> id >> clr; - - QString tmpPath = temporaryFiles.take(id); - if (!tmpPath.isEmpty()) { - QFile file(tmpPath); - file.remove(); - } - - msg << QString("ok"); +void DefaultMessageParser::operator()(Message &msg) { + QString id; + msg >> id >> clr; + + QString tmpPath = temporaryFiles.take(id); + if (!tmpPath.isEmpty()) { + QFile file(tmpPath); + file.remove(); + } + + msg << QString("ok"); } //******************************************************************************* @@ -141,18 +142,22 @@ void DefaultMessageParser::operator()(Message &msg) //******************************************************************************* template <> -QString DefaultMessageParser::header() const { return QString("$quit_on_error"); } +QString DefaultMessageParser::header() const { + return QString("$quit_on_error"); +} //------------------------------------------------------------------ template <> -void DefaultMessageParser::operator()(Message &msg) -{ - QObject::connect(socket(), SIGNAL(error(QLocalSocket::LocalSocketError)), QCoreApplication::instance(), SLOT(quit())); - //In Qt 5.5 originating process's termination emits 'disconnected' instead of 'error' - QObject::connect(socket(), SIGNAL(disconnected()), QCoreApplication::instance(), SLOT(quit())); - - msg << clr << QString("ok"); +void DefaultMessageParser::operator()(Message &msg) { + QObject::connect(socket(), SIGNAL(error(QLocalSocket::LocalSocketError)), + QCoreApplication::instance(), SLOT(quit())); + // In Qt 5.5 originating process's termination emits 'disconnected' instead of + // 'error' + QObject::connect(socket(), SIGNAL(disconnected()), + QCoreApplication::instance(), SLOT(quit())); + + msg << clr << QString("ok"); } //******************************************************************************* @@ -167,4 +172,4 @@ template class DefaultMessageParser; template class DefaultMessageParser; template class DefaultMessageParser; -} //namespace tipc +} // namespace tipc diff --git a/toonz/sources/common/tipc/tipcsrv.cpp b/toonz/sources/common/tipc/tipcsrv.cpp index 4c0b52e..b4dbde9 100644 --- a/toonz/sources/common/tipc/tipcsrv.cpp +++ b/toonz/sources/common/tipc/tipcsrv.cpp @@ -2,7 +2,7 @@ #include "assert.h" -//Qt includes +// Qt includes #include #include @@ -32,136 +32,121 @@ // tipc::SocketListener implementation //******************************************************************************* -void tipc::SocketController::onReadyRead() -{ - //Deliver the message to the server for interpretation. - m_server->dispatchSocket(m_socket); +void tipc::SocketController::onReadyRead() { + // Deliver the message to the server for interpretation. + m_server->dispatchSocket(m_socket); } //----------------------------------------------------------------------- -void tipc::SocketController::onDisconnected() -{ - m_socket->QObject::disconnect(SIGNAL(readyRead())); +void tipc::SocketController::onDisconnected() { + m_socket->QObject::disconnect(SIGNAL(readyRead())); - //Auto-delete this - delete this; + // Auto-delete this + delete this; } //******************************************************************************* // Server implementation //******************************************************************************* -tipc::Server::Server() - : m_lock(false) -{ - connect(this, SIGNAL(newConnection()), this, SLOT(onNewConnection())); - - //Add default parsers - addParser(new DefaultMessageParser); - addParser(new DefaultMessageParser); - addParser(new DefaultMessageParser); - addParser(new DefaultMessageParser); - addParser(new DefaultMessageParser); +tipc::Server::Server() : m_lock(false) { + connect(this, SIGNAL(newConnection()), this, SLOT(onNewConnection())); + + // Add default parsers + addParser(new DefaultMessageParser); + addParser(new DefaultMessageParser); + addParser(new DefaultMessageParser); + addParser(new DefaultMessageParser); + addParser(new DefaultMessageParser); } //----------------------------------------------------------------------- -tipc::Server::~Server() -{ - //Release parsers - QHash::iterator it; - for (it = m_parsers.begin(); it != m_parsers.end(); ++it) - delete it.value(); +tipc::Server::~Server() { + // Release parsers + QHash::iterator it; + for (it = m_parsers.begin(); it != m_parsers.end(); ++it) delete it.value(); } //----------------------------------------------------------------------- -void tipc::Server::addParser(MessageParser *parser) -{ - m_parsers.insert(parser->header(), parser); +void tipc::Server::addParser(MessageParser *parser) { + m_parsers.insert(parser->header(), parser); } //----------------------------------------------------------------------- -void tipc::Server::removeParser(QString header) -{ - MessageParser *parser = m_parsers.take(header); - if (parser) - delete parser; +void tipc::Server::removeParser(QString header) { + MessageParser *parser = m_parsers.take(header); + if (parser) delete parser; } //----------------------------------------------------------------------- -void tipc::Server::onNewConnection() -{ - tipc_debug(qDebug("new connection")); +void tipc::Server::onNewConnection() { + tipc_debug(qDebug("new connection")); - //Accept the connection - QLocalSocket *socket = nextPendingConnection(); + // Accept the connection + QLocalSocket *socket = nextPendingConnection(); - //Allocate a controller for the socket - SocketController *controller = new SocketController; - controller->m_server = this; - controller->m_socket = socket; + // Allocate a controller for the socket + SocketController *controller = new SocketController; + controller->m_server = this; + controller->m_socket = socket; - //Connect the controller to the socket's signals - connect(socket, SIGNAL(readyRead()), controller, SLOT(onReadyRead())); - connect(socket, SIGNAL(disconnected()), controller, SLOT(onDisconnected())); - connect(socket, SIGNAL(disconnected()), socket, SLOT(deleteLater())); - connect(socket, SIGNAL(error(QLocalSocket::LocalSocketError)), - this, SLOT(onError(QLocalSocket::LocalSocketError))); + // Connect the controller to the socket's signals + connect(socket, SIGNAL(readyRead()), controller, SLOT(onReadyRead())); + connect(socket, SIGNAL(disconnected()), controller, SLOT(onDisconnected())); + connect(socket, SIGNAL(disconnected()), socket, SLOT(deleteLater())); + connect(socket, SIGNAL(error(QLocalSocket::LocalSocketError)), this, + SLOT(onError(QLocalSocket::LocalSocketError))); } //----------------------------------------------------------------------- -void tipc::Server::onError(QLocalSocket::LocalSocketError error) -{ - tipc_debug(qDebug() << "Server error #" << error << ": " << errorString()); +void tipc::Server::onError(QLocalSocket::LocalSocketError error) { + tipc_debug(qDebug() << "Server error #" << error << ": " << errorString()); } //----------------------------------------------------------------------- -void tipc::Server::dispatchSocket(QLocalSocket *socket) -{ - //The lock is established when a message is currently being processed. - //Returning if the lock is set avoids having recursive message processing; - //which is possible if a parser expects further message packets. - if (m_lock) - return; +void tipc::Server::dispatchSocket(QLocalSocket *socket) { + // The lock is established when a message is currently being processed. + // Returning if the lock is set avoids having recursive message processing; + // which is possible if a parser expects further message packets. + if (m_lock) return; - tipc::Stream stream(socket); - QString header; + tipc::Stream stream(socket); + QString header; - while (socket->bytesAvailable() > 0) { - if (!stream.messageReady()) - return; + while (socket->bytesAvailable() > 0) { + if (!stream.messageReady()) return; - Message msg; + Message msg; - stream >> msg; - msg >> header; - assert(!header.isEmpty()); + stream >> msg; + msg >> header; + assert(!header.isEmpty()); - tipc_debug(qDebug() << header << endl); + tipc_debug(qDebug() << header << endl); - QHash::iterator it = m_parsers.find(header); - if (it == m_parsers.end()) { - tipc_debug(qDebug() << "Error: Unrecognized command" << endl); - continue; - } + QHash::iterator it = m_parsers.find(header); + if (it == m_parsers.end()) { + tipc_debug(qDebug() << "Error: Unrecognized command" << endl); + continue; + } - m_lock = true; + m_lock = true; - MessageParser *parser = it.value(); - parser->m_socket = socket; - parser->m_stream = &stream; - parser->operator()(msg); + MessageParser *parser = it.value(); + parser->m_socket = socket; + parser->m_stream = &stream; + parser->operator()(msg); - m_lock = false; + m_lock = false; - //The Message has been read and processed. Send the reply. - if (msg.ba().size() > 0) - stream << msg; - } + // The Message has been read and processed. Send the reply. + if (msg.ba().size() > 0) stream << msg; + } } diff --git a/toonz/sources/common/tmeshimage/tmeshimage.cpp b/toonz/sources/common/tmeshimage/tmeshimage.cpp index fbc14b5..2efc173 100644 --- a/toonz/sources/common/tmeshimage/tmeshimage.cpp +++ b/toonz/sources/common/tmeshimage/tmeshimage.cpp @@ -16,8 +16,10 @@ //****************************************************************************** template class DV_EXPORT_API tcg::Vertex; -template class DV_EXPORT_API tcg::Mesh>; -template class DV_EXPORT_API tcg::TriMesh>; +template class DV_EXPORT_API + tcg::Mesh>; +template class DV_EXPORT_API + tcg::TriMesh>; typedef tcg::TriMesh> TriMesh_base; @@ -28,380 +30,368 @@ typedef tcg::TriMesh> TriMesh_base; DEFINE_CLASS_CODE(TTextureMesh, 120) PERSIST_IDENTIFIER(TTextureMesh, "mesh") -static TTextureMeshP cloneMesh_(const TTextureMeshP &other) -{ - return TTextureMeshP(new TTextureMesh(*other)); +static TTextureMeshP cloneMesh_(const TTextureMeshP &other) { + return TTextureMeshP(new TTextureMesh(*other)); } -void static_check() -{ - /* input iterator */ - static_assert(std::is_same::iterator>::iterator_category, std::random_access_iterator_tag>::value == true, "random"); - - static_assert(std::is_base_of::iterator>::iterator_category>::value == true, "input"); - - static_assert(std::is_base_of::iterator>::iterator_category>::value == true, "forward"); - - static_assert(std::is_constructible::iterator>::reference>::value == true, - "akan"); - - /* converted iterator */ - std::vector vec; - auto it = vec.end(); - auto c = tcg::make_cast_it(it, cloneMesh_); - - static_assert(std::is_same::iterator_category, std::random_access_iterator_tag>::value == true, "random"); - - static_assert(std::is_base_of::iterator_category>::value == true, "input"); - - static_assert(std::is_base_of::iterator_category>::value == true, "forward"); - - //TTextureMeshP p(std::iterator_traits< decltype(c) >::reference); - static_assert(std::is_constructible::reference>::value == true, - "akan"); +void static_check() { + /* input iterator */ + static_assert( + std::is_same::iterator>::iterator_category, + std::random_access_iterator_tag>::value == true, + "random"); + + static_assert( + std::is_base_of::iterator>::iterator_category>::value == + true, + "input"); + + static_assert( + std::is_base_of::iterator>::iterator_category>::value == + true, + "forward"); + + static_assert( + std::is_constructible::iterator>::reference>::value == + true, + "akan"); + + /* converted iterator */ + std::vector vec; + auto it = vec.end(); + auto c = tcg::make_cast_it(it, cloneMesh_); + + static_assert( + std::is_same::iterator_category, + std::random_access_iterator_tag>::value == true, + "random"); + + static_assert( + std::is_base_of< + std::input_iterator_tag, + std::iterator_traits::iterator_category>::value == true, + "input"); + + static_assert( + std::is_base_of< + std::forward_iterator_tag, + std::iterator_traits::iterator_category>::value == true, + "forward"); + + // TTextureMeshP p(std::iterator_traits< decltype(c) >::reference); + static_assert( + std::is_constructible< + TTextureMeshP, std::iterator_traits::reference>::value == + true, + "akan"); } //----------------------------------------------------------------------- -TTextureMesh::TTextureMesh() - : TSmartObject(m_classCode) -{ -} +TTextureMesh::TTextureMesh() : TSmartObject(m_classCode) {} //----------------------------------------------------------------------- TTextureMesh::TTextureMesh(const TTextureMesh &other) - : TriMesh_base(other), TSmartObject(m_classCode) -{ -} + : TriMesh_base(other), TSmartObject(m_classCode) {} //----------------------------------------------------------------------- -TTextureMesh &TTextureMesh::operator=(const TTextureMesh &other) -{ - TriMesh_base::operator=(other); - return *this; +TTextureMesh &TTextureMesh::operator=(const TTextureMesh &other) { + TriMesh_base::operator=(other); + return *this; } //----------------------------------------------------------------------- -bool TTextureMesh::faceContains(int f, const TPointD &p) const -{ - int v0, v1, v2; - this->faceVertices(f, v0, v1, v2); +bool TTextureMesh::faceContains(int f, const TPointD &p) const { + int v0, v1, v2; + this->faceVertices(f, v0, v1, v2); - const TPointD &p0 = vertex(v0).P(); - const TPointD &p1 = vertex(v1).P(); - const TPointD &p2 = vertex(v2).P(); + const TPointD &p0 = vertex(v0).P(); + const TPointD &p1 = vertex(v1).P(); + const TPointD &p2 = vertex(v2).P(); - bool clockwise = (tcg::point_ops::cross(p2 - p0, p1 - p0) >= 0); - return ((tcg::point_ops::cross(p - p0, p1 - p0) >= 0) == clockwise) && - ((tcg::point_ops::cross(p - p1, p2 - p1) >= 0) == clockwise) && - ((tcg::point_ops::cross(p - p2, p0 - p2) >= 0) == clockwise); + bool clockwise = (tcg::point_ops::cross(p2 - p0, p1 - p0) >= 0); + return ((tcg::point_ops::cross(p - p0, p1 - p0) >= 0) == clockwise) && + ((tcg::point_ops::cross(p - p1, p2 - p1) >= 0) == clockwise) && + ((tcg::point_ops::cross(p - p2, p0 - p2) >= 0) == clockwise); } //----------------------------------------------------------------------- -int TTextureMesh::faceContaining(const TPointD &p) const -{ - int f, fCount = facesCount(); - for (f = 0; f < fCount; ++f) - if (faceContains(f, p)) - return f; - return -1; +int TTextureMesh::faceContaining(const TPointD &p) const { + int f, fCount = facesCount(); + for (f = 0; f < fCount; ++f) + if (faceContains(f, p)) return f; + return -1; } //----------------------------------------------------------------------- -TRectD TTextureMesh::getBBox() const -{ - // TODO: Should be cached... +TRectD TTextureMesh::getBBox() const { + // TODO: Should be cached... - const double max = (std::numeric_limits::max)(); - TRectD result(max, max, -max, -max); + const double max = (std::numeric_limits::max)(); + TRectD result(max, max, -max, -max); - // Iterate all meshes - assert(m_vertices.size() == m_vertices.nodesCount()); + // Iterate all meshes + assert(m_vertices.size() == m_vertices.nodesCount()); - int v, vCount = int(m_vertices.size()); - for (v = 0; v != vCount; ++v) { - const TTextureVertex &vx = m_vertices[v]; + int v, vCount = int(m_vertices.size()); + for (v = 0; v != vCount; ++v) { + const TTextureVertex &vx = m_vertices[v]; - result.x0 = std::min(result.x0, vx.P().x); - result.y0 = std::min(result.y0, vx.P().y); - result.x1 = std::max(result.x1, vx.P().x); - result.y1 = std::max(result.y1, vx.P().y); - } + result.x0 = std::min(result.x0, vx.P().x); + result.y0 = std::min(result.y0, vx.P().y); + result.x1 = std::max(result.x1, vx.P().x); + result.y1 = std::max(result.y1, vx.P().y); + } - return result; + return result; } //----------------------------------------------------------------------- -void TTextureMesh::saveData(TOStream &os) -{ - struct locals { - static inline bool hasNon1Rigidity(const TTextureMesh &mesh) - { - int v, vCount = int(mesh.verticesCount()); - for (v = 0; v != vCount; ++v) - if (mesh.vertex(v).P().rigidity != 1.0) - return true; - return false; - } - }; - - // NOTE: Primitives saved by INDEX iteration is NOT COINCIDENTAL - since - // the lists' internal linking could have been altered to mismatch the - // natural indexing referred to by primitives' data. - - if (m_vertices.size() != m_vertices.nodesCount() || - m_edges.size() != m_edges.nodesCount() || - m_faces.size() != m_faces.nodesCount()) { - // Ensure the mesh is already squeezed - save a squeezed - // copy if necessary - TTextureMesh mesh(*this); - - mesh.squeeze(); - mesh.saveData(os); - - return; - } - - assert(m_vertices.size() == m_vertices.nodesCount()); - assert(m_edges.size() == m_edges.nodesCount()); - assert(m_faces.size() == m_faces.nodesCount()); - - // Store Vertices - os.openChild("V"); - { - int vCount = int(m_vertices.size()); - os << vCount; - - for (int v = 0; v != vCount; ++v) { - TTextureMesh::vertex_type &vx = m_vertices[v]; - os << vx.P().x << vx.P().y; - } - } - os.closeChild(); - - // Store Edges - os.openChild("E"); - { - int eCount = int(m_edges.size()); - os << eCount; - - for (int e = 0; e != eCount; ++e) { - TTextureMesh::edge_type &ed = m_edges[e]; - os << ed.vertex(0) << ed.vertex(1); - } - } - os.closeChild(); - - // Store Faces - os.openChild("F"); - { - int fCount = int(m_faces.size()); - os << fCount; - - for (int f = 0; f != fCount; ++f) { - TTextureMesh::face_type &fc = m_faces[f]; - - int e, eCount = fc.edgesCount(); - for (e = 0; e < eCount; ++e) - os << fc.edge(e); - } - } - os.closeChild(); - - // Store rigidities - if (locals::hasNon1Rigidity(*this)) { - os.openChild("rigidities"); - { - int vCount = int(m_vertices.size()); - os << vCount; - - for (int v = 0; v != vCount; ++v) - os << m_vertices[v].P().rigidity; - } - os.closeChild(); - } +void TTextureMesh::saveData(TOStream &os) { + struct locals { + static inline bool hasNon1Rigidity(const TTextureMesh &mesh) { + int v, vCount = int(mesh.verticesCount()); + for (v = 0; v != vCount; ++v) + if (mesh.vertex(v).P().rigidity != 1.0) return true; + return false; + } + }; + + // NOTE: Primitives saved by INDEX iteration is NOT COINCIDENTAL - since + // the lists' internal linking could have been altered to mismatch the + // natural indexing referred to by primitives' data. + + if (m_vertices.size() != m_vertices.nodesCount() || + m_edges.size() != m_edges.nodesCount() || + m_faces.size() != m_faces.nodesCount()) { + // Ensure the mesh is already squeezed - save a squeezed + // copy if necessary + TTextureMesh mesh(*this); + + mesh.squeeze(); + mesh.saveData(os); + + return; + } + + assert(m_vertices.size() == m_vertices.nodesCount()); + assert(m_edges.size() == m_edges.nodesCount()); + assert(m_faces.size() == m_faces.nodesCount()); + + // Store Vertices + os.openChild("V"); + { + int vCount = int(m_vertices.size()); + os << vCount; + + for (int v = 0; v != vCount; ++v) { + TTextureMesh::vertex_type &vx = m_vertices[v]; + os << vx.P().x << vx.P().y; + } + } + os.closeChild(); + + // Store Edges + os.openChild("E"); + { + int eCount = int(m_edges.size()); + os << eCount; + + for (int e = 0; e != eCount; ++e) { + TTextureMesh::edge_type &ed = m_edges[e]; + os << ed.vertex(0) << ed.vertex(1); + } + } + os.closeChild(); + + // Store Faces + os.openChild("F"); + { + int fCount = int(m_faces.size()); + os << fCount; + + for (int f = 0; f != fCount; ++f) { + TTextureMesh::face_type &fc = m_faces[f]; + + int e, eCount = fc.edgesCount(); + for (e = 0; e < eCount; ++e) os << fc.edge(e); + } + } + os.closeChild(); + + // Store rigidities + if (locals::hasNon1Rigidity(*this)) { + os.openChild("rigidities"); + { + int vCount = int(m_vertices.size()); + os << vCount; + + for (int v = 0; v != vCount; ++v) os << m_vertices[v].P().rigidity; + } + os.closeChild(); + } } //----------------------------------------------------------------------- -void TTextureMesh::loadData(TIStream &is) -{ - typedef tcg::Mesh mesh_type; +void TTextureMesh::loadData(TIStream &is) { + typedef tcg::Mesh mesh_type; - std::string str; - int i, size; + std::string str; + int i, size; - while (is.openChild(str)) { - if (str == "V") { - is >> size; + while (is.openChild(str)) { + if (str == "V") { + is >> size; - m_vertices.reserve(size); - TTextureMesh::vertex_type v; + m_vertices.reserve(size); + TTextureMesh::vertex_type v; - for (i = 0; i < size; ++i) { - is >> v.P().x >> v.P().y; - mesh_type::addVertex(v); - } + for (i = 0; i < size; ++i) { + is >> v.P().x >> v.P().y; + mesh_type::addVertex(v); + } - is.closeChild(); - } else if (str == "E") { - is >> size; + is.closeChild(); + } else if (str == "E") { + is >> size; - m_edges.reserve(size); - int v0, v1; + m_edges.reserve(size); + int v0, v1; - for (i = 0; i < size; ++i) { - is >> v0 >> v1; - mesh_type::addEdge(TTextureMesh::edge_type(v0, v1)); - } + for (i = 0; i < size; ++i) { + is >> v0 >> v1; + mesh_type::addEdge(TTextureMesh::edge_type(v0, v1)); + } - is.closeChild(); - } else if (str == "F") { - is >> size; + is.closeChild(); + } else if (str == "F") { + is >> size; - m_faces.reserve(size); + m_faces.reserve(size); - int e[3]; + int e[3]; - for (i = 0; i < size; ++i) { - is >> e[0] >> e[1] >> e[2]; - mesh_type::addFace(TTextureMesh::face_type(e)); - } + for (i = 0; i < size; ++i) { + is >> e[0] >> e[1] >> e[2]; + mesh_type::addFace(TTextureMesh::face_type(e)); + } - is.closeChild(); - } else if (str == "rigidities") { - is >> size; - size = std::min(size, this->verticesCount()); + is.closeChild(); + } else if (str == "rigidities") { + is >> size; + size = std::min(size, this->verticesCount()); - for (i = 0; i < size; ++i) - is >> m_vertices[i].P().rigidity; + for (i = 0; i < size; ++i) is >> m_vertices[i].P().rigidity; - is.closeChild(); - } else { - assert(false); - is.skipCurrentTag(); - } - } + is.closeChild(); + } else { + assert(false); + is.skipCurrentTag(); + } + } } //****************************************************************************** // TMeshImage::Imp definition //****************************************************************************** -class TMeshImage::Imp -{ +class TMeshImage::Imp { public: - std::vector m_meshes; //!< Mesh data - double m_dpiX, m_dpiY; //!< Meshes dpi + std::vector m_meshes; //!< Mesh data + double m_dpiX, m_dpiY; //!< Meshes dpi - Imp() : m_dpiX(), m_dpiY() {} + Imp() : m_dpiX(), m_dpiY() {} - Imp(const Imp &other) - : m_meshes(tcg::make_cast_it(other.m_meshes.begin(), cloneMesh), - tcg::make_cast_it(other.m_meshes.end(), cloneMesh)), - m_dpiX(other.m_dpiX), m_dpiY(other.m_dpiY) {} + Imp(const Imp &other) + : m_meshes(tcg::make_cast_it(other.m_meshes.begin(), cloneMesh), + tcg::make_cast_it(other.m_meshes.end(), cloneMesh)) + , m_dpiX(other.m_dpiX) + , m_dpiY(other.m_dpiY) {} private: - static TTextureMeshP cloneMesh(const TTextureMeshP &other) - { - return TTextureMeshP(new TTextureMesh(*other)); - } + static TTextureMeshP cloneMesh(const TTextureMeshP &other) { + return TTextureMeshP(new TTextureMesh(*other)); + } - // Not assignable - Imp &operator=(const Imp &other); + // Not assignable + Imp &operator=(const Imp &other); }; //****************************************************************************** // TMeshImage implementation //****************************************************************************** -TMeshImage::TMeshImage() - : m_imp(new Imp) -{ -} +TMeshImage::TMeshImage() : m_imp(new Imp) {} //----------------------------------------------------------------------- -TMeshImage::TMeshImage(std::shared_ptr imp) - : m_imp(std::move(imp)) -{ -} +TMeshImage::TMeshImage(std::shared_ptr imp) : m_imp(std::move(imp)) {} //----------------------------------------------------------------------- -TMeshImage::~TMeshImage() -{ -} +TMeshImage::~TMeshImage() {} //----------------------------------------------------------------------- TMeshImage::TMeshImage(const TMeshImage &other) - : m_imp(new Imp(*other.m_imp)) -{ -} + : m_imp(new Imp(*other.m_imp)) {} //----------------------------------------------------------------------- -TMeshImage &TMeshImage::operator=(TMeshImage other) -{ - swap(*this, other); - return *this; +TMeshImage &TMeshImage::operator=(TMeshImage other) { + swap(*this, other); + return *this; } //----------------------------------------------------------------------- -TRectD TMeshImage::getBBox() const -{ - const double max = (std::numeric_limits::max)(); - TRectD result(max, max, -max, -max); +TRectD TMeshImage::getBBox() const { + const double max = (std::numeric_limits::max)(); + TRectD result(max, max, -max, -max); - // Iterate all meshes - int m, mCount = int(m_imp->m_meshes.size()); - for (m = 0; m < mCount; ++m) - result += m_imp->m_meshes[m]->getBBox(); + // Iterate all meshes + int m, mCount = int(m_imp->m_meshes.size()); + for (m = 0; m < mCount; ++m) result += m_imp->m_meshes[m]->getBBox(); - return result; + return result; } //----------------------------------------------------------------------- -TImage *TMeshImage::cloneImage() const -{ - return new TMeshImage(*this); -} +TImage *TMeshImage::cloneImage() const { return new TMeshImage(*this); } //----------------------------------------------------------------------- -void TMeshImage::getDpi(double &dpix, double &dpiy) const -{ - dpix = m_imp->m_dpiX, dpiy = m_imp->m_dpiY; +void TMeshImage::getDpi(double &dpix, double &dpiy) const { + dpix = m_imp->m_dpiX, dpiy = m_imp->m_dpiY; } //----------------------------------------------------------------------- -void TMeshImage::setDpi(double dpix, double dpiy) -{ - m_imp->m_dpiX = dpix, m_imp->m_dpiY = dpiy; +void TMeshImage::setDpi(double dpix, double dpiy) { + m_imp->m_dpiX = dpix, m_imp->m_dpiY = dpiy; } //----------------------------------------------------------------------- -const std::vector &TMeshImage::meshes() const -{ - return m_imp->m_meshes; +const std::vector &TMeshImage::meshes() const { + return m_imp->m_meshes; } //----------------------------------------------------------------------- -std::vector &TMeshImage::meshes() -{ - return m_imp->m_meshes; -} +std::vector &TMeshImage::meshes() { return m_imp->m_meshes; } diff --git a/toonz/sources/common/tmsgcore.cpp b/toonz/sources/common/tmsgcore.cpp index d70213c..ab1f373 100644 --- a/toonz/sources/common/tmsgcore.cpp +++ b/toonz/sources/common/tmsgcore.cpp @@ -9,223 +9,220 @@ #include #include -TMsgCore *TMsgCore::instance() -{ - static TMsgCore *theInstance = 0; - if (!theInstance) - theInstance = new TMsgCore(); - return theInstance; +TMsgCore *TMsgCore::instance() { + static TMsgCore *theInstance = 0; + if (!theInstance) theInstance = new TMsgCore(); + return theInstance; } //---------------------------------- -TMsgCore::TMsgCore() - : m_tcpServer(0), m_clientSocket(0) -{ -} +TMsgCore::TMsgCore() : m_tcpServer(0), m_clientSocket(0) {} //---------------------------------- -void TMsgCore::OnNewConnection() //server side +void TMsgCore::OnNewConnection() // server side { - QTcpSocket *socket; - if (m_tcpServer) - socket = m_tcpServer->nextPendingConnection(); - assert(socket); - - bool ret = connect(socket, SIGNAL(readyRead()), SLOT(OnReadyRead())); - ret = ret && connect(socket, SIGNAL(disconnected()), SLOT(OnDisconnected())); - assert(ret); - m_sockets.insert(socket); + QTcpSocket *socket; + if (m_tcpServer) socket = m_tcpServer->nextPendingConnection(); + assert(socket); + + bool ret = connect(socket, SIGNAL(readyRead()), SLOT(OnReadyRead())); + ret = ret && connect(socket, SIGNAL(disconnected()), SLOT(OnDisconnected())); + assert(ret); + m_sockets.insert(socket); } //---------------------------------------------------------- #define TMSG_PORT 10545 -bool TMsgCore::openConnection() //server side +bool TMsgCore::openConnection() // server side { - //QHostAddress host = (remoteConnection) ? QHostAddress::AnyQHostAddress::LocalHost : ; - - if (m_tcpServer != 0 && m_tcpServer->serverAddress() == QHostAddress::Any) - return true; - if (m_tcpServer != 0) - delete m_tcpServer; - - m_tcpServer = new QTcpServer(); - bool ret = connect(m_tcpServer, SIGNAL(newConnection()), SLOT(OnNewConnection())); - //bool listen = m_tcpServer->listen(QString("tmsg")+QString::number(QCoreApplication::applicationPid())); - bool listen = m_tcpServer->listen(QHostAddress::Any, TMSG_PORT); //QString("tmsg")+QString::number(QCoreApplication::applicationPid())); - if (!listen) { - QString err = m_tcpServer->errorString(); - } - - assert(ret && listen); - return true; + // QHostAddress host = (remoteConnection) ? + // QHostAddress::AnyQHostAddress::LocalHost : ; + + if (m_tcpServer != 0 && m_tcpServer->serverAddress() == QHostAddress::Any) + return true; + if (m_tcpServer != 0) delete m_tcpServer; + + m_tcpServer = new QTcpServer(); + bool ret = + connect(m_tcpServer, SIGNAL(newConnection()), SLOT(OnNewConnection())); + // bool listen = + // m_tcpServer->listen(QString("tmsg")+QString::number(QCoreApplication::applicationPid())); + bool listen = m_tcpServer->listen( + QHostAddress::Any, + TMSG_PORT); // QString("tmsg")+QString::number(QCoreApplication::applicationPid())); + if (!listen) { + QString err = m_tcpServer->errorString(); + } + + assert(ret && listen); + return true; } //--------------------------- -QString TMsgCore::getConnectionName() //server side +QString TMsgCore::getConnectionName() // server side { - assert(m_tcpServer); - QString serverName = "pippo"; //m_tcpServer->serverName(); - return serverName; + assert(m_tcpServer); + QString serverName = "pippo"; // m_tcpServer->serverName(); + return serverName; } //----------------------------------------------------------------------- -void TMsgCore::OnDisconnected() //server side +void TMsgCore::OnDisconnected() // server side { - std::set::iterator it = m_sockets.begin(); - while (it != m_sockets.end()) { - if ((*it)->state() != QTcpSocket::ConnectedState) - m_sockets.erase(it++); - else - it++; - } - - //if (m_socketIn) - //delete m_socketIn; - //m_socketIn = 0; + std::set::iterator it = m_sockets.begin(); + while (it != m_sockets.end()) { + if ((*it)->state() != QTcpSocket::ConnectedState) + m_sockets.erase(it++); + else + it++; + } + + // if (m_socketIn) + // delete m_socketIn; + // m_socketIn = 0; } //------------------------------------------------------------------ -void TMsgCore::OnReadyRead() //server side +void TMsgCore::OnReadyRead() // server side { - std::set::iterator it = m_sockets.begin(); - for (; it != m_sockets.end(); it++) //devo scorrerli tutti perche' non so da quale socket viene il messaggio... - { - if ((*it)->state() == QTcpSocket::ConnectedState && (*it)->bytesAvailable() > 0) - break; - } - if (it != m_sockets.end()) { - readFromSocket(*it); - OnReadyRead(); - } + std::set::iterator it = m_sockets.begin(); + for (; it != m_sockets.end(); it++) // devo scorrerli tutti perche' non so da + // quale socket viene il messaggio... + { + if ((*it)->state() == QTcpSocket::ConnectedState && + (*it)->bytesAvailable() > 0) + break; + } + if (it != m_sockets.end()) { + readFromSocket(*it); + OnReadyRead(); + } } //------------------------------------------------- -void TMsgCore::readFromSocket(QTcpSocket *socket) //server side +void TMsgCore::readFromSocket(QTcpSocket *socket) // server side { - static char data[1024]; - static QString prevMessage; - QString str; - int byteread; - - while ((byteread = socket->read(data, 1023)) != 0) { - data[byteread] = '\0'; - str += QString(data); - } - QString message = prevMessage + str; - prevMessage = QString(); - if (message.isEmpty()) - return; - - int lastEnd = message.lastIndexOf("#END"); - int lastbegin = message.lastIndexOf("#TMSG"); - if (lastbegin == -1 && lastEnd == -1) { - prevMessage = message; - return; - } else if (lastbegin != -1 && lastEnd != -1 && lastEnd < lastbegin) { - prevMessage = message.right(message.size() - lastbegin); - message.chop(lastbegin); - } - - QStringList messages = message.split("#TMSG", QString::SkipEmptyParts); - - for (int i = 0; i < messages.size(); i++) { - QString str = messages.at(i).simplified(); - str.chop(4); //rimuovo i "#END" alla fine - if (str.startsWith("ERROR")) - DVGui::error(str.right(str.size() - 5)); - else if (str.startsWith("WARNING")) - DVGui::warning(str.right(str.size() - 7)); - else if (str.startsWith("INFO")) - DVGui::info(str.right(str.size() - 4)); - else - assert(false); - } + static char data[1024]; + static QString prevMessage; + QString str; + int byteread; + + while ((byteread = socket->read(data, 1023)) != 0) { + data[byteread] = '\0'; + str += QString(data); + } + QString message = prevMessage + str; + prevMessage = QString(); + if (message.isEmpty()) return; + + int lastEnd = message.lastIndexOf("#END"); + int lastbegin = message.lastIndexOf("#TMSG"); + if (lastbegin == -1 && lastEnd == -1) { + prevMessage = message; + return; + } else if (lastbegin != -1 && lastEnd != -1 && lastEnd < lastbegin) { + prevMessage = message.right(message.size() - lastbegin); + message.chop(lastbegin); + } + + QStringList messages = message.split("#TMSG", QString::SkipEmptyParts); + + for (int i = 0; i < messages.size(); i++) { + QString str = messages.at(i).simplified(); + str.chop(4); // rimuovo i "#END" alla fine + if (str.startsWith("ERROR")) + DVGui::error(str.right(str.size() - 5)); + else if (str.startsWith("WARNING")) + DVGui::warning(str.right(str.size() - 7)); + else if (str.startsWith("INFO")) + DVGui::info(str.right(str.size() - 4)); + else + assert(false); + } } //------------------------------------------------------ -TMsgCore::~TMsgCore() -{ - if (m_tcpServer == 0 && m_clientSocket != 0) //client side - { - //m_socketIn->waitForBytesWritten (-1); - // m_clientSocket->disconnectFromServer(); - // m_clientSocket->waitForDisconnected(); - delete m_clientSocket; - m_clientSocket = 0; - } +TMsgCore::~TMsgCore() { + if (m_tcpServer == 0 && m_clientSocket != 0) // client side + { + // m_socketIn->waitForBytesWritten (-1); + // m_clientSocket->disconnectFromServer(); + // m_clientSocket->waitForDisconnected(); + delete m_clientSocket; + m_clientSocket = 0; + } } //---------------------------------- -bool TMsgCore::send(DVGui::MsgType type, const QString &message) //client side +bool TMsgCore::send(DVGui::MsgType type, const QString &message) // client side { - if (receivers(SIGNAL(sendMessage(int, const QString &))) == 0) { - if (m_clientSocket == 0 || m_clientSocket->state() != QTcpSocket::ConnectedState) - return false; + if (receivers(SIGNAL(sendMessage(int, const QString &))) == 0) { + if (m_clientSocket == 0 || + m_clientSocket->state() != QTcpSocket::ConnectedState) + return false; - QString socketMessage = (type == DVGui::CRITICAL ? "#TMSG ERROR " : (type == DVGui::WARNING ? "#TMSG WARNING " : "#TMSG INFO ")) + message + " #END\n"; + QString socketMessage = + (type == DVGui::CRITICAL + ? "#TMSG ERROR " + : (type == DVGui::WARNING ? "#TMSG WARNING " : "#TMSG INFO ")) + + message + " #END\n"; #if QT_VERSION >= 0x050000 - m_clientSocket->write(socketMessage.toLatin1()); + m_clientSocket->write(socketMessage.toLatin1()); #else - m_clientSocket->write(socketMessage.toAscii()); + m_clientSocket->write(socketMessage.toAscii()); #endif - m_clientSocket->flush(); - //m_clientSocket->waitForBytesWritten (1000); - } else - Q_EMIT sendMessage(type, message); + m_clientSocket->flush(); + // m_clientSocket->waitForBytesWritten (1000); + } else + Q_EMIT sendMessage(type, message); - return true; + return true; } //------------------------------------------------------------------- -void TMsgCore::connectTo(const QString &address) //client side +void TMsgCore::connectTo(const QString &address) // client side { - m_clientSocket = new QTcpSocket(); - m_clientSocket->connectToHost(address == "" ? QHostAddress::LocalHost : QHostAddress(address), TMSG_PORT); - //m_clientSocket->connectToServer (connectionName, QIODevice::ReadWrite | QIODevice::Text); - bool ret = m_clientSocket->waitForConnected(1000); - if (!ret) { - // std::cout << "cannot connect to "<< address.toStdString() << std::endl; - //std::cout << "error "<< m_clientSocket->errorString().toStdString() << std::endl; - int err = m_clientSocket->error(); - } + m_clientSocket = new QTcpSocket(); + m_clientSocket->connectToHost( + address == "" ? QHostAddress::LocalHost : QHostAddress(address), + TMSG_PORT); + // m_clientSocket->connectToServer (connectionName, QIODevice::ReadWrite | + // QIODevice::Text); + bool ret = m_clientSocket->waitForConnected(1000); + if (!ret) { + // std::cout << "cannot connect to "<< address.toStdString() << std::endl; + // std::cout << "error "<< m_clientSocket->errorString().toStdString() << + // std::endl; + int err = m_clientSocket->error(); + } } //----------------------------------------------------------------------- -void DVGui::MsgBox(MsgType type, const QString &text) -{ - TMsgCore::instance()->send(type, text); +void DVGui::MsgBox(MsgType type, const QString &text) { + TMsgCore::instance()->send(type, text); } //----------------------------------------------------------------------- -void DVGui::error(const QString &msg) -{ - DVGui::MsgBox(DVGui::CRITICAL, msg); -} +void DVGui::error(const QString &msg) { DVGui::MsgBox(DVGui::CRITICAL, msg); } //----------------------------------------------------------------------------- -void DVGui::warning(const QString &msg) -{ - DVGui::MsgBox(DVGui::WARNING, msg); -} +void DVGui::warning(const QString &msg) { DVGui::MsgBox(DVGui::WARNING, msg); } //----------------------------------------------------------------------------- -void DVGui::info(const QString &msg) -{ - DVGui::MsgBox(DVGui::INFORMATION, msg); -} +void DVGui::info(const QString &msg) { DVGui::MsgBox(DVGui::INFORMATION, msg); } diff --git a/toonz/sources/common/tparam/tcubicbezier.cpp b/toonz/sources/common/tparam/tcubicbezier.cpp index 533d867..d0e4bbe 100644 --- a/toonz/sources/common/tparam/tcubicbezier.cpp +++ b/toonz/sources/common/tparam/tcubicbezier.cpp @@ -4,126 +4,111 @@ //----------------------------------------------------------------------------- -DVAPI double invCubicBezierX(double x, - const TPointD &a, - const TPointD &aSpeed, - const TPointD &bSpeed, - const TPointD &b) -{ - double aSpeedX = aSpeed.x; - double bSpeedX = bSpeed.x; - if (aSpeedX == 0) - aSpeedX = epsilon; - if (bSpeedX == 0) - bSpeedX = -epsilon; - - // a*u^3+b*u^2+c*u+d - double x0 = a.x; - double x1 = x0 + aSpeedX; - double x3 = b.x; - double x2 = x3 + bSpeedX; - - double aX = x3 + 3 * (x1 - x2) - x0; - double bX = 3 * (x2 - 2 * x1 + x0); - double cX = 3 * (x1 - x0); - double dX = x0 - x; - - return cubicRoot(aX, bX, cX, dX); +DVAPI double invCubicBezierX(double x, const TPointD &a, const TPointD &aSpeed, + const TPointD &bSpeed, const TPointD &b) { + double aSpeedX = aSpeed.x; + double bSpeedX = bSpeed.x; + if (aSpeedX == 0) aSpeedX = epsilon; + if (bSpeedX == 0) bSpeedX = -epsilon; + + // a*u^3+b*u^2+c*u+d + double x0 = a.x; + double x1 = x0 + aSpeedX; + double x3 = b.x; + double x2 = x3 + bSpeedX; + + double aX = x3 + 3 * (x1 - x2) - x0; + double bX = 3 * (x2 - 2 * x1 + x0); + double cX = 3 * (x1 - x0); + double dX = x0 - x; + + return cubicRoot(aX, bX, cX, dX); } //----------------------------------------------------------------------------- -DVAPI double getCubicBezierY(double x, - const TPointD &a, - const TPointD &aSpeed, - const TPointD &bSpeed, - const TPointD &b) -{ - double y0 = a.y; - double y1 = y0 + aSpeed.y; - double y3 = b.y; - double y2 = y3 + bSpeed.y; - - double aY = y3 + 3 * (y1 - y2) - y0; - double bY = 3 * (y2 - 2 * y1 + y0); - double cY = 3 * (y1 - y0); - double dY = y0; - - double u = invCubicBezierX(x, a, aSpeed, bSpeed, b); - u = tcrop(u, 0.0, 1.0); - return aY * u * u * u + bY * u * u + cY * u + dY; +DVAPI double getCubicBezierY(double x, const TPointD &a, const TPointD &aSpeed, + const TPointD &bSpeed, const TPointD &b) { + double y0 = a.y; + double y1 = y0 + aSpeed.y; + double y3 = b.y; + double y2 = y3 + bSpeed.y; + + double aY = y3 + 3 * (y1 - y2) - y0; + double bY = 3 * (y2 - 2 * y1 + y0); + double cY = 3 * (y1 - y0); + double dY = y0; + + double u = invCubicBezierX(x, a, aSpeed, bSpeed, b); + u = tcrop(u, 0.0, 1.0); + return aY * u * u * u + bY * u * u + cY * u + dY; } //----------------------------------------------------------------------------- DVAPI std::pair getMinMaxCubicBezierY(const TPointD &a, - const TPointD &aSpeed, - const TPointD &bSpeed, - const TPointD &b) -{ - double y0 = a.y; - double y1 = y0 + aSpeed.y; - double y3 = b.y; - double y2 = y3 + bSpeed.y; - - double aY = y3 + 3 * (y1 - y2) - y0; - double bY = 3 * (y2 - 2 * y1 + y0); - double cY = 3 * (y1 - y0); - double dY = y0; - - double x0 = a.x; - double x1 = x0 + aSpeed.x; - double x3 = b.x; - double x2 = x3 + bSpeed.x; - - double aX = x3 + 3 * (x1 - x2) - x0; - double bX = 3 * (x2 - 2 * x1 + x0); - double cX = 3 * (x1 - x0); - double dX = x0; - - double aaY = 3 * (y1 - y2) - y0 + y3; - double bbY = 2 * (y0 + y2 - 2 * y1); - double ccY = y1 - y0; - - if (aaY == 0) { - if (a.y < b.y) - return std::pair(TPointD(a.x, a.y), - TPointD(b.x, b.y)); - else - return std::pair(TPointD(b.x, b.y), - TPointD(a.x, a.y)); - } else { - double discr = bbY * bbY - 4 * aaY * ccY; - if (discr < 0) { - if (a.y < b.y) - return std::pair(TPointD(a.x, a.y), - TPointD(b.x, b.y)); - else - return std::pair(TPointD(b.x, b.y), - TPointD(a.x, a.y)); - } else { - double sqrt_discr = sqrt(discr); - double inv_2aY = 1.0 / (2.0 * aaY); - double u0 = (-bbY + sqrt_discr) * inv_2aY; - double u1 = (-bbY - sqrt_discr) * inv_2aY; - if (u0 > 1.0) - u0 = 1.0; - if (u0 < 0.0) - u0 = 0.0; - if (u1 > 1.0) - u1 = 1.0; - if (u1 < 0.0) - u1 = 0.0; - double y_0 = aY * u0 * u0 * u0 + bY * u0 * u0 + cY * u0 + dY; - double y_1 = aY * u1 * u1 * u1 + bY * u1 * u1 + cY * u1 + dY; - double x_0 = aX * u0 * u0 * u0 + bX * u0 * u0 + cX * u0 + dX; - double x_1 = aX * u1 * u1 * u1 + bX * u1 * u1 + cX * u1 + dX; - if (y_0 < y_1) - return std::pair(TPointD(x_0, y_0), TPointD(x_1, y_1)); - else - return std::pair(TPointD(x_1, y_1), TPointD(x_0, y_0)); - } - } + const TPointD &aSpeed, + const TPointD &bSpeed, + const TPointD &b) { + double y0 = a.y; + double y1 = y0 + aSpeed.y; + double y3 = b.y; + double y2 = y3 + bSpeed.y; + + double aY = y3 + 3 * (y1 - y2) - y0; + double bY = 3 * (y2 - 2 * y1 + y0); + double cY = 3 * (y1 - y0); + double dY = y0; + + double x0 = a.x; + double x1 = x0 + aSpeed.x; + double x3 = b.x; + double x2 = x3 + bSpeed.x; + + double aX = x3 + 3 * (x1 - x2) - x0; + double bX = 3 * (x2 - 2 * x1 + x0); + double cX = 3 * (x1 - x0); + double dX = x0; + + double aaY = 3 * (y1 - y2) - y0 + y3; + double bbY = 2 * (y0 + y2 - 2 * y1); + double ccY = y1 - y0; + + if (aaY == 0) { + if (a.y < b.y) + return std::pair(TPointD(a.x, a.y), TPointD(b.x, b.y)); + else + return std::pair(TPointD(b.x, b.y), TPointD(a.x, a.y)); + } else { + double discr = bbY * bbY - 4 * aaY * ccY; + if (discr < 0) { + if (a.y < b.y) + return std::pair(TPointD(a.x, a.y), + TPointD(b.x, b.y)); + else + return std::pair(TPointD(b.x, b.y), + TPointD(a.x, a.y)); + } else { + double sqrt_discr = sqrt(discr); + double inv_2aY = 1.0 / (2.0 * aaY); + double u0 = (-bbY + sqrt_discr) * inv_2aY; + double u1 = (-bbY - sqrt_discr) * inv_2aY; + if (u0 > 1.0) u0 = 1.0; + if (u0 < 0.0) u0 = 0.0; + if (u1 > 1.0) u1 = 1.0; + if (u1 < 0.0) u1 = 0.0; + double y_0 = aY * u0 * u0 * u0 + bY * u0 * u0 + cY * u0 + dY; + double y_1 = aY * u1 * u1 * u1 + bY * u1 * u1 + cY * u1 + dY; + double x_0 = aX * u0 * u0 * u0 + bX * u0 * u0 + cX * u0 + dX; + double x_1 = aX * u1 * u1 * u1 + bX * u1 * u1 + cX * u1 + dX; + if (y_0 < y_1) + return std::pair(TPointD(x_0, y_0), + TPointD(x_1, y_1)); + else + return std::pair(TPointD(x_1, y_1), + TPointD(x_0, y_0)); + } + } } //----------------------------------------------------------------------------- diff --git a/toonz/sources/common/tparam/tdoublekeyframe.cpp b/toonz/sources/common/tparam/tdoublekeyframe.cpp index f34fdd5..9926afd 100644 --- a/toonz/sources/common/tparam/tdoublekeyframe.cpp +++ b/toonz/sources/common/tparam/tdoublekeyframe.cpp @@ -6,152 +6,151 @@ #include "tunit.h" TDoubleKeyframe::TDoubleKeyframe(double frame, double value) - : m_type(Linear), m_frame(frame), m_value(value), m_step(1), m_isKeyframe(false), m_speedIn(), m_speedOut(), m_linkedHandles(true), m_expressionText(""), m_fileParams(), m_similarShapeOffset(0), m_unitName("") -{ -} + : m_type(Linear) + , m_frame(frame) + , m_value(value) + , m_step(1) + , m_isKeyframe(false) + , m_speedIn() + , m_speedOut() + , m_linkedHandles(true) + , m_expressionText("") + , m_fileParams() + , m_similarShapeOffset(0) + , m_unitName("") {} -TDoubleKeyframe::~TDoubleKeyframe() -{ -} +TDoubleKeyframe::~TDoubleKeyframe() {} -void TDoubleKeyframe::saveData(TOStream &os) const -{ - static std::map typeCodes; - if (typeCodes.empty()) { - typeCodes[None] = "n"; - typeCodes[Constant] = "C"; - typeCodes[Linear] = "L"; - typeCodes[Exponential] = "Exp"; - typeCodes[SpeedInOut] = "S"; - typeCodes[EaseInOut] = "E"; - typeCodes[EaseInOutPercentage] = "Ep"; - typeCodes[Expression] = "Ex"; - typeCodes[File] = "F"; - typeCodes[SimilarShape] = "SimShape"; - }; - std::map attr; - if (!m_linkedHandles) - attr["lnk"] = "no"; - if (m_step > 1) - attr["step"] = std::to_string(m_step); - os.openChild(typeCodes[m_type], attr); - switch (m_prevType) { - case Linear: - os.child("prev") << m_value; - break; - case SpeedInOut: - os.child("prev") << m_value << m_speedIn.x << m_speedIn.y; - break; - case EaseInOut: - case EaseInOutPercentage: - os.child("prev") << m_value << m_speedIn.x; - break; - } - std::string unitName = m_unitName != "" ? m_unitName : "default"; - // Dirty resolution. Because the degree sign is converted to unexpected string... - if (QString::fromStdWString(L"\u00b0").toStdString() == unitName) - unitName = "\\u00b0"; - switch (m_type) { - case Constant: - case Exponential: - case Linear: - os << m_frame << m_value; - break; - case SpeedInOut: - os << m_frame << m_value - << m_speedOut.x << m_speedOut.y; - break; - case EaseInOut: - case EaseInOutPercentage: - os << m_frame << m_value - << m_speedOut.x; - break; - case Expression: - os << m_frame << m_expressionText << unitName; - break; - case SimilarShape: - os << m_frame << m_value << m_expressionText << m_similarShapeOffset; - break; - case File: - os << m_frame << m_fileParams.m_path << m_fileParams.m_fieldIndex << unitName; - break; - } - os.closeChild(); +void TDoubleKeyframe::saveData(TOStream &os) const { + static std::map typeCodes; + if (typeCodes.empty()) { + typeCodes[None] = "n"; + typeCodes[Constant] = "C"; + typeCodes[Linear] = "L"; + typeCodes[Exponential] = "Exp"; + typeCodes[SpeedInOut] = "S"; + typeCodes[EaseInOut] = "E"; + typeCodes[EaseInOutPercentage] = "Ep"; + typeCodes[Expression] = "Ex"; + typeCodes[File] = "F"; + typeCodes[SimilarShape] = "SimShape"; + }; + std::map attr; + if (!m_linkedHandles) attr["lnk"] = "no"; + if (m_step > 1) attr["step"] = std::to_string(m_step); + os.openChild(typeCodes[m_type], attr); + switch (m_prevType) { + case Linear: + os.child("prev") << m_value; + break; + case SpeedInOut: + os.child("prev") << m_value << m_speedIn.x << m_speedIn.y; + break; + case EaseInOut: + case EaseInOutPercentage: + os.child("prev") << m_value << m_speedIn.x; + break; + } + std::string unitName = m_unitName != "" ? m_unitName : "default"; + // Dirty resolution. Because the degree sign is converted to unexpected + // string... + if (QString::fromStdWString(L"\u00b0").toStdString() == unitName) + unitName = "\\u00b0"; + switch (m_type) { + case Constant: + case Exponential: + case Linear: + os << m_frame << m_value; + break; + case SpeedInOut: + os << m_frame << m_value << m_speedOut.x << m_speedOut.y; + break; + case EaseInOut: + case EaseInOutPercentage: + os << m_frame << m_value << m_speedOut.x; + break; + case Expression: + os << m_frame << m_expressionText << unitName; + break; + case SimilarShape: + os << m_frame << m_value << m_expressionText << m_similarShapeOffset; + break; + case File: + os << m_frame << m_fileParams.m_path << m_fileParams.m_fieldIndex + << unitName; + break; + } + os.closeChild(); } -void TDoubleKeyframe::loadData(TIStream &is) -{ - static std::map typeCodes; - if (typeCodes.empty()) { - typeCodes["n"] = None; - typeCodes["C"] = Constant; - typeCodes["L"] = Linear; - typeCodes["Exp"] = Exponential; - typeCodes["S"] = SpeedInOut; - typeCodes["E"] = EaseInOut; - typeCodes["Ep"] = EaseInOutPercentage; - typeCodes["Ex"] = Expression; - typeCodes["F"] = File; - typeCodes["SimShape"] = SimilarShape; - }; +void TDoubleKeyframe::loadData(TIStream &is) { + static std::map typeCodes; + if (typeCodes.empty()) { + typeCodes["n"] = None; + typeCodes["C"] = Constant; + typeCodes["L"] = Linear; + typeCodes["Exp"] = Exponential; + typeCodes["S"] = SpeedInOut; + typeCodes["E"] = EaseInOut; + typeCodes["Ep"] = EaseInOutPercentage; + typeCodes["Ex"] = Expression; + typeCodes["F"] = File; + typeCodes["SimShape"] = SimilarShape; + }; - std::string tagName; - if (!is.matchTag(tagName)) - return; - std::map::iterator it = - typeCodes.find(tagName); - if (it == typeCodes.end()) { - throw TException(tagName + " : unexpected tag"); - } - m_type = it->second; - is.getTagParam("step", m_step); - std::string lnkValue; - if (is.getTagParam("lnk", lnkValue) && lnkValue == "no") - m_linkedHandles = false; - if (is.matchTag(tagName)) { - if (tagName != "prev") - throw TException(tagName + " : unexpected tag"); + std::string tagName; + if (!is.matchTag(tagName)) return; + std::map::iterator it = + typeCodes.find(tagName); + if (it == typeCodes.end()) { + throw TException(tagName + " : unexpected tag"); + } + m_type = it->second; + is.getTagParam("step", m_step); + std::string lnkValue; + if (is.getTagParam("lnk", lnkValue) && lnkValue == "no") + m_linkedHandles = false; + if (is.matchTag(tagName)) { + if (tagName != "prev") throw TException(tagName + " : unexpected tag"); - is >> m_value; - if (!is.eos()) { - is >> m_speedIn.x; - if (!is.eos()) - is >> m_speedIn.y; - } - if (!is.matchEndTag()) - throw TException(tagName + " : missing endtag"); - } - double dummy0, dummy1; - switch (m_type) { - case Constant: - case Linear: - case Exponential: - is >> m_frame >> m_value; - break; - case SpeedInOut: - is >> m_frame >> m_value >> m_speedOut.x >> m_speedOut.y; - if (!is.eos()) - is >> dummy0 >> dummy1; // old and wrong format. used only during the 6.0 release - break; - case EaseInOut: - case EaseInOutPercentage: - is >> m_frame >> m_value >> m_speedOut.x; - if (!is.eos()) - is >> dummy0; // old and wrong format. used only during the 6.0 release - break; - case Expression: - is >> m_frame >> m_expressionText >> m_unitName; - break; - case SimilarShape: - is >> m_frame >> m_value >> m_expressionText >> m_similarShapeOffset; - break; - case File: - is >> m_frame >> m_fileParams.m_path >> m_fileParams.m_fieldIndex >> m_unitName; - break; - } - if (!is.matchEndTag()) - throw TException(tagName + " : missing endtag"); - if (m_unitName == "default") - m_unitName = ""; - m_isKeyframe = true; + is >> m_value; + if (!is.eos()) { + is >> m_speedIn.x; + if (!is.eos()) is >> m_speedIn.y; + } + if (!is.matchEndTag()) throw TException(tagName + " : missing endtag"); + } + double dummy0, dummy1; + switch (m_type) { + case Constant: + case Linear: + case Exponential: + is >> m_frame >> m_value; + break; + case SpeedInOut: + is >> m_frame >> m_value >> m_speedOut.x >> m_speedOut.y; + if (!is.eos()) + is >> dummy0 >> + dummy1; // old and wrong format. used only during the 6.0 release + break; + case EaseInOut: + case EaseInOutPercentage: + is >> m_frame >> m_value >> m_speedOut.x; + if (!is.eos()) + is >> dummy0; // old and wrong format. used only during the 6.0 release + break; + case Expression: + is >> m_frame >> m_expressionText >> m_unitName; + break; + case SimilarShape: + is >> m_frame >> m_value >> m_expressionText >> m_similarShapeOffset; + break; + case File: + is >> m_frame >> m_fileParams.m_path >> m_fileParams.m_fieldIndex >> + m_unitName; + break; + } + if (!is.matchEndTag()) throw TException(tagName + " : missing endtag"); + if (m_unitName == "default") m_unitName = ""; + m_isKeyframe = true; } diff --git a/toonz/sources/common/tparam/tdoubleparam.cpp b/toonz/sources/common/tparam/tdoubleparam.cpp index ada771c..6913c97 100644 --- a/toonz/sources/common/tparam/tdoubleparam.cpp +++ b/toonz/sources/common/tparam/tdoubleparam.cpp @@ -24,461 +24,425 @@ using namespace std; //=============================== -class TActualDoubleKeyframe : public TDoubleKeyframe -{ +class TActualDoubleKeyframe : public TDoubleKeyframe { public: - mutable TExpression m_expression; - mutable TDoubleParamFileData m_fileData; - - TActualDoubleKeyframe(double frame = 0, double value = 0) - : TDoubleKeyframe(frame, value), m_unit(0) {} - explicit TActualDoubleKeyframe(const TDoubleKeyframe &src) : m_unit(0) - { - TDoubleKeyframe::operator=(src); - if (m_type == Expression || m_type == SimilarShape) - m_expression.setText(m_expressionText); - else if (m_type == File) - m_fileData.setParams(m_fileParams); - } - TActualDoubleKeyframe &operator=(const TDoubleKeyframe &src) - { - - TDoubleKeyframe::operator=(src); - m_unit = 0; - if (m_type == Expression || m_type == SimilarShape) { - m_expression.setText(m_expressionText); - } else if (m_type == File) { - m_fileData.setParams(m_fileParams); - } - return *this; - } - - const TUnit *updateUnit(const TMeasure *measure) - { - if (!measure) { - m_unit = 0; - m_unitName = ""; - } else { - if (m_unitName != "") - m_unit = measure->getUnit(::to_wstring(m_unitName)); - else - m_unit = 0; - if (!m_unit) { - m_unit = measure->getCurrentUnit(); - if (m_unit) { - QString app = QString::fromStdWString(m_unit->getDefaultExtension()); - m_unitName = app.toStdString(); - } - } - } - assert(measure || m_unit == 0 && m_unitName == ""); - assert((m_unit == 0) == (m_unitName == "")); - QString app = QString::fromStdString(m_unitName); - assert(m_unit == 0 || m_unit->isExtension(app.toStdWString())); - return m_unit; - } - - double convertFrom(TMeasure *measure, double value) const - { - if (!m_unit) - const_cast(this)->updateUnit(measure); - if (m_unit) - value = m_unit->convertFrom(value); - return value; - } + mutable TExpression m_expression; + mutable TDoubleParamFileData m_fileData; + + TActualDoubleKeyframe(double frame = 0, double value = 0) + : TDoubleKeyframe(frame, value), m_unit(0) {} + explicit TActualDoubleKeyframe(const TDoubleKeyframe &src) : m_unit(0) { + TDoubleKeyframe::operator=(src); + if (m_type == Expression || m_type == SimilarShape) + m_expression.setText(m_expressionText); + else if (m_type == File) + m_fileData.setParams(m_fileParams); + } + TActualDoubleKeyframe &operator=(const TDoubleKeyframe &src) { + TDoubleKeyframe::operator=(src); + m_unit = 0; + if (m_type == Expression || m_type == SimilarShape) { + m_expression.setText(m_expressionText); + } else if (m_type == File) { + m_fileData.setParams(m_fileParams); + } + return *this; + } + + const TUnit *updateUnit(const TMeasure *measure) { + if (!measure) { + m_unit = 0; + m_unitName = ""; + } else { + if (m_unitName != "") + m_unit = measure->getUnit(::to_wstring(m_unitName)); + else + m_unit = 0; + if (!m_unit) { + m_unit = measure->getCurrentUnit(); + if (m_unit) { + QString app = QString::fromStdWString(m_unit->getDefaultExtension()); + m_unitName = app.toStdString(); + } + } + } + assert(measure || m_unit == 0 && m_unitName == ""); + assert((m_unit == 0) == (m_unitName == "")); + QString app = QString::fromStdString(m_unitName); + assert(m_unit == 0 || m_unit->isExtension(app.toStdWString())); + return m_unit; + } + + double convertFrom(TMeasure *measure, double value) const { + if (!m_unit) const_cast(this)->updateUnit(measure); + if (m_unit) value = m_unit->convertFrom(value); + return value; + } private: - mutable const TUnit *m_unit; + mutable const TUnit *m_unit; }; typedef vector DoubleKeyframeVector; //=================================================================== -inline double getConstantValue( - const TActualDoubleKeyframe &k0, - const TActualDoubleKeyframe &k1, - double f) -{ - return (f == k1.m_frame) ? k1.m_value : k0.m_value; +inline double getConstantValue(const TActualDoubleKeyframe &k0, + const TActualDoubleKeyframe &k1, double f) { + return (f == k1.m_frame) ? k1.m_value : k0.m_value; } //--------------------------------------------------------- -inline double getLinearValue( - const TActualDoubleKeyframe &k0, - const TActualDoubleKeyframe &k1, - double f) -{ - return k0.m_value + - (f - k0.m_frame) * (k1.m_value - k0.m_value) / (k1.m_frame - k0.m_frame); +inline double getLinearValue(const TActualDoubleKeyframe &k0, + const TActualDoubleKeyframe &k1, double f) { + return k0.m_value + + (f - k0.m_frame) * (k1.m_value - k0.m_value) / + (k1.m_frame - k0.m_frame); } //--------------------------------------------------------- -void truncateSpeeds(double aFrame, double bFrame, TPointD &aSpeedTrunc, TPointD &bSpeedTrunc) -{ - double deltaX = bFrame - aFrame; - if (aSpeedTrunc.x < 0) - aSpeedTrunc.x = 0; - if (bSpeedTrunc.x > 0) - bSpeedTrunc.x = 0; - - if (aFrame + aSpeedTrunc.x > bFrame) { - if (aSpeedTrunc.x != 0) { - aSpeedTrunc = aSpeedTrunc * (deltaX / aSpeedTrunc.x); - } - } - - if (bFrame + bSpeedTrunc.x < aFrame) { - if (bSpeedTrunc.x != 0) { - bSpeedTrunc = -bSpeedTrunc * (deltaX / bSpeedTrunc.x); - } - } +void truncateSpeeds(double aFrame, double bFrame, TPointD &aSpeedTrunc, + TPointD &bSpeedTrunc) { + double deltaX = bFrame - aFrame; + if (aSpeedTrunc.x < 0) aSpeedTrunc.x = 0; + if (bSpeedTrunc.x > 0) bSpeedTrunc.x = 0; + + if (aFrame + aSpeedTrunc.x > bFrame) { + if (aSpeedTrunc.x != 0) { + aSpeedTrunc = aSpeedTrunc * (deltaX / aSpeedTrunc.x); + } + } + + if (bFrame + bSpeedTrunc.x < aFrame) { + if (bSpeedTrunc.x != 0) { + bSpeedTrunc = -bSpeedTrunc * (deltaX / bSpeedTrunc.x); + } + } } //--------------------------------------------------------- -inline double getSpeedInOutValue( - const TActualDoubleKeyframe &k0, - const TActualDoubleKeyframe &k1, - const TPointD &speed0, - const TPointD &speed1, - double frame) -{ - - double aFrame = k0.m_frame; - double bFrame = k1.m_frame; +inline double getSpeedInOutValue(const TActualDoubleKeyframe &k0, + const TActualDoubleKeyframe &k1, + const TPointD &speed0, const TPointD &speed1, + double frame) { + double aFrame = k0.m_frame; + double bFrame = k1.m_frame; - double aValue = k0.m_value; - double bValue = k1.m_value; + double aValue = k0.m_value; + double bValue = k1.m_value; - if (frame <= aFrame) - return aValue; - else if (frame >= bFrame) - return bValue; + if (frame <= aFrame) + return aValue; + else if (frame >= bFrame) + return bValue; - TPointD aSpeedTrunc = speed0; - TPointD bSpeedTrunc = speed1; - truncateSpeeds(aFrame, bFrame, aSpeedTrunc, bSpeedTrunc); + TPointD aSpeedTrunc = speed0; + TPointD bSpeedTrunc = speed1; + truncateSpeeds(aFrame, bFrame, aSpeedTrunc, bSpeedTrunc); - return getCubicBezierY(frame, - TPointD(aFrame, aValue), - aSpeedTrunc, - bSpeedTrunc, - TPointD(bFrame, bValue)); + return getCubicBezierY(frame, TPointD(aFrame, aValue), aSpeedTrunc, + bSpeedTrunc, TPointD(bFrame, bValue)); } //--------------------------------------------------------- -DV_EXPORT_API void splitSpeedInOutSegment( - TDoubleKeyframe &k, - TDoubleKeyframe &k0, - TDoubleKeyframe &k1) -{ - if (k.m_frame <= k0.m_frame) { - k = k0; - return; - } else if (k.m_frame >= k1.m_frame) { - k = k1; - return; - } - - TPointD aSpeed = k0.m_speedOut; - TPointD bSpeed = k1.m_speedIn; - truncateSpeeds(k0.m_frame, k1.m_frame, aSpeed, bSpeed); - - TPointD p0(k0.m_frame, k0.m_value); - TPointD p3(k1.m_frame, k1.m_value); - TPointD p1 = p0 + aSpeed; - TPointD p2 = p3 + bSpeed; - double t = invCubicBezierX(k.m_frame, p0, aSpeed, bSpeed, p3); - t = tcrop(t, 0.0, 1.0); - - TPointD p01 = (1 - t) * p0 + t * p1; - TPointD p12 = (1 - t) * p1 + t * p2; - TPointD p23 = (1 - t) * p2 + t * p3; - - TPointD p012 = (1 - t) * p01 + t * p12; - TPointD p123 = (1 - t) * p12 + t * p23; - - TPointD p = (1 - t) * p012 + t * p123; - - assert(fabs(p.x - k.m_frame) < 0.1e-3); - k.m_value = p.y; - - k0.m_speedOut = p01 - p0; - k.m_speedIn = p012 - p; - k.m_speedOut = p123 - p; - k1.m_speedIn = p23 - p3; +DV_EXPORT_API void splitSpeedInOutSegment(TDoubleKeyframe &k, + TDoubleKeyframe &k0, + TDoubleKeyframe &k1) { + if (k.m_frame <= k0.m_frame) { + k = k0; + return; + } else if (k.m_frame >= k1.m_frame) { + k = k1; + return; + } + + TPointD aSpeed = k0.m_speedOut; + TPointD bSpeed = k1.m_speedIn; + truncateSpeeds(k0.m_frame, k1.m_frame, aSpeed, bSpeed); + + TPointD p0(k0.m_frame, k0.m_value); + TPointD p3(k1.m_frame, k1.m_value); + TPointD p1 = p0 + aSpeed; + TPointD p2 = p3 + bSpeed; + double t = invCubicBezierX(k.m_frame, p0, aSpeed, bSpeed, p3); + t = tcrop(t, 0.0, 1.0); + + TPointD p01 = (1 - t) * p0 + t * p1; + TPointD p12 = (1 - t) * p1 + t * p2; + TPointD p23 = (1 - t) * p2 + t * p3; + + TPointD p012 = (1 - t) * p01 + t * p12; + TPointD p123 = (1 - t) * p12 + t * p23; + + TPointD p = (1 - t) * p012 + t * p123; + + assert(fabs(p.x - k.m_frame) < 0.1e-3); + k.m_value = p.y; + + k0.m_speedOut = p01 - p0; + k.m_speedIn = p012 - p; + k.m_speedOut = p123 - p; + k1.m_speedIn = p23 - p3; } //--------------------------------------------------------- -inline double getEaseInOutValue( - const TActualDoubleKeyframe &k0, - const TActualDoubleKeyframe &k1, - double frame, - bool percentage) -{ - double x3 = k1.m_frame - k0.m_frame; - if (x3 <= 0.0) - return k0.m_value; - double x = frame - k0.m_frame; - if (x <= 0) - return k0.m_value; - else if (x >= x3) - return k1.m_value; - double e0 = std::max(k0.m_speedOut.x, 0.0); - double e1 = std::max(-k1.m_speedIn.x, 0.0); - if (percentage) { - e0 *= x3 * 0.01; - e1 *= x3 * 0.01; - } - if (e0 + e1 >= x3) { - double x = tcrop((e0 + x3 - e1) / 2, 0.0, x3); - e0 = x; - e1 = x3 - x; - } - double x1 = e0, x2 = x3 - e1; - if (0 < x1 - x2 && x1 - x2 < 0.1e-5) - x1 = x2 = (x1 + x2) * 0.5; // against rounding problems - assert(0 <= x1 && x1 <= x2 && x2 <= x3); - double v = 2 / (x3 + x2 - x1); - double value = 0; - if (x < x1) { - double a = v / e0; - value = 0.5 * a * x * x; - } else if (x > x2) { - double a = v / e1; - value = 1 - 0.5 * a * (x3 - x) * (x3 - x); - } else { - double c = -0.5 * v * e0; - value = x * v + c; - } - return (1 - value) * k0.m_value + value * k1.m_value; +inline double getEaseInOutValue(const TActualDoubleKeyframe &k0, + const TActualDoubleKeyframe &k1, double frame, + bool percentage) { + double x3 = k1.m_frame - k0.m_frame; + if (x3 <= 0.0) return k0.m_value; + double x = frame - k0.m_frame; + if (x <= 0) + return k0.m_value; + else if (x >= x3) + return k1.m_value; + double e0 = std::max(k0.m_speedOut.x, 0.0); + double e1 = std::max(-k1.m_speedIn.x, 0.0); + if (percentage) { + e0 *= x3 * 0.01; + e1 *= x3 * 0.01; + } + if (e0 + e1 >= x3) { + double x = tcrop((e0 + x3 - e1) / 2, 0.0, x3); + e0 = x; + e1 = x3 - x; + } + double x1 = e0, x2 = x3 - e1; + if (0 < x1 - x2 && x1 - x2 < 0.1e-5) + x1 = x2 = (x1 + x2) * 0.5; // against rounding problems + assert(0 <= x1 && x1 <= x2 && x2 <= x3); + double v = 2 / (x3 + x2 - x1); + double value = 0; + if (x < x1) { + double a = v / e0; + value = 0.5 * a * x * x; + } else if (x > x2) { + double a = v / e1; + value = 1 - 0.5 * a * (x3 - x) * (x3 - x); + } else { + double c = -0.5 * v * e0; + value = x * v + c; + } + return (1 - value) * k0.m_value + value * k1.m_value; } //--------------------------------------------------------- -inline double getExponentialValue( - const TActualDoubleKeyframe &k0, - const TActualDoubleKeyframe &k1, - double frame) -{ - double aFrame = k0.m_frame; - double bFrame = k1.m_frame; - double deltaX = bFrame - aFrame; - - double aValue = k0.m_value; - double bValue = k1.m_value; - - // if min(aValue,bValue)<=0 => error => linear - if (aValue <= 0 || bValue <= 0) - return getLinearValue(k0, k1, frame); - - double t = (frame - aFrame) / deltaX; - // if aValue error => linear + if (aValue <= 0 || bValue <= 0) return getLinearValue(k0, k1, frame); + + double t = (frame - aFrame) / deltaX; + // if aValue k0.m_frame) - t = rframe / (k1.m_frame - k0.m_frame); - TSyntax::Calculator *calculator = k0.m_expression.getCalculator(); - if (calculator) { - calculator->setUnit((const_cast(k0)).updateUnit(measure)); - return calculator->compute(t, frame + 1, rframe + 1); - } else if (measure) - return measure->getDefaultValue(); - else - return 0; +inline double getExpressionValue(const TActualDoubleKeyframe &k0, + const TActualDoubleKeyframe &k1, double frame, + const TMeasure *measure) { + double t = 0, rframe = frame - k0.m_frame; + if (k1.m_frame > k0.m_frame) t = rframe / (k1.m_frame - k0.m_frame); + TSyntax::Calculator *calculator = k0.m_expression.getCalculator(); + if (calculator) { + calculator->setUnit( + (const_cast(k0)).updateUnit(measure)); + return calculator->compute(t, frame + 1, rframe + 1); + } else if (measure) + return measure->getDefaultValue(); + else + return 0; } //--------------------------------------------------------- -inline double getSimilarShapeValue( - const TActualDoubleKeyframe &k0, - const TActualDoubleKeyframe &k1, - double frame, - const TMeasure *measure) -{ - double offset = k0.m_similarShapeOffset; - double rv0 = getExpressionValue(k0, k1, k0.m_frame + offset, measure); - double rv1 = getExpressionValue(k0, k1, k1.m_frame + offset, measure); - double rv = getExpressionValue(k0, k1, frame + offset, measure); - double v0 = k0.m_value; - double v1 = k1.m_value; - if (rv1 != rv0) - return v0 + (v1 - v0) * (rv - rv0) / (rv1 - rv0); - else if (measure) - return measure->getDefaultValue(); - else - return 0; +inline double getSimilarShapeValue(const TActualDoubleKeyframe &k0, + const TActualDoubleKeyframe &k1, + double frame, const TMeasure *measure) { + double offset = k0.m_similarShapeOffset; + double rv0 = getExpressionValue(k0, k1, k0.m_frame + offset, measure); + double rv1 = getExpressionValue(k0, k1, k1.m_frame + offset, measure); + double rv = getExpressionValue(k0, k1, frame + offset, measure); + double v0 = k0.m_value; + double v1 = k1.m_value; + if (rv1 != rv0) + return v0 + (v1 - v0) * (rv - rv0) / (rv1 - rv0); + else if (measure) + return measure->getDefaultValue(); + else + return 0; } //=================================================================== -class TDoubleParam::Imp -{ +class TDoubleParam::Imp { public: - const TSyntax::Grammar *m_grammar; - string m_measureName; - TMeasure *m_measure; - double m_defaultValue, m_minValue, m_maxValue; - DoubleKeyframeVector m_keyframes; - bool m_cycleEnabled; - - std::set m_observers; - - Imp(double v = 0.0) - : m_grammar(0), m_measureName(), m_measure(0), m_defaultValue(v), m_minValue(-(std::numeric_limits::max)()), m_maxValue((std::numeric_limits::max)()), m_cycleEnabled(false) - { - } - - ~Imp() {} - - void copy(std::unique_ptr const& src) - { - m_grammar = src->m_grammar; - m_measureName = src->m_measureName; - m_measure = src->m_measure; - m_defaultValue = src->m_defaultValue; - m_minValue = src->m_minValue; - m_maxValue = src->m_maxValue; - m_keyframes = src->m_keyframes; - m_cycleEnabled = src->m_cycleEnabled; - } - - void notify(const TParamChange &change) - { - std::set::iterator it = m_observers.begin(); - for (; it != m_observers.end(); ++it) - (*it)->onChange(change); - } - - double getValue(int segmentIndex, double frame); - double getSpeed(int segmentIndex, double frame); - TPointD getSpeedIn(int kIndex); - TPointD getSpeedOut(int kIndex); + const TSyntax::Grammar *m_grammar; + string m_measureName; + TMeasure *m_measure; + double m_defaultValue, m_minValue, m_maxValue; + DoubleKeyframeVector m_keyframes; + bool m_cycleEnabled; + + std::set m_observers; + + Imp(double v = 0.0) + : m_grammar(0) + , m_measureName() + , m_measure(0) + , m_defaultValue(v) + , m_minValue(-(std::numeric_limits::max)()) + , m_maxValue((std::numeric_limits::max)()) + , m_cycleEnabled(false) {} + + ~Imp() {} + + void copy(std::unique_ptr const &src) { + m_grammar = src->m_grammar; + m_measureName = src->m_measureName; + m_measure = src->m_measure; + m_defaultValue = src->m_defaultValue; + m_minValue = src->m_minValue; + m_maxValue = src->m_maxValue; + m_keyframes = src->m_keyframes; + m_cycleEnabled = src->m_cycleEnabled; + } + + void notify(const TParamChange &change) { + std::set::iterator it = m_observers.begin(); + for (; it != m_observers.end(); ++it) (*it)->onChange(change); + } + + double getValue(int segmentIndex, double frame); + double getSpeed(int segmentIndex, double frame); + TPointD getSpeedIn(int kIndex); + TPointD getSpeedOut(int kIndex); }; //--------------------------------------------------------- -double TDoubleParam::Imp::getValue(int segmentIndex, double frame) -{ - assert(0 <= segmentIndex && segmentIndex + 1 < (int)m_keyframes.size()); - const TActualDoubleKeyframe &k0 = m_keyframes[segmentIndex]; - const TActualDoubleKeyframe &k1 = m_keyframes[segmentIndex + 1]; - - double value = m_defaultValue; - bool convertUnit = false; - switch (k0.m_type) { - case TDoubleKeyframe::Constant: - value = getConstantValue(k0, k1, frame); - break; - case TDoubleKeyframe::Linear: - value = getLinearValue(k0, k1, frame); - break; - case TDoubleKeyframe::SpeedInOut: - value = getSpeedInOutValue(k0, k1, getSpeedOut(segmentIndex), getSpeedIn(segmentIndex + 1), frame); - break; - case TDoubleKeyframe::EaseInOut: - value = getEaseInOutValue(k0, k1, frame, false); - break; - case TDoubleKeyframe::EaseInOutPercentage: - value = getEaseInOutValue(k0, k1, frame, true); - break; - case TDoubleKeyframe::Exponential: - value = getExponentialValue(k0, k1, frame); - break; - case TDoubleKeyframe::Expression: - value = getExpressionValue(k0, k1, frame, m_measure); - convertUnit = true; - break; - case TDoubleKeyframe::File: - value = k0.m_fileData.getValue(frame, m_defaultValue); - convertUnit = true; - break; - case TDoubleKeyframe::SimilarShape: - value = getSimilarShapeValue(k0, k1, frame, m_measure); - break; - } - if (convertUnit) - value = k0.convertFrom(m_measure, value); - return value; +double TDoubleParam::Imp::getValue(int segmentIndex, double frame) { + assert(0 <= segmentIndex && segmentIndex + 1 < (int)m_keyframes.size()); + const TActualDoubleKeyframe &k0 = m_keyframes[segmentIndex]; + const TActualDoubleKeyframe &k1 = m_keyframes[segmentIndex + 1]; + + double value = m_defaultValue; + bool convertUnit = false; + switch (k0.m_type) { + case TDoubleKeyframe::Constant: + value = getConstantValue(k0, k1, frame); + break; + case TDoubleKeyframe::Linear: + value = getLinearValue(k0, k1, frame); + break; + case TDoubleKeyframe::SpeedInOut: + value = getSpeedInOutValue(k0, k1, getSpeedOut(segmentIndex), + getSpeedIn(segmentIndex + 1), frame); + break; + case TDoubleKeyframe::EaseInOut: + value = getEaseInOutValue(k0, k1, frame, false); + break; + case TDoubleKeyframe::EaseInOutPercentage: + value = getEaseInOutValue(k0, k1, frame, true); + break; + case TDoubleKeyframe::Exponential: + value = getExponentialValue(k0, k1, frame); + break; + case TDoubleKeyframe::Expression: + value = getExpressionValue(k0, k1, frame, m_measure); + convertUnit = true; + break; + case TDoubleKeyframe::File: + value = k0.m_fileData.getValue(frame, m_defaultValue); + convertUnit = true; + break; + case TDoubleKeyframe::SimilarShape: + value = getSimilarShapeValue(k0, k1, frame, m_measure); + break; + } + if (convertUnit) value = k0.convertFrom(m_measure, value); + return value; } //--------------------------------------------------------- -double TDoubleParam::Imp::getSpeed(int segmentIndex, double frame) -{ - const double h = 0.00001; - return (getValue(segmentIndex, frame + h) - getValue(segmentIndex, frame - h)) / (2 * h); +double TDoubleParam::Imp::getSpeed(int segmentIndex, double frame) { + const double h = 0.00001; + return (getValue(segmentIndex, frame + h) - + getValue(segmentIndex, frame - h)) / + (2 * h); } //--------------------------------------------------------- -TPointD TDoubleParam::Imp::getSpeedIn(int kIndex) -{ - assert(1 <= kIndex && kIndex < (int)m_keyframes.size()); - const TActualDoubleKeyframe &kf0 = m_keyframes[kIndex - 1]; - const TActualDoubleKeyframe &kf1 = m_keyframes[kIndex]; - assert(kf0.m_type == TDoubleKeyframe::SpeedInOut); - if (!kf1.m_linkedHandles) - return kf1.m_speedIn; - TPointD speedIn = kf1.m_speedIn; - if (kIndex + 1 >= (int)m_keyframes.size()) { - // speedIn.y = 0; - } else { - if (kf1.m_type != TDoubleKeyframe::SpeedInOut && - (kf1.m_type != TDoubleKeyframe::Expression || !kf1.m_expression.isCycling())) { - double speed = getSpeed(kIndex, kf1.m_frame); - speedIn.y = speedIn.x * speed; - } - } - return speedIn; +TPointD TDoubleParam::Imp::getSpeedIn(int kIndex) { + assert(1 <= kIndex && kIndex < (int)m_keyframes.size()); + const TActualDoubleKeyframe &kf0 = m_keyframes[kIndex - 1]; + const TActualDoubleKeyframe &kf1 = m_keyframes[kIndex]; + assert(kf0.m_type == TDoubleKeyframe::SpeedInOut); + if (!kf1.m_linkedHandles) return kf1.m_speedIn; + TPointD speedIn = kf1.m_speedIn; + if (kIndex + 1 >= (int)m_keyframes.size()) { + // speedIn.y = 0; + } else { + if (kf1.m_type != TDoubleKeyframe::SpeedInOut && + (kf1.m_type != TDoubleKeyframe::Expression || + !kf1.m_expression.isCycling())) { + double speed = getSpeed(kIndex, kf1.m_frame); + speedIn.y = speedIn.x * speed; + } + } + return speedIn; } //--------------------------------------------------------- -TPointD TDoubleParam::Imp::getSpeedOut(int kIndex) -{ - assert(0 <= kIndex && kIndex < (int)m_keyframes.size()); - const TDoubleKeyframe &kf1 = m_keyframes[kIndex]; - assert(kf1.m_type == TDoubleKeyframe::SpeedInOut); - if (!kf1.m_linkedHandles) - return kf1.m_speedOut; - TPointD speedOut = kf1.m_speedOut; - if (kIndex == 0) { - // speedOut.y = 0; - } else { - const TDoubleKeyframe &kf0 = m_keyframes[kIndex - 1]; - if (kf0.m_type != TDoubleKeyframe::SpeedInOut) { - double speed = getSpeed(kIndex - 1, kf1.m_frame); - speedOut.y = speedOut.x * speed; - } - } - return speedOut; +TPointD TDoubleParam::Imp::getSpeedOut(int kIndex) { + assert(0 <= kIndex && kIndex < (int)m_keyframes.size()); + const TDoubleKeyframe &kf1 = m_keyframes[kIndex]; + assert(kf1.m_type == TDoubleKeyframe::SpeedInOut); + if (!kf1.m_linkedHandles) return kf1.m_speedOut; + TPointD speedOut = kf1.m_speedOut; + if (kIndex == 0) { + // speedOut.y = 0; + } else { + const TDoubleKeyframe &kf0 = m_keyframes[kIndex - 1]; + if (kf0.m_type != TDoubleKeyframe::SpeedInOut) { + double speed = getSpeed(kIndex - 1, kf1.m_frame); + speedOut.y = speedOut.x * speed; + } + } + return speedOut; } //--------------------------------------------------------- -TPointD TDoubleParam::getSpeedIn(int kIndex) const { return m_imp->getSpeedIn(kIndex); } -TPointD TDoubleParam::getSpeedOut(int kIndex) const { return m_imp->getSpeedOut(kIndex); } +TPointD TDoubleParam::getSpeedIn(int kIndex) const { + return m_imp->getSpeedIn(kIndex); +} +TPointD TDoubleParam::getSpeedOut(int kIndex) const { + return m_imp->getSpeedOut(kIndex); +} //========================================================= @@ -486,842 +450,793 @@ PERSIST_IDENTIFIER(TDoubleParam, "doubleParam") //--------------------------------------------------------- -TDoubleParam::TDoubleParam(double v) - : m_imp(new TDoubleParam::Imp(v)) -{ -} +TDoubleParam::TDoubleParam(double v) : m_imp(new TDoubleParam::Imp(v)) {} //--------------------------------------------------------- TDoubleParam::TDoubleParam(const TDoubleParam &src) - : TParam(src.getName()), m_imp(new TDoubleParam::Imp()) -{ - m_imp->copy(src.m_imp); + : TParam(src.getName()), m_imp(new TDoubleParam::Imp()) { + m_imp->copy(src.m_imp); } //--------------------------------------------------------- -TDoubleParam::~TDoubleParam() -{ -} +TDoubleParam::~TDoubleParam() {} //--------------------------------------------------------- -TDoubleParam &TDoubleParam::operator=(const TDoubleParam &dp) -{ - setName(dp.getName()); - m_imp->copy(dp.m_imp); - return *this; +TDoubleParam &TDoubleParam::operator=(const TDoubleParam &dp) { + setName(dp.getName()); + m_imp->copy(dp.m_imp); + return *this; } //--------------------------------------------------------- -void TDoubleParam::copy(TParam *src) -{ - TDoubleParam *p = dynamic_cast(src); - if (!p) - throw TException("invalid source for copy"); - setName(src->getName()); - m_imp->copy(p->m_imp); +void TDoubleParam::copy(TParam *src) { + TDoubleParam *p = dynamic_cast(src); + if (!p) throw TException("invalid source for copy"); + setName(src->getName()); + m_imp->copy(p->m_imp); - m_imp->notify(TParamChange(this, 0, 0, true, false, false)); + m_imp->notify(TParamChange(this, 0, 0, true, false, false)); } //--------------------------------------------------------- -void TDoubleParam::setValueRange(double min, double max, double step) -{ - if (min > max) - min = max; +void TDoubleParam::setValueRange(double min, double max, double step) { + if (min > max) min = max; - m_imp->m_minValue = min; - m_imp->m_maxValue = max; - // m_imp->m_valueStep = step; + m_imp->m_minValue = min; + m_imp->m_maxValue = max; + // m_imp->m_valueStep = step; } //--------------------------------------------------------- -bool TDoubleParam::getValueRange(double &min, double &max, double &step) const -{ - min = m_imp->m_minValue; - max = m_imp->m_maxValue; - step = 1; // m_imp->m_valueStep; - return min < max; +bool TDoubleParam::getValueRange(double &min, double &max, double &step) const { + min = m_imp->m_minValue; + max = m_imp->m_maxValue; + step = 1; // m_imp->m_valueStep; + return min < max; } //--------------------------------------------------------- -double TDoubleParam::getDefaultValue() const -{ - assert(m_imp); - return m_imp->m_defaultValue; +double TDoubleParam::getDefaultValue() const { + assert(m_imp); + return m_imp->m_defaultValue; } //--------------------------------------------------------- -void TDoubleParam::enableCycle(bool enabled) -{ - m_imp->m_cycleEnabled = enabled; +void TDoubleParam::enableCycle(bool enabled) { + m_imp->m_cycleEnabled = enabled; - m_imp->notify(TParamChange(this, 0, 0, true, false, false)); + m_imp->notify(TParamChange(this, 0, 0, true, false, false)); } //--------------------------------------------------------- -bool TDoubleParam::isCycleEnabled() const -{ - return m_imp->m_cycleEnabled; -} +bool TDoubleParam::isCycleEnabled() const { return m_imp->m_cycleEnabled; } //========================================================= //========================================================= -double TDoubleParam::getValue(double frame, bool leftmost) const -{ - double value = 0; - assert(m_imp); - const DoubleKeyframeVector &keyframes = m_imp->m_keyframes; - if (keyframes.empty()) { - // no keyframes: return the default value - value = m_imp->m_defaultValue; - } else if (keyframes.size() == 1) { - // a single keyframe. Type must be keyframe based (no expression/file) - value = keyframes[0].m_value; - } else { - // keyframes range is [f0,f1] - double f0 = keyframes.begin()->m_frame; - double f1 = keyframes.back().m_frame; - if (frame < f0) - frame = f0; - else if (frame > f1 && !m_imp->m_cycleEnabled) - frame = f1; - double valueOffset = 0; - - if (m_imp->m_cycleEnabled) { - double dist = (f1 - f0); - double dvalue = keyframes.back().m_value - keyframes.begin()->m_value; - while (frame >= f1) { - if (frame != f1 || !leftmost) { - frame -= dist; - valueOffset += dvalue; - } else - break; - } - } - - // frame is in [f0,f1] - assert(f0 <= frame && frame <= f1); - - DoubleKeyframeVector::const_iterator b; - b = std::lower_bound(keyframes.begin(), keyframes.end(), TDoubleKeyframe(frame)); - assert(b != keyframes.end()); - DoubleKeyframeVector::const_iterator a; - if (b->m_frame == frame && (b + 1) != keyframes.end()) { - a = b; - b++; - } else { - assert(b != keyframes.begin()); - a = b - 1; - } - - if (leftmost && frame - a->m_frame < 0.00001 && a != keyframes.begin()) { - a--; - b--; - } - - // segment (a,b) contains frame - assert(a != keyframes.end()); - assert(b != keyframes.end()); - assert(a->m_frame <= frame); - assert(b->m_frame >= frame); - - int kIndex = std::distance(keyframes.begin(), a); - - vector tmpKeyframe(3); - - // if segment is keyframe based .... - if (TDoubleKeyframe::isKeyframeBased(a->m_type)) { - // .. and next segment is not then update the b value - if ((b + 1) != keyframes.end() && !TDoubleKeyframe::isKeyframeBased(b->m_type)) { - tmpKeyframe[0] = *b; - if (b->m_type != TDoubleKeyframe::Expression || !b->m_expression.isCycling()) - tmpKeyframe[0].m_value = getValue(b->m_frame); - b = tmpKeyframe.begin(); - } - // .. and/or if prev segment is not then update the a value - if (a != keyframes.begin() && !TDoubleKeyframe::isKeyframeBased(a[-1].m_type)) { - tmpKeyframe[1] = *a; - tmpKeyframe[1].m_value = getValue(a->m_frame, true); - a = tmpKeyframe.begin() + 1; - } - } - - if (a->m_step > 1) { - tmpKeyframe[2] = *b; - b = tmpKeyframe.begin() + 2; - - int relPos = tfloor(b->m_frame - a->m_frame), step = std::min(a->m_step, relPos); - - tmpKeyframe[2].m_frame = a->m_frame + tfloor(relPos, step); - if (frame > b->m_frame) - frame = b->m_frame; - - frame = a->m_frame + tfloor(tfloor(frame - a->m_frame), step); - } - - assert(0 <= kIndex && kIndex + 1 < (int)m_imp->m_keyframes.size()); - value = m_imp->m_defaultValue; - bool convertUnit = false; - switch (a->m_type) { - case TDoubleKeyframe::Constant: - value = getConstantValue(*a, *b, frame); - break; - case TDoubleKeyframe::Linear: - value = getLinearValue(*a, *b, frame); - break; - case TDoubleKeyframe::SpeedInOut: - value = getSpeedInOutValue(*a, *b, getSpeedOut(kIndex), getSpeedIn(kIndex + 1), frame); - break; - case TDoubleKeyframe::EaseInOut: - value = getEaseInOutValue(*a, *b, frame, false); - break; - case TDoubleKeyframe::EaseInOutPercentage: - value = getEaseInOutValue(*a, *b, frame, true); - break; - case TDoubleKeyframe::Exponential: - value = getExponentialValue(*a, *b, frame); - break; - case TDoubleKeyframe::Expression: - value = getExpressionValue(*a, *b, frame, m_imp->m_measure); - convertUnit = true; - break; - case TDoubleKeyframe::File: - value = a->m_fileData.getValue(frame, m_imp->m_defaultValue); - convertUnit = true; - break; - case TDoubleKeyframe::SimilarShape: - value = getSimilarShapeValue(*a, *b, frame, m_imp->m_measure); - // convertUnit = true; - break; - - default: - value = 0.0; - } - value += valueOffset; - if (convertUnit) - value = a->convertFrom(m_imp->m_measure, value); - } - - //if (cropped) - // value = tcrop(value, m_imp->m_minValue, m_imp->m_maxValue); - return value; +double TDoubleParam::getValue(double frame, bool leftmost) const { + double value = 0; + assert(m_imp); + const DoubleKeyframeVector &keyframes = m_imp->m_keyframes; + if (keyframes.empty()) { + // no keyframes: return the default value + value = m_imp->m_defaultValue; + } else if (keyframes.size() == 1) { + // a single keyframe. Type must be keyframe based (no expression/file) + value = keyframes[0].m_value; + } else { + // keyframes range is [f0,f1] + double f0 = keyframes.begin()->m_frame; + double f1 = keyframes.back().m_frame; + if (frame < f0) + frame = f0; + else if (frame > f1 && !m_imp->m_cycleEnabled) + frame = f1; + double valueOffset = 0; + + if (m_imp->m_cycleEnabled) { + double dist = (f1 - f0); + double dvalue = keyframes.back().m_value - keyframes.begin()->m_value; + while (frame >= f1) { + if (frame != f1 || !leftmost) { + frame -= dist; + valueOffset += dvalue; + } else + break; + } + } + + // frame is in [f0,f1] + assert(f0 <= frame && frame <= f1); + + DoubleKeyframeVector::const_iterator b; + b = std::lower_bound(keyframes.begin(), keyframes.end(), + TDoubleKeyframe(frame)); + assert(b != keyframes.end()); + DoubleKeyframeVector::const_iterator a; + if (b->m_frame == frame && (b + 1) != keyframes.end()) { + a = b; + b++; + } else { + assert(b != keyframes.begin()); + a = b - 1; + } + + if (leftmost && frame - a->m_frame < 0.00001 && a != keyframes.begin()) { + a--; + b--; + } + + // segment (a,b) contains frame + assert(a != keyframes.end()); + assert(b != keyframes.end()); + assert(a->m_frame <= frame); + assert(b->m_frame >= frame); + + int kIndex = std::distance(keyframes.begin(), a); + + vector tmpKeyframe(3); + + // if segment is keyframe based .... + if (TDoubleKeyframe::isKeyframeBased(a->m_type)) { + // .. and next segment is not then update the b value + if ((b + 1) != keyframes.end() && + !TDoubleKeyframe::isKeyframeBased(b->m_type)) { + tmpKeyframe[0] = *b; + if (b->m_type != TDoubleKeyframe::Expression || + !b->m_expression.isCycling()) + tmpKeyframe[0].m_value = getValue(b->m_frame); + b = tmpKeyframe.begin(); + } + // .. and/or if prev segment is not then update the a value + if (a != keyframes.begin() && + !TDoubleKeyframe::isKeyframeBased(a[-1].m_type)) { + tmpKeyframe[1] = *a; + tmpKeyframe[1].m_value = getValue(a->m_frame, true); + a = tmpKeyframe.begin() + 1; + } + } + + if (a->m_step > 1) { + tmpKeyframe[2] = *b; + b = tmpKeyframe.begin() + 2; + + int relPos = tfloor(b->m_frame - a->m_frame), + step = std::min(a->m_step, relPos); + + tmpKeyframe[2].m_frame = a->m_frame + tfloor(relPos, step); + if (frame > b->m_frame) frame = b->m_frame; + + frame = a->m_frame + tfloor(tfloor(frame - a->m_frame), step); + } + + assert(0 <= kIndex && kIndex + 1 < (int)m_imp->m_keyframes.size()); + value = m_imp->m_defaultValue; + bool convertUnit = false; + switch (a->m_type) { + case TDoubleKeyframe::Constant: + value = getConstantValue(*a, *b, frame); + break; + case TDoubleKeyframe::Linear: + value = getLinearValue(*a, *b, frame); + break; + case TDoubleKeyframe::SpeedInOut: + value = getSpeedInOutValue(*a, *b, getSpeedOut(kIndex), + getSpeedIn(kIndex + 1), frame); + break; + case TDoubleKeyframe::EaseInOut: + value = getEaseInOutValue(*a, *b, frame, false); + break; + case TDoubleKeyframe::EaseInOutPercentage: + value = getEaseInOutValue(*a, *b, frame, true); + break; + case TDoubleKeyframe::Exponential: + value = getExponentialValue(*a, *b, frame); + break; + case TDoubleKeyframe::Expression: + value = getExpressionValue(*a, *b, frame, m_imp->m_measure); + convertUnit = true; + break; + case TDoubleKeyframe::File: + value = a->m_fileData.getValue(frame, m_imp->m_defaultValue); + convertUnit = true; + break; + case TDoubleKeyframe::SimilarShape: + value = getSimilarShapeValue(*a, *b, frame, m_imp->m_measure); + // convertUnit = true; + break; + + default: + value = 0.0; + } + value += valueOffset; + if (convertUnit) value = a->convertFrom(m_imp->m_measure, value); + } + + // if (cropped) + // value = tcrop(value, m_imp->m_minValue, m_imp->m_maxValue); + return value; } //--------------------------------------------------------- -bool TDoubleParam::setValue(double frame, double value) -{ - assert(m_imp); - DoubleKeyframeVector &keyframes = m_imp->m_keyframes; - DoubleKeyframeVector::iterator it; - TActualDoubleKeyframe k(frame); - it = std::lower_bound(keyframes.begin(), keyframes.end(), k); - int index = 0; - bool created = false; - /*-- キーフレームが見つかった場合 --*/ - if (it != keyframes.end() && it->m_frame == frame) { - // changing a keyframe value - index = std::distance(keyframes.begin(), it); - TActualDoubleKeyframe oldKeyframe = *it; - if (oldKeyframe.m_type == TDoubleKeyframe::Expression || - oldKeyframe.m_type == TDoubleKeyframe::File) - return false; - - it->m_value = value; - - m_imp->notify(TParamChange(this, 0, 0, true, false, false)); - } - /*-- セグメントの部分なので、新たにキーフレームを作る --*/ - else { - assert(it == keyframes.end() || it->m_frame > frame); - - // can't change value in a file/expression segment - if (it != keyframes.end() && it > keyframes.begin() && - ((it - 1)->m_type == TDoubleKeyframe::Expression || - (it - 1)->m_type == TDoubleKeyframe::File)) - return false; - - // inserting a new keyframe - k.m_value = value; - k.m_isKeyframe = true; - k.m_expression.setGrammar(m_imp->m_grammar); - k.m_expression.setOwnerParameter(this); - it = keyframes.insert(it, k); - if (it == keyframes.begin()) - it->m_prevType = TDoubleKeyframe::None; - else { - it->m_prevType = it[-1].m_type; - /*-- FxGuiでSegment内にKeyを打った場合は、Step値も引き継ぐ --*/ - it->m_step = it[-1].m_step; - } - if (it + 1 != keyframes.end()) - it[1].m_prevType = it->m_type; - - index = std::distance(keyframes.begin(), it); - - m_imp->notify(TParamChange(this, 0, 0, true, false, false)); - created = true; - } - assert(0 == index || keyframes[index - 1].m_frame < keyframes[index].m_frame); - assert(getKeyframeCount() - 1 == index || keyframes[index + 1].m_frame > keyframes[index].m_frame); - - return created; +bool TDoubleParam::setValue(double frame, double value) { + assert(m_imp); + DoubleKeyframeVector &keyframes = m_imp->m_keyframes; + DoubleKeyframeVector::iterator it; + TActualDoubleKeyframe k(frame); + it = std::lower_bound(keyframes.begin(), keyframes.end(), k); + int index = 0; + bool created = false; + /*-- キーフレームが見つかった場合 --*/ + if (it != keyframes.end() && it->m_frame == frame) { + // changing a keyframe value + index = std::distance(keyframes.begin(), it); + TActualDoubleKeyframe oldKeyframe = *it; + if (oldKeyframe.m_type == TDoubleKeyframe::Expression || + oldKeyframe.m_type == TDoubleKeyframe::File) + return false; + + it->m_value = value; + + m_imp->notify(TParamChange(this, 0, 0, true, false, false)); + } + /*-- セグメントの部分なので、新たにキーフレームを作る --*/ + else { + assert(it == keyframes.end() || it->m_frame > frame); + + // can't change value in a file/expression segment + if (it != keyframes.end() && it > keyframes.begin() && + ((it - 1)->m_type == TDoubleKeyframe::Expression || + (it - 1)->m_type == TDoubleKeyframe::File)) + return false; + + // inserting a new keyframe + k.m_value = value; + k.m_isKeyframe = true; + k.m_expression.setGrammar(m_imp->m_grammar); + k.m_expression.setOwnerParameter(this); + it = keyframes.insert(it, k); + if (it == keyframes.begin()) + it->m_prevType = TDoubleKeyframe::None; + else { + it->m_prevType = it[-1].m_type; + /*-- FxGuiでSegment内にKeyを打った場合は、Step値も引き継ぐ --*/ + it->m_step = it[-1].m_step; + } + if (it + 1 != keyframes.end()) it[1].m_prevType = it->m_type; + + index = std::distance(keyframes.begin(), it); + + m_imp->notify(TParamChange(this, 0, 0, true, false, false)); + created = true; + } + assert(0 == index || keyframes[index - 1].m_frame < keyframes[index].m_frame); + assert(getKeyframeCount() - 1 == index || + keyframes[index + 1].m_frame > keyframes[index].m_frame); + + return created; } //--------------------------------------------------------- -void TDoubleParam::setKeyframe(int index, const TDoubleKeyframe &k) -{ - DoubleKeyframeVector &keyframes = m_imp->m_keyframes; - assert(0 <= index && index < (int)keyframes.size()); +void TDoubleParam::setKeyframe(int index, const TDoubleKeyframe &k) { + DoubleKeyframeVector &keyframes = m_imp->m_keyframes; + assert(0 <= index && index < (int)keyframes.size()); - TActualDoubleKeyframe &dst = keyframes[index]; - TActualDoubleKeyframe oldKeyframe = dst; + TActualDoubleKeyframe &dst = keyframes[index]; + TActualDoubleKeyframe oldKeyframe = dst; - (TDoubleKeyframe &)dst = k; - dst.updateUnit(m_imp->m_measure); + (TDoubleKeyframe &)dst = k; + dst.updateUnit(m_imp->m_measure); - if (dst.m_type == TDoubleKeyframe::Expression || dst.m_type == TDoubleKeyframe::SimilarShape) - dst.m_expression.setText(dst.m_expressionText); - if (dst.m_type == TDoubleKeyframe::File) - dst.m_fileData.setParams(dst.m_fileParams); + if (dst.m_type == TDoubleKeyframe::Expression || + dst.m_type == TDoubleKeyframe::SimilarShape) + dst.m_expression.setText(dst.m_expressionText); + if (dst.m_type == TDoubleKeyframe::File) + dst.m_fileData.setParams(dst.m_fileParams); - m_imp->notify(TParamChange(this, 0, 0, true, false, false)); + m_imp->notify(TParamChange(this, 0, 0, true, false, false)); - assert(0 == index || keyframes[index - 1].m_frame < keyframes[index].m_frame); - assert(getKeyframeCount() - 1 == index || keyframes[index + 1].m_frame > keyframes[index].m_frame); - if (index == 0) - dst.m_prevType = TDoubleKeyframe::None; - else - dst.m_prevType = keyframes[index - 1].m_type; + assert(0 == index || keyframes[index - 1].m_frame < keyframes[index].m_frame); + assert(getKeyframeCount() - 1 == index || + keyframes[index + 1].m_frame > keyframes[index].m_frame); + if (index == 0) + dst.m_prevType = TDoubleKeyframe::None; + else + dst.m_prevType = keyframes[index - 1].m_type; } //--------------------------------------------------------- -void TDoubleParam::setKeyframes(const std::map &ks) -{ - DoubleKeyframeVector &keyframes = m_imp->m_keyframes; +void TDoubleParam::setKeyframes(const std::map &ks) { + DoubleKeyframeVector &keyframes = m_imp->m_keyframes; - std::map::const_iterator it; - for (it = ks.begin(); it != ks.end(); ++it) { - int index = it->first; - assert(0 <= index && index < (int)keyframes.size()); + std::map::const_iterator it; + for (it = ks.begin(); it != ks.end(); ++it) { + int index = it->first; + assert(0 <= index && index < (int)keyframes.size()); - TActualDoubleKeyframe oldKeyframe = keyframes[index]; - TActualDoubleKeyframe &dst = keyframes[index]; + TActualDoubleKeyframe oldKeyframe = keyframes[index]; + TActualDoubleKeyframe &dst = keyframes[index]; - (TDoubleKeyframe &)dst = it->second; - dst.updateUnit(m_imp->m_measure); + (TDoubleKeyframe &)dst = it->second; + dst.updateUnit(m_imp->m_measure); - if (dst.m_type == TDoubleKeyframe::Expression || dst.m_type == TDoubleKeyframe::SimilarShape) - dst.m_expression.setText(dst.m_expressionText); - if (dst.m_type == TDoubleKeyframe::File) - dst.m_fileData.setParams(dst.m_fileParams); - } - if (!keyframes.empty()) { - keyframes[0].m_prevType = TDoubleKeyframe::None; - for (int i = 1; i < (int)keyframes.size(); i++) - keyframes[i].m_prevType = keyframes[i - 1].m_type; - } + if (dst.m_type == TDoubleKeyframe::Expression || + dst.m_type == TDoubleKeyframe::SimilarShape) + dst.m_expression.setText(dst.m_expressionText); + if (dst.m_type == TDoubleKeyframe::File) + dst.m_fileData.setParams(dst.m_fileParams); + } + if (!keyframes.empty()) { + keyframes[0].m_prevType = TDoubleKeyframe::None; + for (int i = 1; i < (int)keyframes.size(); i++) + keyframes[i].m_prevType = keyframes[i - 1].m_type; + } - m_imp->notify(TParamChange(this, 0, 0, true, false, false)); + m_imp->notify(TParamChange(this, 0, 0, true, false, false)); #ifndef NDEBUG - for (int i = 0; i + 1 < (int)keyframes.size(); i++) { - assert(keyframes[i].m_frame <= keyframes[i + 1].m_frame); - } + for (int i = 0; i + 1 < (int)keyframes.size(); i++) { + assert(keyframes[i].m_frame <= keyframes[i + 1].m_frame); + } #endif } //--------------------------------------------------------- -void TDoubleParam::setKeyframe(const TDoubleKeyframe &k) -{ - DoubleKeyframeVector &keyframes = m_imp->m_keyframes; - DoubleKeyframeVector::iterator it; - it = std::lower_bound(keyframes.begin(), keyframes.end(), k); - if (it != keyframes.end() && it->m_frame == k.m_frame) { - // int index = std::distance(keyframes.begin(), it); - TActualDoubleKeyframe &dst = *it; - (TDoubleKeyframe &)dst = k; - dst.updateUnit(m_imp->m_measure); - } else { - it = keyframes.insert(it, TActualDoubleKeyframe(k)); - // int index = std::distance(keyframes.begin(), it); - //TDoubleKeyframe oldKeyframe = *it; - it->m_expression.setGrammar(m_imp->m_grammar); - it->m_expression.setOwnerParameter(this); - it->updateUnit(m_imp->m_measure); - } - it->m_isKeyframe = true; - - if (it->m_type == TDoubleKeyframe::Expression) - it->m_expression.setText(it->m_expressionText); - - if (it->m_type == TDoubleKeyframe::File) - it->m_fileData.setParams(it->m_fileParams); - - if (it == keyframes.begin()) - it->m_prevType = TDoubleKeyframe::None; - else - it->m_prevType = it[-1].m_type; - - m_imp->notify(TParamChange(this, 0, 0, true, false, false)); - - assert(it == keyframes.begin() || (it - 1)->m_frame < it->m_frame); - assert(it + 1 == keyframes.end() || (it + 1)->m_frame > it->m_frame); +void TDoubleParam::setKeyframe(const TDoubleKeyframe &k) { + DoubleKeyframeVector &keyframes = m_imp->m_keyframes; + DoubleKeyframeVector::iterator it; + it = std::lower_bound(keyframes.begin(), keyframes.end(), k); + if (it != keyframes.end() && it->m_frame == k.m_frame) { + // int index = std::distance(keyframes.begin(), it); + TActualDoubleKeyframe &dst = *it; + (TDoubleKeyframe &)dst = k; + dst.updateUnit(m_imp->m_measure); + } else { + it = keyframes.insert(it, TActualDoubleKeyframe(k)); + // int index = std::distance(keyframes.begin(), it); + // TDoubleKeyframe oldKeyframe = *it; + it->m_expression.setGrammar(m_imp->m_grammar); + it->m_expression.setOwnerParameter(this); + it->updateUnit(m_imp->m_measure); + } + it->m_isKeyframe = true; + + if (it->m_type == TDoubleKeyframe::Expression) + it->m_expression.setText(it->m_expressionText); + + if (it->m_type == TDoubleKeyframe::File) + it->m_fileData.setParams(it->m_fileParams); + + if (it == keyframes.begin()) + it->m_prevType = TDoubleKeyframe::None; + else + it->m_prevType = it[-1].m_type; + + m_imp->notify(TParamChange(this, 0, 0, true, false, false)); + + assert(it == keyframes.begin() || (it - 1)->m_frame < it->m_frame); + assert(it + 1 == keyframes.end() || (it + 1)->m_frame > it->m_frame); } //--------------------------------------------------------- -void TDoubleParam::setDefaultValue(double value) -{ - assert(m_imp); - if (m_imp->m_defaultValue != value) { - m_imp->m_defaultValue = value; - - // gmt, 19-6-2010; needed to get a notification in the FxParamsGraphicEditor (Camera Stand) - // when a param (without keyframes) is changed - m_imp->notify(TParamChange(this, 0, 0, true, false, false)); - } +void TDoubleParam::setDefaultValue(double value) { + assert(m_imp); + if (m_imp->m_defaultValue != value) { + m_imp->m_defaultValue = value; + + // gmt, 19-6-2010; needed to get a notification in the FxParamsGraphicEditor + // (Camera Stand) + // when a param (without keyframes) is changed + m_imp->notify(TParamChange(this, 0, 0, true, false, false)); + } } //--------------------------------------------------------- -bool TDoubleParam::isDefault() const -{ - return m_imp->m_keyframes.empty() && - // m_imp->m_type == Keyframes && - m_imp->m_defaultValue == 0; +bool TDoubleParam::isDefault() const { + return m_imp->m_keyframes.empty() && + // m_imp->m_type == Keyframes && + m_imp->m_defaultValue == 0; } //--------------------------------------------------------- -int TDoubleParam::getKeyframeCount() const -{ - return m_imp->m_keyframes.size(); -} +int TDoubleParam::getKeyframeCount() const { return m_imp->m_keyframes.size(); } //--------------------------------------------------------- -void TDoubleParam::getKeyframes(std::set &frames) const -{ - for (DoubleKeyframeVector::iterator it = m_imp->m_keyframes.begin(); - it != m_imp->m_keyframes.end(); ++it) - frames.insert(it->m_frame); +void TDoubleParam::getKeyframes(std::set &frames) const { + for (DoubleKeyframeVector::iterator it = m_imp->m_keyframes.begin(); + it != m_imp->m_keyframes.end(); ++it) + frames.insert(it->m_frame); } //--------------------------------------------------------- -bool TDoubleParam::hasKeyframes() const -{ - return !m_imp->m_keyframes.empty(); -} +bool TDoubleParam::hasKeyframes() const { return !m_imp->m_keyframes.empty(); } //--------------------------------------------------------- -const TDoubleKeyframe &TDoubleParam::getKeyframe(int index) const -{ - assert(0 <= index && index < (int)m_imp->m_keyframes.size()); - return m_imp->m_keyframes[index]; +const TDoubleKeyframe &TDoubleParam::getKeyframe(int index) const { + assert(0 <= index && index < (int)m_imp->m_keyframes.size()); + return m_imp->m_keyframes[index]; } //--------------------------------------------------------- -const TDoubleKeyframe &TDoubleParam::getKeyframeAt(double frame) const -{ - static TDoubleKeyframe k; - k = TDoubleKeyframe(); - int i = 0; - for (i = 0; i < (int)m_imp->m_keyframes.size(); i++) - if (m_imp->m_keyframes[i].m_frame >= frame) - break; - if (i < (int)m_imp->m_keyframes.size() && m_imp->m_keyframes[i].m_frame == frame) { - k = m_imp->m_keyframes[i]; - return k; - } - k.m_frame = frame; - k.m_value = getValue(frame); - k.m_isKeyframe = false; - return k; +const TDoubleKeyframe &TDoubleParam::getKeyframeAt(double frame) const { + static TDoubleKeyframe k; + k = TDoubleKeyframe(); + int i = 0; + for (i = 0; i < (int)m_imp->m_keyframes.size(); i++) + if (m_imp->m_keyframes[i].m_frame >= frame) break; + if (i < (int)m_imp->m_keyframes.size() && + m_imp->m_keyframes[i].m_frame == frame) { + k = m_imp->m_keyframes[i]; + return k; + } + k.m_frame = frame; + k.m_value = getValue(frame); + k.m_isKeyframe = false; + return k; } //--------------------------------------------------------- -bool TDoubleParam::isKeyframe(double frame) const -{ - return std::binary_search( - m_imp->m_keyframes.begin(), - m_imp->m_keyframes.end(), - TDoubleKeyframe(frame)); +bool TDoubleParam::isKeyframe(double frame) const { + return std::binary_search(m_imp->m_keyframes.begin(), + m_imp->m_keyframes.end(), TDoubleKeyframe(frame)); } //--------------------------------------------------------- -void TDoubleParam::deleteKeyframe(double frame) -{ - DoubleKeyframeVector &keyframes = m_imp->m_keyframes; - DoubleKeyframeVector::iterator it; - it = std::lower_bound(keyframes.begin(), keyframes.end(), - TDoubleKeyframe(frame)); - if (it == keyframes.end() || it->m_frame != frame) - return; - - TDoubleKeyframe::Type type = it->m_prevType; - it = m_imp->m_keyframes.erase(it); - if (it != keyframes.end()) - it->m_prevType = type; - - m_imp->notify(TParamChange(this, 0, 0, true, false, false)); +void TDoubleParam::deleteKeyframe(double frame) { + DoubleKeyframeVector &keyframes = m_imp->m_keyframes; + DoubleKeyframeVector::iterator it; + it = std::lower_bound(keyframes.begin(), keyframes.end(), + TDoubleKeyframe(frame)); + if (it == keyframes.end() || it->m_frame != frame) return; + + TDoubleKeyframe::Type type = it->m_prevType; + it = m_imp->m_keyframes.erase(it); + if (it != keyframes.end()) it->m_prevType = type; + + m_imp->notify(TParamChange(this, 0, 0, true, false, false)); } //--------------------------------------------------------- -void TDoubleParam::clearKeyframes() -{ - m_imp->m_keyframes.clear(); - m_imp->notify(TParamChange(this, 0, 0, true, false, false)); +void TDoubleParam::clearKeyframes() { + m_imp->m_keyframes.clear(); + m_imp->notify(TParamChange(this, 0, 0, true, false, false)); } //--------------------------------------------------------- -void TDoubleParam::assignKeyframe( - double frame, - const TParamP &src, double srcFrame, - bool changedOnly) -{ - TDoubleParamP dp = src; - if (!dp) - return; - double value = dp->getValue(srcFrame); - if (!changedOnly || getValue(frame) != value) - setValue(frame, value); +void TDoubleParam::assignKeyframe(double frame, const TParamP &src, + double srcFrame, bool changedOnly) { + TDoubleParamP dp = src; + if (!dp) return; + double value = dp->getValue(srcFrame); + if (!changedOnly || getValue(frame) != value) setValue(frame, value); } //--------------------------------------------------------- -int TDoubleParam::getClosestKeyframe(double frame) const -{ - DoubleKeyframeVector &keyframes = m_imp->m_keyframes; - typedef DoubleKeyframeVector::iterator Iterator; - Iterator it = std::lower_bound(keyframes.begin(), keyframes.end(), - TDoubleKeyframe(frame)); - if (it == keyframes.end()) { - // frame > k.m_frame per qualsiasi k. - // ritorna l'indice dell'ultimo keyframe (o -1 se l'array e' vuoto) - return keyframes.size() - 1; - } else { - int index = std::distance(keyframes.begin(), it); - if (it->m_frame == frame || index == 0) - return index; - else { - double nextFrame = it->m_frame; - double prevFrame = keyframes[index - 1].m_frame; - assert(prevFrame < frame && frame < nextFrame); - return (nextFrame - frame < frame - prevFrame) ? index : index - 1; - } - } +int TDoubleParam::getClosestKeyframe(double frame) const { + DoubleKeyframeVector &keyframes = m_imp->m_keyframes; + typedef DoubleKeyframeVector::iterator Iterator; + Iterator it = std::lower_bound(keyframes.begin(), keyframes.end(), + TDoubleKeyframe(frame)); + if (it == keyframes.end()) { + // frame > k.m_frame per qualsiasi k. + // ritorna l'indice dell'ultimo keyframe (o -1 se l'array e' vuoto) + return keyframes.size() - 1; + } else { + int index = std::distance(keyframes.begin(), it); + if (it->m_frame == frame || index == 0) + return index; + else { + double nextFrame = it->m_frame; + double prevFrame = keyframes[index - 1].m_frame; + assert(prevFrame < frame && frame < nextFrame); + return (nextFrame - frame < frame - prevFrame) ? index : index - 1; + } + } } //--------------------------------------------------------- -int TDoubleParam::getNextKeyframe(double frame) const -{ - TDoubleKeyframe k(frame); - typedef DoubleKeyframeVector::const_iterator Iterator; - Iterator it = std::upper_bound(m_imp->m_keyframes.begin(), m_imp->m_keyframes.end(), k); - if (it == m_imp->m_keyframes.end()) - return -1; - int index = std::distance(m_imp->m_keyframes.begin(), it); - if (it->m_frame == frame) { - ++index; - return index < getKeyframeCount() ? index : -1; - } - return index; +int TDoubleParam::getNextKeyframe(double frame) const { + TDoubleKeyframe k(frame); + typedef DoubleKeyframeVector::const_iterator Iterator; + Iterator it = + std::upper_bound(m_imp->m_keyframes.begin(), m_imp->m_keyframes.end(), k); + if (it == m_imp->m_keyframes.end()) return -1; + int index = std::distance(m_imp->m_keyframes.begin(), it); + if (it->m_frame == frame) { + ++index; + return index < getKeyframeCount() ? index : -1; + } + return index; } //--------------------------------------------------------- -int TDoubleParam::getPrevKeyframe(double frame) const -{ - TDoubleKeyframe k(frame); - typedef DoubleKeyframeVector::const_iterator Iterator; - Iterator it = std::lower_bound(m_imp->m_keyframes.begin(), m_imp->m_keyframes.end(), k); - if (it == m_imp->m_keyframes.end()) - return m_imp->m_keyframes.size() - 1; - int index = std::distance(m_imp->m_keyframes.begin(), it); - return index - 1; +int TDoubleParam::getPrevKeyframe(double frame) const { + TDoubleKeyframe k(frame); + typedef DoubleKeyframeVector::const_iterator Iterator; + Iterator it = + std::lower_bound(m_imp->m_keyframes.begin(), m_imp->m_keyframes.end(), k); + if (it == m_imp->m_keyframes.end()) return m_imp->m_keyframes.size() - 1; + int index = std::distance(m_imp->m_keyframes.begin(), it); + return index - 1; } //--------------------------------------------------------- -double TDoubleParam::keyframeIndexToFrame(int index) const -{ - assert(0 <= index && index < getKeyframeCount()); - return getKeyframe(index).m_frame; +double TDoubleParam::keyframeIndexToFrame(int index) const { + assert(0 <= index && index < getKeyframeCount()); + return getKeyframe(index).m_frame; } //--------------------------------------------------------- -void TDoubleParam::addObserver(TParamObserver *observer) -{ - m_imp->m_observers.insert(observer); +void TDoubleParam::addObserver(TParamObserver *observer) { + m_imp->m_observers.insert(observer); } //--------------------------------------------------------- -void TDoubleParam::removeObserver(TParamObserver *observer) -{ - m_imp->m_observers.erase(observer); +void TDoubleParam::removeObserver(TParamObserver *observer) { + m_imp->m_observers.erase(observer); } //--------------------------------------------------------- -const std::set &TDoubleParam::observers() const -{ - return m_imp->m_observers; +const std::set &TDoubleParam::observers() const { + return m_imp->m_observers; } //--------------------------------------------------------- -void TDoubleParam::loadData(TIStream &is) +void TDoubleParam::loadData(TIStream &is) { + string tagName; + /* +if(is.matchTag(tagName)) { - string tagName; - /* - if(is.matchTag(tagName)) - { - // nuovo formato (29 agosto 2005) - if(tagName!="type") throw TException("expected "); - int type = 0; - is >> type; - // m_imp->m_type = TDoubleParam::Type(type); - if(!is.matchEndTag()) throw TException(tagName + " : missing endtag"); - - - //if(!is.matchTag(tagName) || tagName != "default") throw TException("expected "); - //is >> m_imp->m_defaultValue; - //if(!is.matchEndTag()) throw TException(tagName + " : missing endtag"); - //if(!is.matchTag(tagName) || tagName != "default") throw TException("expected "); - +// nuovo formato (29 agosto 2005) +if(tagName!="type") throw TException("expected "); +int type = 0; +is >> type; +// m_imp->m_type = TDoubleParam::Type(type); +if(!is.matchEndTag()) throw TException(tagName + " : missing endtag"); + +//if(!is.matchTag(tagName) || tagName != "default") throw TException("expected +"); +//is >> m_imp->m_defaultValue; +//if(!is.matchEndTag()) throw TException(tagName + " : missing endtag"); +//if(!is.matchTag(tagName) || tagName != "default") throw TException("expected +"); + + +} +else +{ +// vecchio formato +is >> m_imp->m_defaultValue; +} +*/ + + m_imp->m_keyframes.clear(); + int oldType = -1; + while (is.matchTag(tagName)) { + if (tagName == "type") { + // (old) format 5.2. Since 6.0 param type is no used anymore + is >> oldType; + } else if (tagName == "default") { + is >> m_imp->m_defaultValue; + } else if (tagName == "cycle") { + string dummy; + is >> dummy; + m_imp->m_cycleEnabled = true; + // setExtrapolationAfter(Loop); + } else if (tagName == "k") { + // vecchio formato + if (oldType != 0) continue; + int linkStatus = 0; + TActualDoubleKeyframe k; + is >> k.m_frame >> k.m_value >> k.m_speedIn.x >> k.m_speedIn.y >> + k.m_speedOut.x >> k.m_speedOut.y >> linkStatus; + + k.m_isKeyframe = true; + k.m_linkedHandles = (linkStatus & 1) != 0; + + if ((linkStatus & 1) != 0) + k.m_type = TDoubleKeyframe::SpeedInOut; + else if ((linkStatus & 2) != 0 || (linkStatus & 4) != 0) + k.m_type = TDoubleKeyframe::EaseInOut; + else + k.m_type = TDoubleKeyframe::Linear; + k.m_expression.setGrammar(m_imp->m_grammar); + k.m_expression.setOwnerParameter(this); + k.m_prevType = m_imp->m_keyframes.empty() + ? TDoubleKeyframe::None + : m_imp->m_keyframes.back().m_type; + m_imp->m_keyframes.push_back(k); + } else if (tagName == "expr") { + // vecchio formato + if (oldType != 1) continue; + string text = is.getTagAttribute("text"); + string enabled = is.getTagAttribute("enabled"); + TDoubleKeyframe kk1, kk2; + kk1.m_frame = -1000; + kk2.m_frame = 1000; + kk1.m_isKeyframe = true; + kk2.m_isKeyframe = true; + kk1.m_expressionText = text; + kk2.m_expressionText = text; + kk1.m_type = TDoubleKeyframe::Expression; + kk2.m_type = TDoubleKeyframe::Expression; + TActualDoubleKeyframe k1(kk1); + TActualDoubleKeyframe k2(kk2); + k1.m_expression.setGrammar(m_imp->m_grammar); + k1.m_expression.setOwnerParameter(this); + k1.m_prevType = m_imp->m_keyframes.empty() + ? TDoubleKeyframe::None + : m_imp->m_keyframes.back().m_type; + k2.m_expression.setGrammar(m_imp->m_grammar); + k2.m_expression.setOwnerParameter(this); + k2.m_prevType = m_imp->m_keyframes.empty() + ? TDoubleKeyframe::None + : m_imp->m_keyframes.back().m_type; + m_imp->m_keyframes.push_back(k1); + m_imp->m_keyframes.push_back(k2); + continue; + } else if (tagName == "file") { + // vecchio formato + if (oldType != 2) continue; + TDoubleKeyframe::FileParams params; + params.m_path = TFilePath(is.getTagAttribute("path")); + params.m_fieldIndex = std::stoi(is.getTagAttribute("index")); + TActualDoubleKeyframe k1, k2; + k1.m_frame = -1000; + k2.m_frame = 1000; + k1.m_isKeyframe = true; + k2.m_isKeyframe = true; + k1.m_fileData.setParams(params); + k2.m_fileData.setParams(params); + k1.m_type = TDoubleKeyframe::File; + k2.m_type = TDoubleKeyframe::File; + k1.m_expression.setGrammar(m_imp->m_grammar); + k1.m_expression.setOwnerParameter(this); + k1.m_prevType = m_imp->m_keyframes.empty() + ? TDoubleKeyframe::None + : m_imp->m_keyframes.back().m_type; + k2.m_expression.setGrammar(m_imp->m_grammar); + k2.m_expression.setOwnerParameter(this); + k2.m_prevType = m_imp->m_keyframes.empty() + ? TDoubleKeyframe::None + : m_imp->m_keyframes.back().m_type; + m_imp->m_keyframes.push_back(k1); + m_imp->m_keyframes.push_back(k2); + continue; + } else if (tagName == "step") { + int step = 0; + is >> step; + // if(step>1) + // m_imp->m_frameStep = step; + } else if (tagName == "keyframes") { + while (!is.eos()) { + TDoubleKeyframe kk; + kk.loadData(is); + TActualDoubleKeyframe k(kk); + k.m_expression.setGrammar(m_imp->m_grammar); + k.m_expression.setOwnerParameter(this); + k.m_prevType = m_imp->m_keyframes.empty() + ? TDoubleKeyframe::None + : m_imp->m_keyframes.back().m_type; + m_imp->m_keyframes.push_back(k); + } + } else { + throw TException(tagName + " : unexpected tag"); } - else - { - // vecchio formato - is >> m_imp->m_defaultValue; + if (!is.matchEndTag()) throw TException(tagName + " : missing endtag"); + } + if (m_imp->m_keyframes.empty() && !is.eos()) { + // vecchio sistema (prima 16/1/2003) + while (!is.eos()) { + double t, v; + is >> t >> v; + m_imp->m_keyframes.push_back(TActualDoubleKeyframe(t, v)); } - */ - - m_imp->m_keyframes.clear(); - int oldType = -1; - while (is.matchTag(tagName)) { - if (tagName == "type") { - // (old) format 5.2. Since 6.0 param type is no used anymore - is >> oldType; - } else if (tagName == "default") { - is >> m_imp->m_defaultValue; - } else if (tagName == "cycle") { - string dummy; - is >> dummy; - m_imp->m_cycleEnabled = true; - //setExtrapolationAfter(Loop); - } else if (tagName == "k") { - // vecchio formato - if (oldType != 0) - continue; - int linkStatus = 0; - TActualDoubleKeyframe k; - is >> k.m_frame >> k.m_value >> k.m_speedIn.x >> k.m_speedIn.y >> k.m_speedOut.x >> k.m_speedOut.y >> linkStatus; - - k.m_isKeyframe = true; - k.m_linkedHandles = (linkStatus & 1) != 0; - - if ((linkStatus & 1) != 0) - k.m_type = TDoubleKeyframe::SpeedInOut; - else if ((linkStatus & 2) != 0 || (linkStatus & 4) != 0) - k.m_type = TDoubleKeyframe::EaseInOut; - else - k.m_type = TDoubleKeyframe::Linear; - k.m_expression.setGrammar(m_imp->m_grammar); - k.m_expression.setOwnerParameter(this); - k.m_prevType = m_imp->m_keyframes.empty() ? TDoubleKeyframe::None : m_imp->m_keyframes.back().m_type; - m_imp->m_keyframes.push_back(k); - } else if (tagName == "expr") { - // vecchio formato - if (oldType != 1) - continue; - string text = is.getTagAttribute("text"); - string enabled = is.getTagAttribute("enabled"); - TDoubleKeyframe kk1, kk2; - kk1.m_frame = -1000; - kk2.m_frame = 1000; - kk1.m_isKeyframe = true; - kk2.m_isKeyframe = true; - kk1.m_expressionText = text; - kk2.m_expressionText = text; - kk1.m_type = TDoubleKeyframe::Expression; - kk2.m_type = TDoubleKeyframe::Expression; - TActualDoubleKeyframe k1(kk1); - TActualDoubleKeyframe k2(kk2); - k1.m_expression.setGrammar(m_imp->m_grammar); - k1.m_expression.setOwnerParameter(this); - k1.m_prevType = m_imp->m_keyframes.empty() ? TDoubleKeyframe::None : m_imp->m_keyframes.back().m_type; - k2.m_expression.setGrammar(m_imp->m_grammar); - k2.m_expression.setOwnerParameter(this); - k2.m_prevType = m_imp->m_keyframes.empty() ? TDoubleKeyframe::None : m_imp->m_keyframes.back().m_type; - m_imp->m_keyframes.push_back(k1); - m_imp->m_keyframes.push_back(k2); - continue; - } else if (tagName == "file") { - // vecchio formato - if (oldType != 2) - continue; - TDoubleKeyframe::FileParams params; - params.m_path = TFilePath(is.getTagAttribute("path")); - params.m_fieldIndex = std::stoi(is.getTagAttribute("index")); - TActualDoubleKeyframe k1, k2; - k1.m_frame = -1000; - k2.m_frame = 1000; - k1.m_isKeyframe = true; - k2.m_isKeyframe = true; - k1.m_fileData.setParams(params); - k2.m_fileData.setParams(params); - k1.m_type = TDoubleKeyframe::File; - k2.m_type = TDoubleKeyframe::File; - k1.m_expression.setGrammar(m_imp->m_grammar); - k1.m_expression.setOwnerParameter(this); - k1.m_prevType = m_imp->m_keyframes.empty() ? TDoubleKeyframe::None : m_imp->m_keyframes.back().m_type; - k2.m_expression.setGrammar(m_imp->m_grammar); - k2.m_expression.setOwnerParameter(this); - k2.m_prevType = m_imp->m_keyframes.empty() ? TDoubleKeyframe::None : m_imp->m_keyframes.back().m_type; - m_imp->m_keyframes.push_back(k1); - m_imp->m_keyframes.push_back(k2); - continue; - } else if (tagName == "step") { - int step = 0; - is >> step; - //if(step>1) - // m_imp->m_frameStep = step; - } else if (tagName == "keyframes") { - while (!is.eos()) { - TDoubleKeyframe kk; - kk.loadData(is); - TActualDoubleKeyframe k(kk); - k.m_expression.setGrammar(m_imp->m_grammar); - k.m_expression.setOwnerParameter(this); - k.m_prevType = m_imp->m_keyframes.empty() ? TDoubleKeyframe::None : m_imp->m_keyframes.back().m_type; - m_imp->m_keyframes.push_back(k); - } - } else { - throw TException(tagName + " : unexpected tag"); - } - if (!is.matchEndTag()) - throw TException(tagName + " : missing endtag"); - } - if (m_imp->m_keyframes.empty() && !is.eos()) { - // vecchio sistema (prima 16/1/2003) - while (!is.eos()) { - double t, v; - is >> t >> v; - m_imp->m_keyframes.push_back(TActualDoubleKeyframe(t, v)); - } - if (!m_imp->m_keyframes.empty()) { - m_imp->m_keyframes[0].m_prevType = TDoubleKeyframe::None; - for (int i = 1; i < (int)m_imp->m_keyframes.size(); i++) - m_imp->m_keyframes[i].m_prevType = m_imp->m_keyframes[i - 1].m_type; - } - } - - m_imp->notify(TParamChange(this, 0, 0, true, false, false)); + if (!m_imp->m_keyframes.empty()) { + m_imp->m_keyframes[0].m_prevType = TDoubleKeyframe::None; + for (int i = 1; i < (int)m_imp->m_keyframes.size(); i++) + m_imp->m_keyframes[i].m_prevType = m_imp->m_keyframes[i - 1].m_type; + } + } + + m_imp->notify(TParamChange(this, 0, 0, true, false, false)); } //--------------------------------------------------------- -void TDoubleParam::saveData(TOStream &os) -{ - // os.child("type") << (int)m_imp->m_type; - os.child("default") << m_imp->m_defaultValue; - if (isCycleEnabled()) - os.child("cycle") << std::string("enabled"); - //if(getExtrapolationAfter() == Loop) - // os.child("cycle") << string("loop"); - if (!m_imp->m_keyframes.empty()) { - os.openChild("keyframes"); - DoubleKeyframeVector::const_iterator it; - for (it = m_imp->m_keyframes.begin(); it != m_imp->m_keyframes.end(); ++it) - it->saveData(os); - os.closeChild(); - } +void TDoubleParam::saveData(TOStream &os) { + // os.child("type") << (int)m_imp->m_type; + os.child("default") << m_imp->m_defaultValue; + if (isCycleEnabled()) os.child("cycle") << std::string("enabled"); + // if(getExtrapolationAfter() == Loop) + // os.child("cycle") << string("loop"); + if (!m_imp->m_keyframes.empty()) { + os.openChild("keyframes"); + DoubleKeyframeVector::const_iterator it; + for (it = m_imp->m_keyframes.begin(); it != m_imp->m_keyframes.end(); ++it) + it->saveData(os); + os.closeChild(); + } } //--------------------------------------------------------- -string TDoubleParam::getStreamTag() const -{ - return "doubleParam"; -} +string TDoubleParam::getStreamTag() const { return "doubleParam"; } //------------------------------------------------------------------- -string TDoubleParam::getValueAlias(double frame, int precision) -{ - return ::to_string(getValue(frame), precision); +string TDoubleParam::getValueAlias(double frame, int precision) { + return ::to_string(getValue(frame), precision); } //------------------------------------------------------------------- -void TDoubleParam::setGrammar(const TSyntax::Grammar *grammar) -{ - m_imp->m_grammar = grammar; - for (int i = 0; i < (int)m_imp->m_keyframes.size(); i++) - m_imp->m_keyframes[i].m_expression.setGrammar(grammar); +void TDoubleParam::setGrammar(const TSyntax::Grammar *grammar) { + m_imp->m_grammar = grammar; + for (int i = 0; i < (int)m_imp->m_keyframes.size(); i++) + m_imp->m_keyframes[i].m_expression.setGrammar(grammar); } //------------------------------------------------------------------- -const TSyntax::Grammar *TDoubleParam::getGrammar() const -{ - return m_imp->m_grammar; +const TSyntax::Grammar *TDoubleParam::getGrammar() const { + return m_imp->m_grammar; } //------------------------------------------------------------------- -void TDoubleParam::accept(TSyntax::CalculatorNodeVisitor &visitor) -{ - for (int i = 0; i < (int)m_imp->m_keyframes.size(); i++) - if (m_imp->m_keyframes[i].m_type == TDoubleKeyframe::Expression || m_imp->m_keyframes[i].m_type == TDoubleKeyframe::SimilarShape) - m_imp->m_keyframes[i].m_expression.accept(visitor); +void TDoubleParam::accept(TSyntax::CalculatorNodeVisitor &visitor) { + for (int i = 0; i < (int)m_imp->m_keyframes.size(); i++) + if (m_imp->m_keyframes[i].m_type == TDoubleKeyframe::Expression || + m_imp->m_keyframes[i].m_type == TDoubleKeyframe::SimilarShape) + m_imp->m_keyframes[i].m_expression.accept(visitor); } //------------------------------------------------------------------- -string TDoubleParam::getMeasureName() const -{ - return m_imp->m_measureName; -} +string TDoubleParam::getMeasureName() const { return m_imp->m_measureName; } //------------------------------------------------------------------- -void TDoubleParam::setMeasureName(string name) -{ - m_imp->m_measureName = name; - m_imp->m_measure = TMeasureManager::instance()->get(name); +void TDoubleParam::setMeasureName(string name) { + m_imp->m_measureName = name; + m_imp->m_measure = TMeasureManager::instance()->get(name); } //------------------------------------------------------------------- -TMeasure *TDoubleParam::getMeasure() const -{ - return m_imp->m_measure; -} +TMeasure *TDoubleParam::getMeasure() const { return m_imp->m_measure; } diff --git a/toonz/sources/common/tparam/tdoubleparamfile.cpp b/toonz/sources/common/tparam/tdoubleparamfile.cpp index f22dee1..05fce2f 100644 --- a/toonz/sources/common/tparam/tdoubleparamfile.cpp +++ b/toonz/sources/common/tparam/tdoubleparamfile.cpp @@ -4,140 +4,114 @@ #include "tfilepath_io.h" #include "tconvert.h" -namespace -{ +namespace { //--------------------------------------------------------- -bool parseDouble(double &value, char *&s) -{ - if (!(*s == '-' || *s == '.' || '0' <= *s && *s <= '9')) - return false; - char *t = s; - if (*s == '-') - s++; - while ('0' <= *s && *s <= '9') - s++; - if (*s == '.') { - s++; - while ('0' <= *s && *s <= '9') - s++; - if (*s == 'e' || *s == 'E') { - s++; - if (*s == '+' || *s == '-') - s++; - while ('0' <= *s && *s <= '9') - s++; - } - } - std::string w(t, s - t); - value = std::stod(w); - return true; +bool parseDouble(double &value, char *&s) { + if (!(*s == '-' || *s == '.' || '0' <= *s && *s <= '9')) return false; + char *t = s; + if (*s == '-') s++; + while ('0' <= *s && *s <= '9') s++; + if (*s == '.') { + s++; + while ('0' <= *s && *s <= '9') s++; + if (*s == 'e' || *s == 'E') { + s++; + if (*s == '+' || *s == '-') s++; + while ('0' <= *s && *s <= '9') s++; + } + } + std::string w(t, s - t); + value = std::stod(w); + return true; } //--------------------------------------------------------- -int split(std::vector &values, char *s) -{ - int count = 0; - for (;;) { - while (*s == ' ' || *s == '\t') - s++; - if (*s == '\0') - break; - double value = 0; - bool found = parseDouble(value, s); - if (found) { - count++; - values.push_back(value); - while (*s == ' ' || *s == '\t') - s++; - } - if (*s == ',' || *s == ';') { - if (!found) { - count++; - values.push_back(0); - } - s++; - } else { - if (!found) - break; - } - } - return count; +int split(std::vector &values, char *s) { + int count = 0; + for (;;) { + while (*s == ' ' || *s == '\t') s++; + if (*s == '\0') break; + double value = 0; + bool found = parseDouble(value, s); + if (found) { + count++; + values.push_back(value); + while (*s == ' ' || *s == '\t') s++; + } + if (*s == ',' || *s == ';') { + if (!found) { + count++; + values.push_back(0); + } + s++; + } else { + if (!found) break; + } + } + return count; } //--------------------------------------------------------- -} // namespace +} // namespace //--------------------------------------------------------- -TDoubleParamFileData::TDoubleParamFileData() - : m_params(), m_dirtyFlag(false) -{ -} +TDoubleParamFileData::TDoubleParamFileData() : m_params(), m_dirtyFlag(false) {} //--------------------------------------------------------- -TDoubleParamFileData::~TDoubleParamFileData() -{ -} +TDoubleParamFileData::~TDoubleParamFileData() {} //--------------------------------------------------------- -void TDoubleParamFileData::setParams(const TDoubleKeyframe::FileParams ¶ms) -{ - m_params = params; - invalidate(); +void TDoubleParamFileData::setParams( + const TDoubleKeyframe::FileParams ¶ms) { + m_params = params; + invalidate(); } //--------------------------------------------------------- -void TDoubleParamFileData::invalidate() -{ - m_dirtyFlag = true; - m_values.clear(); +void TDoubleParamFileData::invalidate() { + m_dirtyFlag = true; + m_values.clear(); } //--------------------------------------------------------- -double TDoubleParamFileData::getValue(double frame, double defaultValue) -{ - if (frame < 0) - return defaultValue; - int intFrame = (int)frame; - if (m_dirtyFlag) - read(); - if (intFrame >= (int)m_values.size()) - return defaultValue; - else - return m_values[intFrame]; +double TDoubleParamFileData::getValue(double frame, double defaultValue) { + if (frame < 0) return defaultValue; + int intFrame = (int)frame; + if (m_dirtyFlag) read(); + if (intFrame >= (int)m_values.size()) + return defaultValue; + else + return m_values[intFrame]; } //--------------------------------------------------------- -void TDoubleParamFileData::read() -{ - m_dirtyFlag = false; - m_values.clear(); - int k = m_params.m_fieldIndex; - if (k < 0) - return; - TFilePath fp = m_params.m_path; - Tifstream is(fp); - char buffer[2048]; - memset(buffer, 0, sizeof buffer); - while (is) { - is.getline(buffer, sizeof(buffer) - 1); - std::vector fields; - QString line(buffer); - if (line.size() == 0 || line.startsWith("#")) - continue; - split(fields, buffer); - double value = 0; - if (k < (int)fields.size()) - value = fields[k]; - m_values.push_back(value); - } +void TDoubleParamFileData::read() { + m_dirtyFlag = false; + m_values.clear(); + int k = m_params.m_fieldIndex; + if (k < 0) return; + TFilePath fp = m_params.m_path; + Tifstream is(fp); + char buffer[2048]; + memset(buffer, 0, sizeof buffer); + while (is) { + is.getline(buffer, sizeof(buffer) - 1); + std::vector fields; + QString line(buffer); + if (line.size() == 0 || line.startsWith("#")) continue; + split(fields, buffer); + double value = 0; + if (k < (int)fields.size()) value = fields[k]; + m_values.push_back(value); + } } //--------------------------------------------------------- diff --git a/toonz/sources/common/tparam/tdoubleparamfile.h b/toonz/sources/common/tparam/tdoubleparamfile.h index cff9967..7344326 100644 --- a/toonz/sources/common/tparam/tdoubleparamfile.h +++ b/toonz/sources/common/tparam/tdoubleparamfile.h @@ -15,24 +15,23 @@ #define DVVAR DV_IMPORT_VAR #endif -class DVAPI TDoubleParamFileData -{ - TDoubleKeyframe::FileParams m_params; - std::vector m_values; - bool m_dirtyFlag; +class DVAPI TDoubleParamFileData { + TDoubleKeyframe::FileParams m_params; + std::vector m_values; + bool m_dirtyFlag; - void read(); + void read(); public: - TDoubleParamFileData(); - ~TDoubleParamFileData(); + TDoubleParamFileData(); + ~TDoubleParamFileData(); - void setParams(const TDoubleKeyframe::FileParams ¶ms); - const TDoubleKeyframe::FileParams &getParams() { return m_params; } + void setParams(const TDoubleKeyframe::FileParams ¶ms); + const TDoubleKeyframe::FileParams &getParams() { return m_params; } - void invalidate(); + void invalidate(); - double getValue(double frame, double defaultValue = 0); + double getValue(double frame, double defaultValue = 0); }; #endif diff --git a/toonz/sources/common/tparam/tdoubleparamrelayproperty.cpp b/toonz/sources/common/tparam/tdoubleparamrelayproperty.cpp index 95a7446..3156af9 100644 --- a/toonz/sources/common/tparam/tdoubleparamrelayproperty.cpp +++ b/toonz/sources/common/tparam/tdoubleparamrelayproperty.cpp @@ -6,104 +6,88 @@ // TDoubleParamRelayProperty implementation //***************************************************************************** -TDoubleParamRelayProperty::TDoubleParamRelayProperty(const std::string &name, TDoubleParamP param) - : TProperty(name), m_frame() -{ - if (param) - setParam(param); +TDoubleParamRelayProperty::TDoubleParamRelayProperty(const std::string &name, + TDoubleParamP param) + : TProperty(name), m_frame() { + if (param) setParam(param); } //------------------------------------------------------------------- -TDoubleParamRelayProperty::~TDoubleParamRelayProperty() -{ - if (m_param) - m_param->removeObserver(this); +TDoubleParamRelayProperty::~TDoubleParamRelayProperty() { + if (m_param) m_param->removeObserver(this); } //------------------------------------------------------------------- -TDoubleParamRelayProperty::TDoubleParamRelayProperty(const TDoubleParamRelayProperty &other) - : TProperty(other), m_param(other.m_param), m_frame(other.m_frame) -{ - if (m_param) - m_param->addObserver(this); +TDoubleParamRelayProperty::TDoubleParamRelayProperty( + const TDoubleParamRelayProperty &other) + : TProperty(other), m_param(other.m_param), m_frame(other.m_frame) { + if (m_param) m_param->addObserver(this); } //------------------------------------------------------------------- -TDoubleParamRelayProperty &TDoubleParamRelayProperty::operator=(const TDoubleParamRelayProperty &other) -{ - TProperty::operator=(other); +TDoubleParamRelayProperty &TDoubleParamRelayProperty::operator=( + const TDoubleParamRelayProperty &other) { + TProperty::operator=(other); - if (m_param) - m_param->removeObserver(this); + if (m_param) m_param->removeObserver(this); - m_param = other.m_param; - m_frame = other.m_frame; + m_param = other.m_param; + m_frame = other.m_frame; - if (m_param) - m_param->addObserver(this); + if (m_param) m_param->addObserver(this); - return *this; + return *this; } //------------------------------------------------------------------- -TProperty *TDoubleParamRelayProperty::clone() const -{ - return new TDoubleParamRelayProperty(*this); +TProperty *TDoubleParamRelayProperty::clone() const { + return new TDoubleParamRelayProperty(*this); } //------------------------------------------------------------------- -std::string TDoubleParamRelayProperty::getValueAsString() -{ - return m_param ? std::to_string(m_param->getValue(m_frame)) : ""; +std::string TDoubleParamRelayProperty::getValueAsString() { + return m_param ? std::to_string(m_param->getValue(m_frame)) : ""; } //------------------------------------------------------------------- -void TDoubleParamRelayProperty::setParam(const TDoubleParamP ¶m) -{ - if (m_param == param) - return; +void TDoubleParamRelayProperty::setParam(const TDoubleParamP ¶m) { + if (m_param == param) return; - if (m_param) - m_param->removeObserver(this); + if (m_param) m_param->removeObserver(this); - m_param = param; + m_param = param; - if (param) - param->addObserver(this); + if (param) param->addObserver(this); } //------------------------------------------------------------------- -void TDoubleParamRelayProperty::setValue(double v) -{ - if (m_param) - m_param->setValue(m_frame, v); +void TDoubleParamRelayProperty::setValue(double v) { + if (m_param) m_param->setValue(m_frame, v); } //------------------------------------------------------------------- -double TDoubleParamRelayProperty::getValue() const -{ - return m_param ? m_param->getValue(m_frame) : 0.0; +double TDoubleParamRelayProperty::getValue() const { + return m_param ? m_param->getValue(m_frame) : 0.0; } //------------------------------------------------------------------- -void TDoubleParamRelayProperty::accept(TProperty::Visitor &v) -{ - if (TDoubleParamRelayProperty::Visitor *vv = dynamic_cast(&v)) - vv->visit(this); +void TDoubleParamRelayProperty::accept(TProperty::Visitor &v) { + if (TDoubleParamRelayProperty::Visitor *vv = + dynamic_cast(&v)) + vv->visit(this); } //------------------------------------------------------------------- -void TDoubleParamRelayProperty::onChange(const TParamChange &) -{ - notifyListeners(); +void TDoubleParamRelayProperty::onChange(const TParamChange &) { + notifyListeners(); } diff --git a/toonz/sources/common/tparam/tnotanimatableparam.cpp b/toonz/sources/common/tparam/tnotanimatableparam.cpp index a77834c..dc89a62 100644 --- a/toonz/sources/common/tparam/tnotanimatableparam.cpp +++ b/toonz/sources/common/tparam/tnotanimatableparam.cpp @@ -8,283 +8,245 @@ PERSIST_IDENTIFIER(TBoolParam, "boolParam") PERSIST_IDENTIFIER(TFilePathParam, "filePathParam") PERSIST_IDENTIFIER(TStringParam, "stringParam") PERSIST_IDENTIFIER(TNADoubleParam, "naDoubleParam") -//PERSIST_IDENTIFIER(TIntEnumParam, "intEnumParam") +// PERSIST_IDENTIFIER(TIntEnumParam, "intEnumParam") TPersistDeclarationT TEnumParam::m_declaration("intEnumParam"); //========================================================= -void TIntParam::loadData(TIStream &is) -{ - int def, value; - is >> def; - if (is.eos()) { - def += 1; - setDefaultValue(def); - setValue(def, false); - return; - } - setDefaultValue(def); - is >> value; - setValue(value, false); +void TIntParam::loadData(TIStream &is) { + int def, value; + is >> def; + if (is.eos()) { + def += 1; + setDefaultValue(def); + setValue(def, false); + return; + } + setDefaultValue(def); + is >> value; + setValue(value, false); } //--------------------------------------------------------- -void TIntParam::saveData(TOStream &os) -{ - os << getDefaultValue(); - os << getValue(); +void TIntParam::saveData(TOStream &os) { + os << getDefaultValue(); + os << getValue(); } //--------------------------------------------------------- -bool TIntParam::isWheelEnabled() const -{ - return m_isWheelEnabled; -} +bool TIntParam::isWheelEnabled() const { return m_isWheelEnabled; } //--------------------------------------------------------- -void TIntParam::enableWheel(bool on) -{ - m_isWheelEnabled = on; -} +void TIntParam::enableWheel(bool on) { m_isWheelEnabled = on; } //========================================================= -void TBoolParam::loadData(TIStream &is) -{ - int def, value; - is >> def >> value; - setDefaultValue(def ? true : false); - setValue(value ? true : false, false); +void TBoolParam::loadData(TIStream &is) { + int def, value; + is >> def >> value; + setDefaultValue(def ? true : false); + setValue(value ? true : false, false); } //--------------------------------------------------------- -void TBoolParam::saveData(TOStream &os) -{ - os << (int)getDefaultValue() << (int)getValue(); +void TBoolParam::saveData(TOStream &os) { + os << (int)getDefaultValue() << (int)getValue(); } //========================================================= -void TFilePathParam::loadData(TIStream &is) -{ - TFilePath def, value; - is >> def >> value; - setDefaultValue(def); - setValue(value, false); +void TFilePathParam::loadData(TIStream &is) { + TFilePath def, value; + is >> def >> value; + setDefaultValue(def); + setValue(value, false); } //--------------------------------------------------------- -void TFilePathParam::saveData(TOStream &os) -{ - os << getDefaultValue(); - os << getValue(); +void TFilePathParam::saveData(TOStream &os) { + os << getDefaultValue(); + os << getValue(); } //========================================================= -void TStringParam::loadData(TIStream &is) -{ - std::wstring def, value; - is >> def >> value; - setDefaultValue(def); - setValue(value, false); +void TStringParam::loadData(TIStream &is) { + std::wstring def, value; + is >> def >> value; + setDefaultValue(def); + setValue(value, false); } -void TStringParam::saveData(TOStream &os) -{ - os << getDefaultValue(); - os << getValue(); +void TStringParam::saveData(TOStream &os) { + os << getDefaultValue(); + os << getValue(); } //========================================================= -void TNADoubleParam::loadData(TIStream &is) -{ - double def, value; - is >> def >> value; - setDefaultValue(def); - setValue(value, false); +void TNADoubleParam::loadData(TIStream &is) { + double def, value; + is >> def >> value; + setDefaultValue(def); + setValue(value, false); } -void TNADoubleParam::saveData(TOStream &os) -{ - os << getDefaultValue(); - os << getValue(); +void TNADoubleParam::saveData(TOStream &os) { + os << getDefaultValue(); + os << getValue(); } //========================================================= //========================================================= -namespace -{ +namespace { template -class matchesValue -{ - T m_v; +class matchesValue { + T m_v; public: - matchesValue(T v) : m_v(v) {} - bool operator()(const std::pair &p) { return m_v == p.first; } + matchesValue(T v) : m_v(v) {} + bool operator()(const std::pair &p) { return m_v == p.first; } }; } //--------------------------------------------------------- -class TEnumParamImp -{ +class TEnumParamImp { public: - std::vector> m_items; - void copy(std::unique_ptr& src) - { - m_items.clear(); - std::back_insert_iterator>> bii(m_items); - std::copy(src->m_items.begin(), src->m_items.end(), bii); - } - bool checkValue(int v) - { - std::vector>::iterator it = - std::find_if(m_items.begin(), m_items.end(), matchesValue(v)); - return it != m_items.end(); - } + std::vector> m_items; + void copy(std::unique_ptr &src) { + m_items.clear(); + std::back_insert_iterator>> bii( + m_items); + std::copy(src->m_items.begin(), src->m_items.end(), bii); + } + bool checkValue(int v) { + std::vector>::iterator it = + std::find_if(m_items.begin(), m_items.end(), matchesValue(v)); + return it != m_items.end(); + } }; //--------------------------------------------------------- TEnumParam::TEnumParam(const int &v, const std::string &caption) - : TNotAnimatableParam(v), m_imp(new TEnumParamImp()) -{ - addItem(v, caption); + : TNotAnimatableParam(v), m_imp(new TEnumParamImp()) { + addItem(v, caption); } //--------------------------------------------------------- -void TEnumParam::copy(TParam *src) -{ - TNotAnimatableParam::copy(src); - TEnumParam *p = dynamic_cast(src); - if (!p) - throw TException("invalid source for copy"); - TEnumParam::setName(src->getName()); - m_imp->copy(p->m_imp); +void TEnumParam::copy(TParam *src) { + TNotAnimatableParam::copy(src); + TEnumParam *p = dynamic_cast(src); + if (!p) throw TException("invalid source for copy"); + TEnumParam::setName(src->getName()); + m_imp->copy(p->m_imp); } //--------------------------------------------------------- -TEnumParam::~TEnumParam() -{ -} +TEnumParam::~TEnumParam() {} //--------------------------------------------------------- TEnumParam::TEnumParam(const TEnumParam &src) - : TNotAnimatableParam(src), m_imp(new TEnumParamImp(*src.m_imp)) -{ -} + : TNotAnimatableParam(src), m_imp(new TEnumParamImp(*src.m_imp)) {} //--------------------------------------------------------- TEnumParam::TEnumParam() - : TNotAnimatableParam(), m_imp(new TEnumParamImp()) + : TNotAnimatableParam() + , m_imp(new TEnumParamImp()) -{ -} +{} //--------------------------------------------------------- -void TEnumParam::setValue(int v, bool undoing) -{ - bool valid = false; - std::vector>::iterator it = m_imp->m_items.begin(); - for (; it != m_imp->m_items.end(); ++it) { - if (it->first == v) { - valid = true; - break; - } - } - - if (!valid) - throw TException("out of range parameter value"); - - TNotAnimatableParam::setValue(v, undoing); +void TEnumParam::setValue(int v, bool undoing) { + bool valid = false; + std::vector>::iterator it = + m_imp->m_items.begin(); + for (; it != m_imp->m_items.end(); ++it) { + if (it->first == v) { + valid = true; + break; + } + } + + if (!valid) throw TException("out of range parameter value"); + + TNotAnimatableParam::setValue(v, undoing); } //--------------------------------------------------------- -void TEnumParam::setValue(const std::string &caption, bool undoing) -{ - bool valid = false; - int v = 0; - std::vector>::iterator it = m_imp->m_items.begin(); - for (; it != m_imp->m_items.end(); ++it) { - if (it->second == caption) { - v = it->first; - valid = true; - break; - } - } - - if (!valid) - throw TException("out of range parameter value"); - - TNotAnimatableParam::setValue(v, undoing); +void TEnumParam::setValue(const std::string &caption, bool undoing) { + bool valid = false; + int v = 0; + std::vector>::iterator it = + m_imp->m_items.begin(); + for (; it != m_imp->m_items.end(); ++it) { + if (it->second == caption) { + v = it->first; + valid = true; + break; + } + } + + if (!valid) throw TException("out of range parameter value"); + + TNotAnimatableParam::setValue(v, undoing); } //--------------------------------------------------------- -void TEnumParam::addItem(const int &item, const std::string &caption) -{ - m_imp->m_items.push_back(std::make_pair(item, caption)); +void TEnumParam::addItem(const int &item, const std::string &caption) { + m_imp->m_items.push_back(std::make_pair(item, caption)); } //--------------------------------------------------------- -int TEnumParam::getItemCount() const -{ - return m_imp->m_items.size(); -} +int TEnumParam::getItemCount() const { return m_imp->m_items.size(); } //--------------------------------------------------------- -void TEnumParam::getItem(int i, int &item, std::string &caption) const -{ - assert(i >= 0 && i < m_imp->m_items.size()); - item = m_imp->m_items[i].first; - caption = m_imp->m_items[i].second; +void TEnumParam::getItem(int i, int &item, std::string &caption) const { + assert(i >= 0 && i < m_imp->m_items.size()); + item = m_imp->m_items[i].first; + caption = m_imp->m_items[i].second; } //--------------------------------------------------------- -void TEnumParam::loadData(TIStream &is) -{ - int value; - is >> value; +void TEnumParam::loadData(TIStream &is) { + int value; + is >> value; - try { - setValue(value, false); - } catch (TException &) { - TNotAnimatableParam::reset(); - } + try { + setValue(value, false); + } catch (TException &) { + TNotAnimatableParam::reset(); + } } //--------------------------------------------------------- -void TEnumParam::saveData(TOStream &os) -{ - os << TNotAnimatableParam::getValue(); +void TEnumParam::saveData(TOStream &os) { + os << TNotAnimatableParam::getValue(); } //--------------------------------------------------------- -void TIntParam::setValueRange(int min, int max) -{ - assert(min < max); +void TIntParam::setValueRange(int min, int max) { + assert(min < max); - minValue = min; - maxValue = max; + minValue = min; + maxValue = max; } -bool TIntParam::getValueRange(int &min, int &max) const -{ - min = minValue; - max = maxValue; - return min < max; +bool TIntParam::getValueRange(int &min, int &max) const { + min = minValue; + max = maxValue; + return min < max; } diff --git a/toonz/sources/common/tparam/tparam.cpp b/toonz/sources/common/tparam/tparam.cpp index f2bb84c..1299c7f 100644 --- a/toonz/sources/common/tparam/tparam.cpp +++ b/toonz/sources/common/tparam/tparam.cpp @@ -11,9 +11,12 @@ double TParamChange::m_maxFrame = +(std::numeric_limits::max)(); //------------------------------------------------------------------------------ -TParamChange::TParamChange(TParam *param, - double firstAffectedFrame, double lastAffectedFrame, - bool keyframeChanged, bool dragging, bool undoing) - : m_param(param), m_firstAffectedFrame(firstAffectedFrame), m_lastAffectedFrame(lastAffectedFrame), m_keyframeChanged(keyframeChanged), m_dragging(dragging), m_undoing(undoing) -{ -} +TParamChange::TParamChange(TParam *param, double firstAffectedFrame, + double lastAffectedFrame, bool keyframeChanged, + bool dragging, bool undoing) + : m_param(param) + , m_firstAffectedFrame(firstAffectedFrame) + , m_lastAffectedFrame(lastAffectedFrame) + , m_keyframeChanged(keyframeChanged) + , m_dragging(dragging) + , m_undoing(undoing) {} diff --git a/toonz/sources/common/tparam/tparamcontainer.cpp b/toonz/sources/common/tparam/tparamcontainer.cpp index 7865e6f..38548b8 100644 --- a/toonz/sources/common/tparam/tparamcontainer.cpp +++ b/toonz/sources/common/tparam/tparamcontainer.cpp @@ -6,129 +6,105 @@ #include "tparam.h" -void TParamVar::setParamObserver(TParamObserver *obs) -{ - if (m_paramObserver == obs) - return; - TParam *param = getParam(); - if (param) { - if (obs) - param->addObserver(obs); - if (m_paramObserver) - param->removeObserver(m_paramObserver); - } - m_paramObserver = obs; +void TParamVar::setParamObserver(TParamObserver *obs) { + if (m_paramObserver == obs) return; + TParam *param = getParam(); + if (param) { + if (obs) param->addObserver(obs); + if (m_paramObserver) param->removeObserver(m_paramObserver); + } + m_paramObserver = obs; } -class TParamContainer::Imp -{ +class TParamContainer::Imp { public: - std::map m_nameTable; - std::vector m_vars; - TParamObserver *m_paramObserver; - Imp() : m_paramObserver(0) {} - ~Imp() { clearPointerContainer(m_vars); } + std::map m_nameTable; + std::vector m_vars; + TParamObserver *m_paramObserver; + Imp() : m_paramObserver(0) {} + ~Imp() { clearPointerContainer(m_vars); } }; -TParamContainer::TParamContainer() - : m_imp(new Imp()) -{ -} +TParamContainer::TParamContainer() : m_imp(new Imp()) {} -TParamContainer::~TParamContainer() -{ -} +TParamContainer::~TParamContainer() {} -void TParamContainer::setParamObserver(TParamObserver *observer) -{ - m_imp->m_paramObserver = observer; +void TParamContainer::setParamObserver(TParamObserver *observer) { + m_imp->m_paramObserver = observer; } -TParamObserver *TParamContainer::getParamObserver() const -{ - return m_imp->m_paramObserver; +TParamObserver *TParamContainer::getParamObserver() const { + return m_imp->m_paramObserver; } -void TParamContainer::add(TParamVar *var) -{ - m_imp->m_vars.push_back(var); - m_imp->m_nameTable[var->getName()] = var; - var->setParamObserver(m_imp->m_paramObserver); - var->getParam()->setName(var->getName()); +void TParamContainer::add(TParamVar *var) { + m_imp->m_vars.push_back(var); + m_imp->m_nameTable[var->getName()] = var; + var->setParamObserver(m_imp->m_paramObserver); + var->getParam()->setName(var->getName()); } -int TParamContainer::getParamCount() const -{ - return m_imp->m_vars.size(); -} +int TParamContainer::getParamCount() const { return m_imp->m_vars.size(); } -TParam *TParamContainer::getParam(int index) const -{ - assert(0 <= index && index < getParamCount()); - return m_imp->m_vars[index]->getParam(); +TParam *TParamContainer::getParam(int index) const { + assert(0 <= index && index < getParamCount()); + return m_imp->m_vars[index]->getParam(); } -bool TParamContainer::isParamHidden(int index) const -{ - assert(0 <= index && index < getParamCount()); - return m_imp->m_vars[index]->isHidden(); +bool TParamContainer::isParamHidden(int index) const { + assert(0 <= index && index < getParamCount()); + return m_imp->m_vars[index]->isHidden(); } -std::string TParamContainer::getParamName(int index) const -{ - assert(0 <= index && index < getParamCount()); - return m_imp->m_vars[index]->getName(); +std::string TParamContainer::getParamName(int index) const { + assert(0 <= index && index < getParamCount()); + return m_imp->m_vars[index]->getName(); } -const TParamVar *TParamContainer::getParamVar(int index) const -{ - assert(0 <= index && index < getParamCount()); - return m_imp->m_vars[index]; +const TParamVar *TParamContainer::getParamVar(int index) const { + assert(0 <= index && index < getParamCount()); + return m_imp->m_vars[index]; } -TParam *TParamContainer::getParam(std::string name) const -{ - std::map::const_iterator it; - it = m_imp->m_nameTable.find(name); - if (it == m_imp->m_nameTable.end()) - return 0; - else - return it->second->getParam(); +TParam *TParamContainer::getParam(std::string name) const { + std::map::const_iterator it; + it = m_imp->m_nameTable.find(name); + if (it == m_imp->m_nameTable.end()) + return 0; + else + return it->second->getParam(); } -void TParamContainer::unlink() -{ - for (int i = 0; i < getParamCount(); i++) { - //TRangeParam *p0;//,*p1; - TParamVar *var = m_imp->m_vars[i]; - TParam *param = var->getParam(); - //p0 = dynamic_cast(param); - var->setParam(param->clone()); - /*p1 = dynamic_cast(var->getParam()); - if(p0 && p1) - { - string name = p0->getName(); - name = p1->getName(); - }*/ - } +void TParamContainer::unlink() { + for (int i = 0; i < getParamCount(); i++) { + // TRangeParam *p0;//,*p1; + TParamVar *var = m_imp->m_vars[i]; + TParam *param = var->getParam(); + // p0 = dynamic_cast(param); + var->setParam(param->clone()); + /*p1 = dynamic_cast(var->getParam()); +if(p0 && p1) +{ +string name = p0->getName(); +name = p1->getName(); +}*/ + } } -void TParamContainer::link(const TParamContainer *src) -{ - assert(getParamCount() == src->getParamCount()); - for (int i = 0; i < getParamCount(); i++) { - assert(getParamName(i) == src->getParamName(i)); - assert(m_imp->m_vars[i]->getName() == getParamName(i)); - m_imp->m_vars[i]->setParam(src->getParam(i)); - } +void TParamContainer::link(const TParamContainer *src) { + assert(getParamCount() == src->getParamCount()); + for (int i = 0; i < getParamCount(); i++) { + assert(getParamName(i) == src->getParamName(i)); + assert(m_imp->m_vars[i]->getName() == getParamName(i)); + m_imp->m_vars[i]->setParam(src->getParam(i)); + } } -void TParamContainer::copy(const TParamContainer *src) -{ - assert(getParamCount() == src->getParamCount()); - for (int i = 0; i < getParamCount(); i++) { - assert(getParamName(i) == src->getParamName(i)); - assert(m_imp->m_vars[i]->getName() == getParamName(i)); - getParam(i)->copy(src->getParam(i)); - } +void TParamContainer::copy(const TParamContainer *src) { + assert(getParamCount() == src->getParamCount()); + for (int i = 0; i < getParamCount(); i++) { + assert(getParamName(i) == src->getParamName(i)); + assert(m_imp->m_vars[i]->getName() == getParamName(i)); + getParam(i)->copy(src->getParam(i)); + } } diff --git a/toonz/sources/common/tparam/tparamset.cpp b/toonz/sources/common/tparam/tparamset.cpp index 88b6c2c..2d47d11 100644 --- a/toonz/sources/common/tparam/tparamset.cpp +++ b/toonz/sources/common/tparam/tparamset.cpp @@ -10,81 +10,67 @@ //--------------------------------------------------------- -namespace -{ -void doRelease(const std::pair ¶m) -{ - param.first->release(); +namespace { +void doRelease(const std::pair ¶m) { + param.first->release(); } }; //------------------------------------------------------------------------------ -class TParamSetImp : public TParamObserver -{ - friend class TParamSet; - TParamSet *m_param; - std::vector> m_params; +class TParamSetImp : public TParamObserver { + friend class TParamSet; + TParamSet *m_param; + std::vector> m_params; - // ChangeBlock *m_changeBlock; - bool m_draggingEnabled, m_notificationEnabled; + // ChangeBlock *m_changeBlock; + bool m_draggingEnabled, m_notificationEnabled; public: - TParamSetImp(TParamSet *param) : m_param(param) - //, m_changeBlock(0) - , - m_draggingEnabled(false), m_notificationEnabled(true) - { - } - - ~TParamSetImp() - { - std::for_each(m_params.begin(), m_params.end(), doRelease); - } - // std::set m_observers; - std::set m_paramObservers; - - template - void notify(const T &change); - - void onChange(const TParamChange &change) - { - } + TParamSetImp(TParamSet *param) + : m_param(param) + //, m_changeBlock(0) + , m_draggingEnabled(false) + , m_notificationEnabled(true) {} + + ~TParamSetImp() { + std::for_each(m_params.begin(), m_params.end(), doRelease); + } + // std::set m_observers; + std::set m_paramObservers; + + template + void notify(const T &change); + + void onChange(const TParamChange &change) {} }; //--------------------------------------------------------- TParamSet::TParamSet(std::string name) - : TParam(name) - , m_imp(new TParamSetImp(this)) -{ -} + : TParam(name), m_imp(new TParamSetImp(this)) {} //--------------------------------------------------------- TParamSet::TParamSet(const TParamSet &src) - : TParam(src.getName()) - , m_imp(new TParamSetImp(this)) -{ -} + : TParam(src.getName()), m_imp(new TParamSetImp(this)) {} //--------------------------------------------------------- -TParamSet::~TParamSet() -{ - delete m_imp; -} +TParamSet::~TParamSet() { delete m_imp; } //--------------------------------------------------------- /* template -class MyBackInsertIterator : public std::iterator +class MyBackInsertIterator : public std::iterator { protected: Container &container; public: MyBackInsertIterator(Container &c) : container(c) {} - MyBackInsertIterator &operator=(const typename Container::value_type &value) + MyBackInsertIterator &operator=(const typename +Container::value_type &value) { container.push_back(value); return *this; @@ -106,38 +92,38 @@ public: //--------------------------------------------------------- -void TParamSet::beginParameterChange() -{ - // assert(0); +void TParamSet::beginParameterChange() { + // assert(0); - //std::set::iterator it = m_imp->m_observers.begin(); - //for (;it != m_imp->m_observers.end(); ++it) - // (*it)->onBeginChangeBlock(this); + // std::set::iterator it = m_imp->m_observers.begin(); + // for (;it != m_imp->m_observers.end(); ++it) + // (*it)->onBeginChangeBlock(this); - //assert(!m_imp->m_changeBlock); + // assert(!m_imp->m_changeBlock); - std::vector params; + std::vector params; - /* -MyBackInsertIterator > > myBackInsertIterator(params); + /* +MyBackInsertIterator > > +myBackInsertIterator(params); copy(m_imp->m_params.begin(), m_imp->m_params.end(), myIterator); */ - std::vector>::iterator it2 = m_imp->m_params.begin(); - for (; it2 != m_imp->m_params.end(); ++it2) - params.push_back(it2->first); + std::vector>::iterator it2 = + m_imp->m_params.begin(); + for (; it2 != m_imp->m_params.end(); ++it2) params.push_back(it2->first); - // m_imp->m_changeBlock = new ChangeBlock; + // m_imp->m_changeBlock = new ChangeBlock; }; //--------------------------------------------------------- void TParamSet::endParameterChange(){ - // assert(0); - //assert(m_imp->m_changeBlock); - /* -TParamSetChange change(this, m_imp->m_changeBlock->m_firstAffectedFrame, - m_imp->m_changeBlock->m_lastAffectedFrame, - m_imp->m_changeBlock->m_changes, false); + // assert(0); + // assert(m_imp->m_changeBlock); + /* +TParamSetChange change(this, m_imp->m_changeBlock->m_firstAffectedFrame, + m_imp->m_changeBlock->m_lastAffectedFrame, + m_imp->m_changeBlock->m_changes, false); change.m_dragging = m_imp->m_draggingEnabled; @@ -155,196 +141,182 @@ m_imp->notify(change); //--------------------------------------------------------- -void TParamSet::addParam(const TParamP ¶m, const std::string &name) -{ - std::pair paramToInsert = std::make_pair(param.getPointer(), name); - std::vector>::iterator it = - std::find(m_imp->m_params.begin(), m_imp->m_params.end(), paramToInsert); - - if (it == m_imp->m_params.end()) { - param->addRef(); - param->addObserver(m_imp); - m_imp->m_params.push_back(paramToInsert); - //TParamSetParamAdded psParamAdded(this, param.getPointer(), name, false); - if (param->getName().empty()) - param->setName(name); - //m_imp->notify(psParamAdded); - } +void TParamSet::addParam(const TParamP ¶m, const std::string &name) { + std::pair paramToInsert = + std::make_pair(param.getPointer(), name); + std::vector>::iterator it = + std::find(m_imp->m_params.begin(), m_imp->m_params.end(), paramToInsert); + + if (it == m_imp->m_params.end()) { + param->addRef(); + param->addObserver(m_imp); + m_imp->m_params.push_back(paramToInsert); + // TParamSetParamAdded psParamAdded(this, param.getPointer(), name, false); + if (param->getName().empty()) param->setName(name); + // m_imp->notify(psParamAdded); + } } //--------------------------------------------------------- -void TParamSet::insertParam(const TParamP ¶m, const std::string &name, int index) -{ - std::pair paramToInsert = std::make_pair(param.getPointer(), name); - std::vector>::iterator it = - std::find(m_imp->m_params.begin(), m_imp->m_params.end(), paramToInsert); - - if (it == m_imp->m_params.end()) { - param->addRef(); - param->addObserver(m_imp); - it = m_imp->m_params.begin(); - int f; - for (f = 0; f < index; f++) - it++; - m_imp->m_params.insert(it, paramToInsert); - if (param->getName().empty()) - param->setName(name); - } +void TParamSet::insertParam(const TParamP ¶m, const std::string &name, + int index) { + std::pair paramToInsert = + std::make_pair(param.getPointer(), name); + std::vector>::iterator it = + std::find(m_imp->m_params.begin(), m_imp->m_params.end(), paramToInsert); + + if (it == m_imp->m_params.end()) { + param->addRef(); + param->addObserver(m_imp); + it = m_imp->m_params.begin(); + int f; + for (f = 0; f < index; f++) it++; + m_imp->m_params.insert(it, paramToInsert); + if (param->getName().empty()) param->setName(name); + } } //--------------------------------------------------------- -namespace -{ -class matchesParam -{ - TParamP m_param; +namespace { +class matchesParam { + TParamP m_param; public: - matchesParam(const TParamP ¶m) : m_param(param) {} - bool operator()(const std::pair ¶m) - { - return m_param.getPointer() == param.first; - } + matchesParam(const TParamP ¶m) : m_param(param) {} + bool operator()(const std::pair ¶m) { + return m_param.getPointer() == param.first; + } }; } //--------------------------------------------------------- -void TParamSet::removeParam(const TParamP ¶m) -{ - std::vector>::iterator it = - std::find_if(m_imp->m_params.begin(), m_imp->m_params.end(), matchesParam(param)); - if (it != m_imp->m_params.end()) { - param->removeObserver(m_imp); +void TParamSet::removeParam(const TParamP ¶m) { + std::vector>::iterator it = std::find_if( + m_imp->m_params.begin(), m_imp->m_params.end(), matchesParam(param)); + if (it != m_imp->m_params.end()) { + param->removeObserver(m_imp); - //TParamSetParamRemoved psParamRemoved(this, param.getPointer(), it->second, false); - //m_imp->notify(psParamRemoved); + // TParamSetParamRemoved psParamRemoved(this, param.getPointer(), + // it->second, false); + // m_imp->notify(psParamRemoved); - param->release(); - m_imp->m_params.erase(it); - } + param->release(); + m_imp->m_params.erase(it); + } } //--------------------------------------------------------- -void TParamSet::removeAllParam() -{ - while (!m_imp->m_params.empty()) { - std::vector>::iterator it = m_imp->m_params.begin(); - TParam *param = it->first; - param->removeObserver(m_imp); - param->release(); - m_imp->m_params.erase(it); - } +void TParamSet::removeAllParam() { + while (!m_imp->m_params.empty()) { + std::vector>::iterator it = + m_imp->m_params.begin(); + TParam *param = it->first; + param->removeObserver(m_imp); + param->release(); + m_imp->m_params.erase(it); + } } //--------------------------------------------------------- -int TParamSet::getParamCount() const -{ - return m_imp->m_params.size(); -} +int TParamSet::getParamCount() const { return m_imp->m_params.size(); } //--------------------------------------------------------- -TParamP TParamSet::getParam(int i) const -{ - assert(i >= 0 && i < (int)m_imp->m_params.size()); - return m_imp->m_params[i].first; +TParamP TParamSet::getParam(int i) const { + assert(i >= 0 && i < (int)m_imp->m_params.size()); + return m_imp->m_params[i].first; } //--------------------------------------------------------- -std::string TParamSet::getParamName(int i) const -{ - assert(i >= 0 && i < (int)m_imp->m_params.size()); - return m_imp->m_params[i].second; +std::string TParamSet::getParamName(int i) const { + assert(i >= 0 && i < (int)m_imp->m_params.size()); + return m_imp->m_params[i].second; } //--------------------------------------------------------- -int TParamSet::getParamIdx(const std::string &name) const -{ - int i, paramsCount = m_imp->m_params.size(); - for (i = 0; i < paramsCount; ++i) - if (m_imp->m_params[i].second == name) - break; +int TParamSet::getParamIdx(const std::string &name) const { + int i, paramsCount = m_imp->m_params.size(); + for (i = 0; i < paramsCount; ++i) + if (m_imp->m_params[i].second == name) break; - return i; + return i; } //--------------------------------------------------------- -void TParamSet::getAnimatableParams(std::vector ¶ms, bool recursive) -{ - std::vector>::iterator it = m_imp->m_params.begin(); - for (; it != m_imp->m_params.end(); ++it) { - TParam *param = it->first; - - TDoubleParamP dparam = TParamP(param); - if (dparam) - params.push_back(dparam); - else { - TParamSetP paramset = TParamP(param); - if (paramset && recursive) - paramset->getAnimatableParams(params, recursive); - } - } +void TParamSet::getAnimatableParams(std::vector ¶ms, + bool recursive) { + std::vector>::iterator it = + m_imp->m_params.begin(); + for (; it != m_imp->m_params.end(); ++it) { + TParam *param = it->first; + + TDoubleParamP dparam = TParamP(param); + if (dparam) + params.push_back(dparam); + else { + TParamSetP paramset = TParamP(param); + if (paramset && recursive) + paramset->getAnimatableParams(params, recursive); + } + } } //--------------------------------------------------------- -void TParamSet::addObserver(TParamObserver *observer) -{ - //TParamSetObserver *obs = dynamic_cast(observer); - //if (obs) - // m_imp->m_observers.insert(obs); - //else - m_imp->m_paramObservers.insert(observer); +void TParamSet::addObserver(TParamObserver *observer) { + // TParamSetObserver *obs = dynamic_cast(observer); + // if (obs) + // m_imp->m_observers.insert(obs); + // else + m_imp->m_paramObservers.insert(observer); } //--------------------------------------------------------- template -void TParamSetImp::notify(const T &change) -{ - if (m_notificationEnabled) { - // for (std::set::iterator it = m_observers.begin(); - // it!= m_observers.end(); - // ++it) - // (*it)->onChange(change); - for (std::set::iterator paramIt = m_paramObservers.begin(); - paramIt != m_paramObservers.end(); - ++paramIt) - (*paramIt)->onChange(change); - } +void TParamSetImp::notify(const T &change) { + if (m_notificationEnabled) { + // for (std::set::iterator it = m_observers.begin(); + // it!= m_observers.end(); + // ++it) + // (*it)->onChange(change); + for (std::set::iterator paramIt = + m_paramObservers.begin(); + paramIt != m_paramObservers.end(); ++paramIt) + (*paramIt)->onChange(change); + } } //--------------------------------------------------------- -void TParamSet::removeObserver(TParamObserver *observer) -{ - //TParamSetObserver *obs = dynamic_cast(observer); - //if (obs) - // m_imp->m_observers.erase(obs); - //else - m_imp->m_paramObservers.erase(observer); +void TParamSet::removeObserver(TParamObserver *observer) { + // TParamSetObserver *obs = dynamic_cast(observer); + // if (obs) + // m_imp->m_observers.erase(obs); + // else + m_imp->m_paramObservers.erase(observer); } //--------------------------------------------------------- -void TParamSet::enableDragging(bool on) -{ - std::vector>::iterator it = m_imp->m_params.begin(); - for (; it != m_imp->m_params.end(); ++it) { - TDoubleParamP dparam(it->first); - //if (dparam) - // dparam->enableDragging(on); - } - - m_imp->m_draggingEnabled = on; +void TParamSet::enableDragging(bool on) { + std::vector>::iterator it = + m_imp->m_params.begin(); + for (; it != m_imp->m_params.end(); ++it) { + TDoubleParamP dparam(it->first); + // if (dparam) + // dparam->enableDragging(on); + } + + m_imp->m_draggingEnabled = on; } //--------------------------------------------------------- @@ -355,7 +327,7 @@ class DoEnableNotification : public std::binary_function { public: DoEnableNotification() {} - void operator() (const pair ¶m, bool on) + void operator() (const pair ¶m, bool on) { return param->first->enableNotification(on); } @@ -364,211 +336,188 @@ public: */ //--------------------------------------------------------- -void TParamSet::enableNotification(bool on) -{ - // std::for_each(m_imp->m_params.begin(), m_imp->m_params.end(), std::bind2nd(DoEnableNotification, on)); +void TParamSet::enableNotification(bool on) { + // std::for_each(m_imp->m_params.begin(), m_imp->m_params.end(), + // std::bind2nd(DoEnableNotification, on)); - std::vector>::iterator it = m_imp->m_params.begin(); - for (; it != m_imp->m_params.end(); ++it) { - it->first->enableNotification(on); - } + std::vector>::iterator it = + m_imp->m_params.begin(); + for (; it != m_imp->m_params.end(); ++it) { + it->first->enableNotification(on); + } - m_imp->m_notificationEnabled = on; + m_imp->m_notificationEnabled = on; } //--------------------------------------------------------- -bool TParamSet::isNotificationEnabled() const -{ - return m_imp->m_notificationEnabled; +bool TParamSet::isNotificationEnabled() const { + return m_imp->m_notificationEnabled; } //--------------------------------------------------------- -bool TParamSet::isKeyframe(double frame) const -{ - for (int i = 0; i < getParamCount(); i++) - if (getParam(i)->isKeyframe(frame)) - return true; - return false; +bool TParamSet::isKeyframe(double frame) const { + for (int i = 0; i < getParamCount(); i++) + if (getParam(i)->isKeyframe(frame)) return true; + return false; } //--------------------------------------------------------- -void TParamSet::getKeyframes(std::set &frames) const -{ - for (int i = 0; i < getParamCount(); i++) - getParam(i)->getKeyframes(frames); +void TParamSet::getKeyframes(std::set &frames) const { + for (int i = 0; i < getParamCount(); i++) getParam(i)->getKeyframes(frames); } //--------------------------------------------------------- -double TParamSet::keyframeIndexToFrame(int index) const -{ - std::set frames; - getKeyframes(frames); - assert(0 <= index && index < (int)frames.size()); - std::set::const_iterator it = frames.begin(); - std::advance(it, index); - return *it; +double TParamSet::keyframeIndexToFrame(int index) const { + std::set frames; + getKeyframes(frames); + assert(0 <= index && index < (int)frames.size()); + std::set::const_iterator it = frames.begin(); + std::advance(it, index); + return *it; } //--------------------------------------------------------- -int TParamSet::getNextKeyframe(double frame) const -{ - std::set frames; - getKeyframes(frames); - std::set::iterator it = frames.upper_bound(frame); - if (it == frames.end()) - return -1; - else - return std::distance(frames.begin(), it); +int TParamSet::getNextKeyframe(double frame) const { + std::set frames; + getKeyframes(frames); + std::set::iterator it = frames.upper_bound(frame); + if (it == frames.end()) + return -1; + else + return std::distance(frames.begin(), it); } //--------------------------------------------------------- -int TParamSet::getPrevKeyframe(double frame) const -{ - std::set frames; - getKeyframes(frames); - std::set::iterator it = frames.lower_bound(frame); - if (it == frames.begin()) - return -1; - else { - --it; - return std::distance(frames.begin(), it); - } +int TParamSet::getPrevKeyframe(double frame) const { + std::set frames; + getKeyframes(frames); + std::set::iterator it = frames.lower_bound(frame); + if (it == frames.begin()) + return -1; + else { + --it; + return std::distance(frames.begin(), it); + } } //--------------------------------------------------------- -bool TParamSet::hasKeyframes() const -{ - for (int i = 0; i < getParamCount(); i++) - if (getParam(i)->hasKeyframes()) - return true; - return false; +bool TParamSet::hasKeyframes() const { + for (int i = 0; i < getParamCount(); i++) + if (getParam(i)->hasKeyframes()) return true; + return false; } //--------------------------------------------------------- -int TParamSet::getKeyframeCount() const -{ - std::set frames; - getKeyframes(frames); - return frames.size(); +int TParamSet::getKeyframeCount() const { + std::set frames; + getKeyframes(frames); + return frames.size(); } //--------------------------------------------------------- -void TParamSet::deleteKeyframe(double frame) -{ - for (int i = 0; i < getParamCount(); i++) - getParam(i)->deleteKeyframe(frame); +void TParamSet::deleteKeyframe(double frame) { + for (int i = 0; i < getParamCount(); i++) getParam(i)->deleteKeyframe(frame); } //--------------------------------------------------------- -void TParamSet::clearKeyframes() -{ - for (int i = 0; i < getParamCount(); i++) - getParam(i)->clearKeyframes(); +void TParamSet::clearKeyframes() { + for (int i = 0; i < getParamCount(); i++) getParam(i)->clearKeyframes(); } //--------------------------------------------------------- -void TParamSet::assignKeyframe( - double frame, - const TParamP &src, double srcFrame, - bool changedOnly) -{ - TParamSetP paramSetSrc = src; - if (!paramSetSrc) - return; - if (getParamCount() != paramSetSrc->getParamCount()) - return; - for (int i = 0; i < getParamCount(); i++) - getParam(i)->assignKeyframe( - frame, paramSetSrc->getParam(i), srcFrame, changedOnly); +void TParamSet::assignKeyframe(double frame, const TParamP &src, + double srcFrame, bool changedOnly) { + TParamSetP paramSetSrc = src; + if (!paramSetSrc) return; + if (getParamCount() != paramSetSrc->getParamCount()) return; + for (int i = 0; i < getParamCount(); i++) + getParam(i)->assignKeyframe(frame, paramSetSrc->getParam(i), srcFrame, + changedOnly); } //--------------------------------------------------------- -TParam *TParamSet::clone() const -{ - return new TParamSet(*this); -} +TParam *TParamSet::clone() const { return new TParamSet(*this); } //--------------------------------------------------------- -void TParamSet::copy(TParam *src) -{ - TParamSet *p = dynamic_cast(src); - if (!p) - throw TException("invalid source for copy"); - int srcParamCount = p->getParamCount(); - removeAllParam(); - int i; - for (i = 0; i < srcParamCount; i++) { - TParamP param = p->getParam(i); - addParam(param->clone(), param->getName()); - } +void TParamSet::copy(TParam *src) { + TParamSet *p = dynamic_cast(src); + if (!p) throw TException("invalid source for copy"); + int srcParamCount = p->getParamCount(); + removeAllParam(); + int i; + for (i = 0; i < srcParamCount; i++) { + TParamP param = p->getParam(i); + addParam(param->clone(), param->getName()); + } } //--------------------------------------------------------- -void TParamSet::loadData(TIStream &is) -{ - std::string tagName; - is.openChild(tagName); - while (!is.eos()) { - std::string paramName; - is.openChild(paramName); - TPersist *p = 0; - is >> p; - TParam *param = dynamic_cast(p); - assert(param); - addParam(param, paramName); - is.closeChild(); - } - is.closeChild(); +void TParamSet::loadData(TIStream &is) { + std::string tagName; + is.openChild(tagName); + while (!is.eos()) { + std::string paramName; + is.openChild(paramName); + TPersist *p = 0; + is >> p; + TParam *param = dynamic_cast(p); + assert(param); + addParam(param, paramName); + is.closeChild(); + } + is.closeChild(); } //--------------------------------------------------------- -void TParamSet::saveData(TOStream &os) -{ - os.openChild(getName()); - std::vector>::iterator it = m_imp->m_params.begin(); - std::vector>::iterator end = m_imp->m_params.end(); - while (it != end) { - os.openChild(it->second); - //it->first->saveData(os); - os << it->first; - os.closeChild(); - ++it; - } - os.closeChild(); +void TParamSet::saveData(TOStream &os) { + os.openChild(getName()); + std::vector>::iterator it = + m_imp->m_params.begin(); + std::vector>::iterator end = + m_imp->m_params.end(); + while (it != end) { + os.openChild(it->second); + // it->first->saveData(os); + os << it->first; + os.closeChild(); + ++it; + } + os.closeChild(); } //--------------------------------------------------------- -std::string TParamSet::getValueAlias(double frame, int precision) -{ - std::string alias = "("; +std::string TParamSet::getValueAlias(double frame, int precision) { + std::string alias = "("; - std::vector>::iterator end = m_imp->m_params.begin(); - std::advance(end, m_imp->m_params.size() - 1); + std::vector>::iterator end = + m_imp->m_params.begin(); + std::advance(end, m_imp->m_params.size() - 1); - std::vector>::iterator it = m_imp->m_params.begin(); - for (; it != end; ++it) - alias += it->first->getValueAlias(frame, precision) + ","; + std::vector>::iterator it = + m_imp->m_params.begin(); + for (; it != end; ++it) + alias += it->first->getValueAlias(frame, precision) + ","; - alias += it->first->getValueAlias(frame, precision); + alias += it->first->getValueAlias(frame, precision); - alias += ")"; - return alias; + alias += ")"; + return alias; } //--------------------------------------------------------- diff --git a/toonz/sources/common/tparam/tpixelparam.cpp b/toonz/sources/common/tparam/tpixelparam.cpp index bff017f..73a5ca2 100644 --- a/toonz/sources/common/tparam/tpixelparam.cpp +++ b/toonz/sources/common/tparam/tpixelparam.cpp @@ -7,238 +7,202 @@ #include "tpixelutils.h" #include "tstream.h" -class TPixelParamImp -{ +class TPixelParamImp { public: - TPixelParamImp(const TPixel32 &p) - : m_r(new TDoubleParam(p.r / 255.0)), m_g(new TDoubleParam(p.g / 255.0)), m_b(new TDoubleParam(p.b / 255.0)), m_m(new TDoubleParam(p.m / 255.0)), m_isMatteEnabled(true) - { - } - TPixelParamImp(const TPixelParamImp &src) - : m_r(src.m_r->clone()), m_g(src.m_g->clone()), m_b(src.m_b->clone()), m_m(src.m_m->clone()), m_isMatteEnabled(src.m_isMatteEnabled) - { - } - ~TPixelParamImp() {} - TDoubleParamP m_r, m_g, m_b, m_m; - bool m_isMatteEnabled; + TPixelParamImp(const TPixel32 &p) + : m_r(new TDoubleParam(p.r / 255.0)) + , m_g(new TDoubleParam(p.g / 255.0)) + , m_b(new TDoubleParam(p.b / 255.0)) + , m_m(new TDoubleParam(p.m / 255.0)) + , m_isMatteEnabled(true) {} + TPixelParamImp(const TPixelParamImp &src) + : m_r(src.m_r->clone()) + , m_g(src.m_g->clone()) + , m_b(src.m_b->clone()) + , m_m(src.m_m->clone()) + , m_isMatteEnabled(src.m_isMatteEnabled) {} + ~TPixelParamImp() {} + TDoubleParamP m_r, m_g, m_b, m_m; + bool m_isMatteEnabled; }; PERSIST_IDENTIFIER(TPixelParam, "pixelParam") //--------------------------------------------------------- -TPixelParam::TPixelParam(const TPixel32 &p) - : m_data(new TPixelParamImp(p)) -{ - addParam(m_data->m_r, "Red"); - addParam(m_data->m_g, "Green"); - addParam(m_data->m_b, "Blue"); - addParam(m_data->m_m, "Alpha"); - std::string measureName("colorChannel"); - m_data->m_r->setMeasureName(measureName); - m_data->m_g->setMeasureName(measureName); - m_data->m_b->setMeasureName(measureName); - m_data->m_m->setMeasureName(measureName); +TPixelParam::TPixelParam(const TPixel32 &p) : m_data(new TPixelParamImp(p)) { + addParam(m_data->m_r, "Red"); + addParam(m_data->m_g, "Green"); + addParam(m_data->m_b, "Blue"); + addParam(m_data->m_m, "Alpha"); + std::string measureName("colorChannel"); + m_data->m_r->setMeasureName(measureName); + m_data->m_g->setMeasureName(measureName); + m_data->m_b->setMeasureName(measureName); + m_data->m_m->setMeasureName(measureName); } //--------------------------------------------------------- TPixelParam::TPixelParam(const TPixelParam &src) - : TParamSet(src.getName()), m_data(new TPixelParamImp(*src.m_data)) -{ - addParam(m_data->m_r, "Red"); - addParam(m_data->m_g, "Green"); - addParam(m_data->m_b, "Blue"); - addParam(m_data->m_m, "Alpha"); - std::string measureName("colorChannel"); - m_data->m_r->setMeasureName(measureName); - m_data->m_g->setMeasureName(measureName); - m_data->m_b->setMeasureName(measureName); - m_data->m_m->setMeasureName(measureName); + : TParamSet(src.getName()), m_data(new TPixelParamImp(*src.m_data)) { + addParam(m_data->m_r, "Red"); + addParam(m_data->m_g, "Green"); + addParam(m_data->m_b, "Blue"); + addParam(m_data->m_m, "Alpha"); + std::string measureName("colorChannel"); + m_data->m_r->setMeasureName(measureName); + m_data->m_g->setMeasureName(measureName); + m_data->m_b->setMeasureName(measureName); + m_data->m_m->setMeasureName(measureName); } //--------------------------------------------------------- -void TPixelParam::copy(TParam *src) -{ - TPixelParam *p = dynamic_cast(src); - if (!p) - throw TException("invalid source for copy"); - setName(src->getName()); - m_data->m_r->copy(p->m_data->m_r.getPointer()); - m_data->m_g->copy(p->m_data->m_g.getPointer()); - m_data->m_b->copy(p->m_data->m_b.getPointer()); - m_data->m_m->copy(p->m_data->m_m.getPointer()); - std::string measureName("colorChannel"); +void TPixelParam::copy(TParam *src) { + TPixelParam *p = dynamic_cast(src); + if (!p) throw TException("invalid source for copy"); + setName(src->getName()); + m_data->m_r->copy(p->m_data->m_r.getPointer()); + m_data->m_g->copy(p->m_data->m_g.getPointer()); + m_data->m_b->copy(p->m_data->m_b.getPointer()); + m_data->m_m->copy(p->m_data->m_m.getPointer()); + std::string measureName("colorChannel"); - m_data->m_r->setMeasureName(measureName); - m_data->m_g->setMeasureName(measureName); - m_data->m_b->setMeasureName(measureName); - m_data->m_m->setMeasureName(measureName); + m_data->m_r->setMeasureName(measureName); + m_data->m_g->setMeasureName(measureName); + m_data->m_b->setMeasureName(measureName); + m_data->m_m->setMeasureName(measureName); } //--------------------------------------------------------- -TPixelParam::~TPixelParam() -{ - delete m_data; -} +TPixelParam::~TPixelParam() { delete m_data; } //--------------------------------------------------------- -TPixel32 TPixelParam::getDefaultValue() const -{ - TPixelD pixd( - m_data->m_r->getDefaultValue(), - m_data->m_g->getDefaultValue(), - m_data->m_b->getDefaultValue(), - m_data->m_m->getDefaultValue()); - return toPixel32(pixd); +TPixel32 TPixelParam::getDefaultValue() const { + TPixelD pixd(m_data->m_r->getDefaultValue(), m_data->m_g->getDefaultValue(), + m_data->m_b->getDefaultValue(), m_data->m_m->getDefaultValue()); + return toPixel32(pixd); } //--------------------------------------------------------- -void TPixelParam::setDefaultValue(const TPixel32 &p) -{ - TPixelD pixd = toPixelD(p); - m_data->m_r->setDefaultValue(pixd.r); - m_data->m_g->setDefaultValue(pixd.g); - m_data->m_b->setDefaultValue(pixd.b); - m_data->m_m->setDefaultValue(pixd.m); +void TPixelParam::setDefaultValue(const TPixel32 &p) { + TPixelD pixd = toPixelD(p); + m_data->m_r->setDefaultValue(pixd.r); + m_data->m_g->setDefaultValue(pixd.g); + m_data->m_b->setDefaultValue(pixd.b); + m_data->m_m->setDefaultValue(pixd.m); } //--------------------------------------------------------- -TPixelD TPixelParam::getValueD(double frame) const -{ - return TPixelD(m_data->m_r->getValue(frame), m_data->m_g->getValue(frame), - m_data->m_b->getValue(frame), m_data->m_m->getValue(frame)); +TPixelD TPixelParam::getValueD(double frame) const { + return TPixelD(m_data->m_r->getValue(frame), m_data->m_g->getValue(frame), + m_data->m_b->getValue(frame), m_data->m_m->getValue(frame)); } //--------------------------------------------------------- -TPixel32 TPixelParam::getValue(double frame) const -{ - return toPixel32(getValueD(frame)); +TPixel32 TPixelParam::getValue(double frame) const { + return toPixel32(getValueD(frame)); } //--------------------------------------------------------- -TPixel64 TPixelParam::getValue64(double frame) const -{ - return toPixel64(getValueD(frame)); +TPixel64 TPixelParam::getValue64(double frame) const { + return toPixel64(getValueD(frame)); } //--------------------------------------------------------- -TPixel32 TPixelParam::getPremultipliedValue(double frame) const -{ - return premultiply(getValue(frame)); +TPixel32 TPixelParam::getPremultipliedValue(double frame) const { + return premultiply(getValue(frame)); } //--------------------------------------------------------- -bool TPixelParam::setValueD(double frame, const TPixelD &p) -{ - beginParameterChange(); - m_data->m_r->setValue(frame, p.r); - m_data->m_g->setValue(frame, p.g); - m_data->m_b->setValue(frame, p.b); - m_data->m_m->setValue(frame, p.m); - endParameterChange(); - return true; +bool TPixelParam::setValueD(double frame, const TPixelD &p) { + beginParameterChange(); + m_data->m_r->setValue(frame, p.r); + m_data->m_g->setValue(frame, p.g); + m_data->m_b->setValue(frame, p.b); + m_data->m_m->setValue(frame, p.m); + endParameterChange(); + return true; } //--------------------------------------------------------- -bool TPixelParam::setValue(double frame, const TPixel32 &pix) -{ - return setValueD(frame, toPixelD(pix)); +bool TPixelParam::setValue(double frame, const TPixel32 &pix) { + return setValueD(frame, toPixelD(pix)); } //--------------------------------------------------------- -bool TPixelParam::setValue64(double frame, const TPixel64 &pix) -{ - return setValueD(frame, toPixelD(pix)); +bool TPixelParam::setValue64(double frame, const TPixel64 &pix) { + return setValueD(frame, toPixelD(pix)); } //--------------------------------------------------------- -void TPixelParam::loadData(TIStream &is) -{ - std::string childName; - while (is.openChild(childName)) { - if (childName == "red") - m_data->m_r->loadData(is); - else if (childName == "green") - m_data->m_g->loadData(is); - else if (childName == "blue") - m_data->m_b->loadData(is); - else if (childName == "matte") - m_data->m_m->loadData(is); - else - throw TException("unknown channel name: " + childName); - is.closeChild(); - } +void TPixelParam::loadData(TIStream &is) { + std::string childName; + while (is.openChild(childName)) { + if (childName == "red") + m_data->m_r->loadData(is); + else if (childName == "green") + m_data->m_g->loadData(is); + else if (childName == "blue") + m_data->m_b->loadData(is); + else if (childName == "matte") + m_data->m_m->loadData(is); + else + throw TException("unknown channel name: " + childName); + is.closeChild(); + } } //--------------------------------------------------------- -void TPixelParam::saveData(TOStream &os) -{ - os.openChild("red"); - m_data->m_r->saveData(os); - os.closeChild(); - os.openChild("green"); - m_data->m_g->saveData(os); - os.closeChild(); - os.openChild("blue"); - m_data->m_b->saveData(os); - os.closeChild(); - os.openChild("matte"); - m_data->m_m->saveData(os); - os.closeChild(); +void TPixelParam::saveData(TOStream &os) { + os.openChild("red"); + m_data->m_r->saveData(os); + os.closeChild(); + os.openChild("green"); + m_data->m_g->saveData(os); + os.closeChild(); + os.openChild("blue"); + m_data->m_b->saveData(os); + os.closeChild(); + os.openChild("matte"); + m_data->m_m->saveData(os); + os.closeChild(); } //--------------------------------------------------------- -TDoubleParamP &TPixelParam::getRed() -{ - return m_data->m_r; -} +TDoubleParamP &TPixelParam::getRed() { return m_data->m_r; } //--------------------------------------------------------- -TDoubleParamP &TPixelParam::getGreen() -{ - return m_data->m_g; -} +TDoubleParamP &TPixelParam::getGreen() { return m_data->m_g; } //--------------------------------------------------------- -TDoubleParamP &TPixelParam::getBlue() -{ - return m_data->m_b; -} +TDoubleParamP &TPixelParam::getBlue() { return m_data->m_b; } //--------------------------------------------------------- -TDoubleParamP &TPixelParam::getMatte() -{ - return m_data->m_m; -} +TDoubleParamP &TPixelParam::getMatte() { return m_data->m_m; } //--------------------------------------------------------- -void TPixelParam::enableMatte(bool on) -{ - m_data->m_isMatteEnabled = on; - if (on == false) - m_data->m_m = new TDoubleParam(255.0); +void TPixelParam::enableMatte(bool on) { + m_data->m_isMatteEnabled = on; + if (on == false) m_data->m_m = new TDoubleParam(255.0); } //--------------------------------------------------------- -bool TPixelParam::isMatteEnabled() const -{ - return m_data->m_isMatteEnabled; -} +bool TPixelParam::isMatteEnabled() const { return m_data->m_isMatteEnabled; } diff --git a/toonz/sources/common/tparam/tpointparam.cpp b/toonz/sources/common/tparam/tpointparam.cpp index 03b7abd..5f5ef56 100644 --- a/toonz/sources/common/tparam/tpointparam.cpp +++ b/toonz/sources/common/tparam/tpointparam.cpp @@ -8,19 +8,14 @@ //========================================================= -class TPointParamImp -{ +class TPointParamImp { public: - TPointParamImp(const TPointD &p) - : m_x(new TDoubleParam(p.x)), m_y(new TDoubleParam(p.y)) - { - } - TPointParamImp(const TPointParamImp &src) - : m_x(src.m_x->clone()), m_y(src.m_y->clone()) - { - } - ~TPointParamImp() {} - TDoubleParamP m_x, m_y; + TPointParamImp(const TPointD &p) + : m_x(new TDoubleParam(p.x)), m_y(new TDoubleParam(p.y)) {} + TPointParamImp(const TPointParamImp &src) + : m_x(src.m_x->clone()), m_y(src.m_y->clone()) {} + ~TPointParamImp() {} + TDoubleParamP m_x, m_y; }; //--------------------------------------------------------- @@ -28,111 +23,95 @@ public: PERSIST_IDENTIFIER(TPointParam, "pointParam") TPointParam::TPointParam(const TPointD &p, bool from_plugin) - : m_data(new TPointParamImp(p)), m_from_plugin(from_plugin) -{ - addParam(m_data->m_x, "x"); - addParam(m_data->m_y, "y"); + : m_data(new TPointParamImp(p)), m_from_plugin(from_plugin) { + addParam(m_data->m_x, "x"); + addParam(m_data->m_y, "y"); } //--------------------------------------------------------- TPointParam::TPointParam(const TPointParam &src) - : TParamSet(src.getName()), m_data(new TPointParamImp(*src.m_data)), m_from_plugin(src.m_from_plugin) -{ - addParam(m_data->m_x, "x"); - addParam(m_data->m_y, "y"); + : TParamSet(src.getName()) + , m_data(new TPointParamImp(*src.m_data)) + , m_from_plugin(src.m_from_plugin) { + addParam(m_data->m_x, "x"); + addParam(m_data->m_y, "y"); } //--------------------------------------------------------- -TPointParam::~TPointParam() -{ - delete m_data; -} +TPointParam::~TPointParam() { delete m_data; } //--------------------------------------------------------- -void TPointParam::copy(TParam *src) -{ - TPointParam *p = dynamic_cast(src); - if (!p) - throw TException("invalid source for copy"); - setName(src->getName()); - m_data->m_x->copy(p->m_data->m_x.getPointer()); - m_data->m_y->copy(p->m_data->m_y.getPointer()); +void TPointParam::copy(TParam *src) { + TPointParam *p = dynamic_cast(src); + if (!p) throw TException("invalid source for copy"); + setName(src->getName()); + m_data->m_x->copy(p->m_data->m_x.getPointer()); + m_data->m_y->copy(p->m_data->m_y.getPointer()); } //--------------------------------------------------------- -TPointD TPointParam::getDefaultValue() const -{ - return TPointD(m_data->m_x->getDefaultValue(), m_data->m_y->getDefaultValue()); +TPointD TPointParam::getDefaultValue() const { + return TPointD(m_data->m_x->getDefaultValue(), + m_data->m_y->getDefaultValue()); } //--------------------------------------------------------- -TPointD TPointParam::getValue(double frame) const -{ - return TPointD(m_data->m_x->getValue(frame), m_data->m_y->getValue(frame)); +TPointD TPointParam::getValue(double frame) const { + return TPointD(m_data->m_x->getValue(frame), m_data->m_y->getValue(frame)); } //--------------------------------------------------------- -bool TPointParam::setValue(double frame, const TPointD &p) -{ - beginParameterChange(); - m_data->m_x->setValue(frame, p.x); - m_data->m_y->setValue(frame, p.y); - endParameterChange(); - return true; +bool TPointParam::setValue(double frame, const TPointD &p) { + beginParameterChange(); + m_data->m_x->setValue(frame, p.x); + m_data->m_y->setValue(frame, p.y); + endParameterChange(); + return true; } //--------------------------------------------------------- -void TPointParam::setDefaultValue(const TPointD &p) -{ - m_data->m_x->setDefaultValue(p.x); - m_data->m_y->setDefaultValue(p.y); +void TPointParam::setDefaultValue(const TPointD &p) { + m_data->m_x->setDefaultValue(p.x); + m_data->m_y->setDefaultValue(p.y); } //--------------------------------------------------------- -void TPointParam::loadData(TIStream &is) -{ - std::string childName; - while (is.openChild(childName)) { - if (childName == "x") - m_data->m_x->loadData(is); - else if (childName == "y") - m_data->m_y->loadData(is); - else - throw TException("unknown coord"); - is.closeChild(); - } +void TPointParam::loadData(TIStream &is) { + std::string childName; + while (is.openChild(childName)) { + if (childName == "x") + m_data->m_x->loadData(is); + else if (childName == "y") + m_data->m_y->loadData(is); + else + throw TException("unknown coord"); + is.closeChild(); + } } //--------------------------------------------------------- -void TPointParam::saveData(TOStream &os) -{ - os.openChild("x"); - m_data->m_x->saveData(os); - os.closeChild(); - os.openChild("y"); - m_data->m_y->saveData(os); - os.closeChild(); +void TPointParam::saveData(TOStream &os) { + os.openChild("x"); + m_data->m_x->saveData(os); + os.closeChild(); + os.openChild("y"); + m_data->m_y->saveData(os); + os.closeChild(); } //--------------------------------------------------------- -TDoubleParamP &TPointParam::getX() -{ - return m_data->m_x; -} +TDoubleParamP &TPointParam::getX() { return m_data->m_x; } //--------------------------------------------------------- -TDoubleParamP &TPointParam::getY() -{ - return m_data->m_y; -} +TDoubleParamP &TPointParam::getY() { return m_data->m_y; } diff --git a/toonz/sources/common/tparam/trangeparam.cpp b/toonz/sources/common/tparam/trangeparam.cpp index 7faaa45..4b7e0c7 100644 --- a/toonz/sources/common/tparam/trangeparam.cpp +++ b/toonz/sources/common/tparam/trangeparam.cpp @@ -7,181 +7,154 @@ //========================================================= -class TRangeParamImp -{ +class TRangeParamImp { public: - TRangeParamImp(const DoublePair &v) - : m_min(new TDoubleParam(v.first)), m_max(new TDoubleParam(v.second)) - { - } - TRangeParamImp(const TRangeParamImp &src) - : m_min(src.m_min->clone()), m_max(src.m_max->clone()) - { - } - - ~TRangeParamImp() {} - - TDoubleParamP m_min, m_max; + TRangeParamImp(const DoublePair &v) + : m_min(new TDoubleParam(v.first)), m_max(new TDoubleParam(v.second)) {} + TRangeParamImp(const TRangeParamImp &src) + : m_min(src.m_min->clone()), m_max(src.m_max->clone()) {} + + ~TRangeParamImp() {} + + TDoubleParamP m_min, m_max; }; //--------------------------------------------------------- PERSIST_IDENTIFIER(TRangeParam, "rangeParam") -TRangeParam::TRangeParam(const DoublePair &v) - : m_data(new TRangeParamImp(v)) -{ - addParam(m_data->m_min, "min"); - addParam(m_data->m_max, "max"); +TRangeParam::TRangeParam(const DoublePair &v) : m_data(new TRangeParamImp(v)) { + addParam(m_data->m_min, "min"); + addParam(m_data->m_max, "max"); } //--------------------------------------------------------- TRangeParam::TRangeParam(const TRangeParam &src) - : TParamSet(src.getName()), m_data(new TRangeParamImp(*src.m_data)) -{ - addParam(m_data->m_min, "min"); - addParam(m_data->m_max, "max"); + : TParamSet(src.getName()), m_data(new TRangeParamImp(*src.m_data)) { + addParam(m_data->m_min, "min"); + addParam(m_data->m_max, "max"); } //--------------------------------------------------------- -TRangeParam::~TRangeParam() -{ - delete m_data; -} +TRangeParam::~TRangeParam() { delete m_data; } //--------------------------------------------------------- -void TRangeParam::copy(TParam *src) -{ - TRangeParam *p = dynamic_cast(src); - if (!p) - throw TException("invalid source for copy"); - setName(src->getName()); - m_data->m_min->copy(p->m_data->m_min.getPointer()); - m_data->m_max->copy(p->m_data->m_max.getPointer()); +void TRangeParam::copy(TParam *src) { + TRangeParam *p = dynamic_cast(src); + if (!p) throw TException("invalid source for copy"); + setName(src->getName()); + m_data->m_min->copy(p->m_data->m_min.getPointer()); + m_data->m_max->copy(p->m_data->m_max.getPointer()); } //--------------------------------------------------------- -DoublePair TRangeParam::getDefaultValue() const -{ - return DoublePair(m_data->m_min->getDefaultValue(), m_data->m_max->getDefaultValue()); +DoublePair TRangeParam::getDefaultValue() const { + return DoublePair(m_data->m_min->getDefaultValue(), + m_data->m_max->getDefaultValue()); } //--------------------------------------------------------- -DoublePair TRangeParam::getValue(double frame) const -{ - return DoublePair(m_data->m_min->getValue(frame), m_data->m_max->getValue(frame)); +DoublePair TRangeParam::getValue(double frame) const { + return DoublePair(m_data->m_min->getValue(frame), + m_data->m_max->getValue(frame)); } //--------------------------------------------------------- -bool TRangeParam::setValue(double frame, const DoublePair &v) -{ - beginParameterChange(); - m_data->m_min->setValue(frame, v.first); - m_data->m_max->setValue(frame, v.second); - endParameterChange(); - return true; +bool TRangeParam::setValue(double frame, const DoublePair &v) { + beginParameterChange(); + m_data->m_min->setValue(frame, v.first); + m_data->m_max->setValue(frame, v.second); + endParameterChange(); + return true; } //--------------------------------------------------------- -void TRangeParam::setDefaultValue(const DoublePair &v) -{ - m_data->m_min->setDefaultValue(v.first); - m_data->m_max->setDefaultValue(v.second); +void TRangeParam::setDefaultValue(const DoublePair &v) { + m_data->m_min->setDefaultValue(v.first); + m_data->m_max->setDefaultValue(v.second); } //--------------------------------------------------------- -void TRangeParam::loadData(TIStream &is) -{ - std::string childName; - while (is.openChild(childName)) { - if (childName == "min") - m_data->m_min->loadData(is); - else if (childName == "max") - m_data->m_max->loadData(is); - else - throw TException("unknown tag"); - is.closeChild(); - } +void TRangeParam::loadData(TIStream &is) { + std::string childName; + while (is.openChild(childName)) { + if (childName == "min") + m_data->m_min->loadData(is); + else if (childName == "max") + m_data->m_max->loadData(is); + else + throw TException("unknown tag"); + is.closeChild(); + } } //--------------------------------------------------------- -void TRangeParam::saveData(TOStream &os) -{ - os.openChild("min"); - m_data->m_min->saveData(os); - os.closeChild(); - os.openChild("max"); - m_data->m_max->saveData(os); - os.closeChild(); +void TRangeParam::saveData(TOStream &os) { + os.openChild("min"); + m_data->m_min->saveData(os); + os.closeChild(); + os.openChild("max"); + m_data->m_max->saveData(os); + os.closeChild(); } //--------------------------------------------------------- -TDoubleParamP &TRangeParam::getMin() -{ - return m_data->m_min; -} +TDoubleParamP &TRangeParam::getMin() { return m_data->m_min; } //--------------------------------------------------------- -TDoubleParamP &TRangeParam::getMax() -{ - return m_data->m_max; -} +TDoubleParamP &TRangeParam::getMax() { return m_data->m_max; } #ifdef BUTTA //--------------------------------------------------------- -int TRangeParam::getNextKeyframe(double frame) const -{ - int f_min = m_data->m_min->getNextKeyframe(frame); - int f_max = m_data->m_max->getNextKeyframe(frame); - if (f_min <= f_max && f_min != -1) - return f_min; - else { - if (f_max != -1) - return f_max; - else - return -1; - } +int TRangeParam::getNextKeyframe(double frame) const { + int f_min = m_data->m_min->getNextKeyframe(frame); + int f_max = m_data->m_max->getNextKeyframe(frame); + if (f_min <= f_max && f_min != -1) + return f_min; + else { + if (f_max != -1) + return f_max; + else + return -1; + } } //--------------------------------------------------------- -int TRangeParam::getPrevKeyframe(double frame) const -{ - int f_min = m_data->m_min->getPrevKeyframe(frame); - int f_max = m_data->m_max->getPrevKeyframe(frame); - if (f_min >= f_max) - return f_min; - else - return f_max; +int TRangeParam::getPrevKeyframe(double frame) const { + int f_min = m_data->m_min->getPrevKeyframe(frame); + int f_max = m_data->m_max->getPrevKeyframe(frame); + if (f_min >= f_max) + return f_min; + else + return f_max; } //--------------------------------------------------------- -void TRangeParam::deleteKeyframe(double frame, bool undoing) -{ - m_data->m_min->deleteKeyframe(frame, undoing); - m_data->m_max->deleteKeyframe(frame, undoing); +void TRangeParam::deleteKeyframe(double frame, bool undoing) { + m_data->m_min->deleteKeyframe(frame, undoing); + m_data->m_max->deleteKeyframe(frame, undoing); } //--------------------------------------------------------- -bool TRangeParam::isKeyframe(double frame) const -{ - bool min, max; - min = m_data->m_min->isKeyframe(frame); - max = m_data->m_max->isKeyframe(frame); - return (min || max); +bool TRangeParam::isKeyframe(double frame) const { + bool min, max; + min = m_data->m_min->isKeyframe(frame); + max = m_data->m_max->isKeyframe(frame); + return (min || max); } //--------------------------------------------------------- diff --git a/toonz/sources/common/tparam/tspectrumparam.cpp b/toonz/sources/common/tparam/tspectrumparam.cpp index 8bee58c..b3f0a82 100644 --- a/toonz/sources/common/tparam/tspectrumparam.cpp +++ b/toonz/sources/common/tparam/tspectrumparam.cpp @@ -17,94 +17,79 @@ typedef std::pair ColorKeyParam; //========================================================= -class TSpectrumParamImp -{ - TSpectrumParam *m_sp; +class TSpectrumParamImp { + TSpectrumParam *m_sp; - std::vector m_keys; + std::vector m_keys; public: - bool m_draggingEnabled; - bool m_notificationEnabled; - bool m_isMatteEnabled; + bool m_draggingEnabled; + bool m_notificationEnabled; + bool m_isMatteEnabled; - std::set m_observers; + std::set m_observers; public: - TSpectrumParamImp(TSpectrumParam *sp) : m_sp(sp), m_keys(), m_draggingEnabled(false), m_notificationEnabled(true), m_isMatteEnabled(true) - { - } - - TSpectrumParamImp(const TSpectrumParamImp &s) - { - copy(s); - } - - void copy(const TSpectrumParamImp &src) - { - m_keys.clear(); - - std::vector::const_iterator it = src.m_keys.begin(); - for (; it != src.m_keys.end(); ++it) { - TDoubleParamP s(it->first->clone()); - TPixelParamP c(it->second->clone()); - m_keys.push_back(std::make_pair(s, c)); - } - } - - void addKey(const ColorKeyParam &colorKey) - { - /* - m_sp->addParam(colorKey.first); - m_sp->addParam(colorKey.second); + TSpectrumParamImp(TSpectrumParam *sp) + : m_sp(sp) + , m_keys() + , m_draggingEnabled(false) + , m_notificationEnabled(true) + , m_isMatteEnabled(true) {} + + TSpectrumParamImp(const TSpectrumParamImp &s) { copy(s); } + + void copy(const TSpectrumParamImp &src) { + m_keys.clear(); + + std::vector::const_iterator it = src.m_keys.begin(); + for (; it != src.m_keys.end(); ++it) { + TDoubleParamP s(it->first->clone()); + TPixelParamP c(it->second->clone()); + m_keys.push_back(std::make_pair(s, c)); + } + } + + void addKey(const ColorKeyParam &colorKey) { + /* +m_sp->addParam(colorKey.first); +m_sp->addParam(colorKey.second); */ - m_keys.push_back(colorKey); - } - - void insertKey(int index, ColorKeyParam &colorKey) - { - /* - m_sp->addParam(colorKey.first); - m_sp->addParam(colorKey.second); + m_keys.push_back(colorKey); + } + + void insertKey(int index, ColorKeyParam &colorKey) { + /* +m_sp->addParam(colorKey.first); +m_sp->addParam(colorKey.second); */ - std::vector::iterator it = m_keys.begin() + index; - m_keys.insert(it, colorKey); - } - - void eraseKey(int index) - { - std::vector::iterator colorKeyIt = m_keys.begin() + index; - /* - m_sp->removeParam((*colorKeyIt).first); - m_sp->removeParam((*colorKeyIt).second); + std::vector::iterator it = m_keys.begin() + index; + m_keys.insert(it, colorKey); + } + + void eraseKey(int index) { + std::vector::iterator colorKeyIt = m_keys.begin() + index; + /* +m_sp->removeParam((*colorKeyIt).first); +m_sp->removeParam((*colorKeyIt).second); */ - m_keys.erase(colorKeyIt); - } - - int getKeyCount() const - { - return m_keys.size(); - } - - ColorKeyParam getKey(int index) const - { - return m_keys[index]; - } - - void clearKeys() - { - m_keys.clear(); - } - - void notify(const TParamChange &change) - { - for (std::set::iterator it = m_observers.begin(); - it != m_observers.end(); ++it) - (*it)->onChange(change); - } + m_keys.erase(colorKeyIt); + } + + int getKeyCount() const { return m_keys.size(); } + + ColorKeyParam getKey(int index) const { return m_keys[index]; } + + void clearKeys() { m_keys.clear(); } + + void notify(const TParamChange &change) { + for (std::set::iterator it = m_observers.begin(); + it != m_observers.end(); ++it) + (*it)->onChange(change); + } private: - TSpectrumParamImp &operator=(const TSpectrumParamImp &); //not implemented + TSpectrumParamImp &operator=(const TSpectrumParamImp &); // not implemented }; //========================================================= @@ -113,489 +98,439 @@ PERSIST_IDENTIFIER(TSpectrumParam, "spectrumParam") //--------------------------------------------------------- -TSpectrumParam::TSpectrumParam(): m_imp(new TSpectrumParamImp(this)) //brutto... +TSpectrumParam::TSpectrumParam() + : m_imp(new TSpectrumParamImp(this)) // brutto... { - ColorKeyParam ck1(TDoubleParamP(0.0), TPixelParamP(TPixel32::Black)); - ColorKeyParam ck2(TDoubleParamP(1.0), TPixelParamP(TPixel32::White)); - m_imp->addKey(ck1); - m_imp->addKey(ck2); + ColorKeyParam ck1(TDoubleParamP(0.0), TPixelParamP(TPixel32::Black)); + ColorKeyParam ck2(TDoubleParamP(1.0), TPixelParamP(TPixel32::White)); + m_imp->addKey(ck1); + m_imp->addKey(ck2); } //--------------------------------------------------------- TSpectrumParam::TSpectrumParam(const TSpectrumParam &src) - : TParam(src.getName()) - , m_imp(new TSpectrumParamImp(*src.m_imp)) -{ -} + : TParam(src.getName()), m_imp(new TSpectrumParamImp(*src.m_imp)) {} //--------------------------------------------------------- -void TSpectrumParam::addObserver(TParamObserver *obs) -{ - m_imp->m_observers.insert(obs); +void TSpectrumParam::addObserver(TParamObserver *obs) { + m_imp->m_observers.insert(obs); } //--------------------------------------------------------- -void TSpectrumParam::removeObserver(TParamObserver *obs) -{ - m_imp->m_observers.erase(obs); +void TSpectrumParam::removeObserver(TParamObserver *obs) { + m_imp->m_observers.erase(obs); } //--------------------------------------------------------- TSpectrumParam::TSpectrumParam(int keyCount, TSpectrum::ColorKey keys[]) - : m_imp(new TSpectrumParamImp(this)) -{ - for (int i = 0; i < keyCount; i++) { - double v = keys[i].first; - TPixel32 pix = keys[i].second; - TDoubleParamP dp(v); - TPixelParamP pp(pix); - pp->enableMatte(m_imp->m_isMatteEnabled); - ColorKeyParam ck(dp, pp); - m_imp->addKey(ck); - } + : m_imp(new TSpectrumParamImp(this)) { + for (int i = 0; i < keyCount; i++) { + double v = keys[i].first; + TPixel32 pix = keys[i].second; + TDoubleParamP dp(v); + TPixelParamP pp(pix); + pp->enableMatte(m_imp->m_isMatteEnabled); + ColorKeyParam ck(dp, pp); + m_imp->addKey(ck); + } } //--------------------------------------------------------- -void TSpectrumParam::copy(TParam *src) -{ - TSpectrumParam *p = dynamic_cast(src); - if (!p) - throw TException("invalid source for copy"); - setName(src->getName()); - m_imp->copy(*(p->m_imp)); +void TSpectrumParam::copy(TParam *src) { + TSpectrumParam *p = dynamic_cast(src); + if (!p) throw TException("invalid source for copy"); + setName(src->getName()); + m_imp->copy(*(p->m_imp)); } //--------------------------------------------------------- -TSpectrumParam::~TSpectrumParam() -{ -} +TSpectrumParam::~TSpectrumParam() {} //--------------------------------------------------------- -TSpectrum TSpectrumParam::getValue(double frame) const -{ - assert(m_imp); - std::vector keys; - int keyCount = m_imp->getKeyCount(); - for (int i = 0; i < keyCount; i++) { - ColorKeyParam paramKey = m_imp->getKey(i); - TSpectrum::ColorKey key( - paramKey.first->getValue(frame), - paramKey.second->getValue(frame)); - keys.push_back(key); - } - return TSpectrum(keys.size(), &keys[0]); +TSpectrum TSpectrumParam::getValue(double frame) const { + assert(m_imp); + std::vector keys; + int keyCount = m_imp->getKeyCount(); + for (int i = 0; i < keyCount; i++) { + ColorKeyParam paramKey = m_imp->getKey(i); + TSpectrum::ColorKey key(paramKey.first->getValue(frame), + paramKey.second->getValue(frame)); + keys.push_back(key); + } + return TSpectrum(keys.size(), &keys[0]); } //--------------------------------------------------------- -TSpectrum64 TSpectrumParam::getValue64(double frame) const -{ - assert(m_imp); - std::vector keys; - int keyCount = m_imp->getKeyCount(); - for (int i = 0; i < keyCount; i++) { - ColorKeyParam paramKey = m_imp->getKey(i); - TSpectrum64::ColorKey key( - paramKey.first->getValue(frame), - toPixel64(paramKey.second->getValue(frame))); - keys.push_back(key); - } - return TSpectrum64(keys.size(), &keys[0]); +TSpectrum64 TSpectrumParam::getValue64(double frame) const { + assert(m_imp); + std::vector keys; + int keyCount = m_imp->getKeyCount(); + for (int i = 0; i < keyCount; i++) { + ColorKeyParam paramKey = m_imp->getKey(i); + TSpectrum64::ColorKey key(paramKey.first->getValue(frame), + toPixel64(paramKey.second->getValue(frame))); + keys.push_back(key); + } + return TSpectrum64(keys.size(), &keys[0]); } //--------------------------------------------------------- -void TSpectrumParam::setValue(double frame, const TSpectrum &spectrum, bool undoing) -{ - assert(getKeyCount() == spectrum.getKeyCount()); - int keyCount = getKeyCount(); - for (int i = 0; i < keyCount; i++) { - TSpectrum::Key key = spectrum.getKey(i); - setValue(frame, i, key.first, key.second, undoing); - } +void TSpectrumParam::setValue(double frame, const TSpectrum &spectrum, + bool undoing) { + assert(getKeyCount() == spectrum.getKeyCount()); + int keyCount = getKeyCount(); + for (int i = 0; i < keyCount; i++) { + TSpectrum::Key key = spectrum.getKey(i); + setValue(frame, i, key.first, key.second, undoing); + } } //--------------------------------------------------------- -TDoubleParamP TSpectrumParam::getPosition(int index) const -{ - assert(index <= m_imp->getKeyCount()); - return m_imp->getKey(index).first; +TDoubleParamP TSpectrumParam::getPosition(int index) const { + assert(index <= m_imp->getKeyCount()); + return m_imp->getKey(index).first; } //--------------------------------------------------------- -TPixelParamP TSpectrumParam::getColor(int index) const -{ - assert(index <= m_imp->getKeyCount()); - return m_imp->getKey(index).second; +TPixelParamP TSpectrumParam::getColor(int index) const { + assert(index <= m_imp->getKeyCount()); + return m_imp->getKey(index).second; } //--------------------------------------------------------- -int TSpectrumParam::getKeyCount() const -{ - assert(m_imp); - return m_imp->getKeyCount(); +int TSpectrumParam::getKeyCount() const { + assert(m_imp); + return m_imp->getKeyCount(); } //--------------------------------------------------------- -void TSpectrumParam::setValue(double frame, int index, double s, const TPixel32 &color, bool undoing) -{ - assert(m_imp); - int keyCount = m_imp->getKeyCount(); - if (index < 0 || index >= keyCount) - throw TException("TSpectrumParam::setValue. Index out of range"); +void TSpectrumParam::setValue(double frame, int index, double s, + const TPixel32 &color, bool undoing) { + assert(m_imp); + int keyCount = m_imp->getKeyCount(); + if (index < 0 || index >= keyCount) + throw TException("TSpectrumParam::setValue. Index out of range"); - ColorKeyParam key = m_imp->getKey(index); + ColorKeyParam key = m_imp->getKey(index); - // beginParameterChange(); - key.first->setValue(frame, s); - key.second->setValue(frame, color); - // endParameterChange(); + // beginParameterChange(); + key.first->setValue(frame, s); + key.second->setValue(frame, color); + // endParameterChange(); - m_imp->notify(TParamChange(this, TParamChange::m_minFrame, TParamChange::m_maxFrame, true, m_imp->m_draggingEnabled, false)); + m_imp->notify(TParamChange(this, TParamChange::m_minFrame, + TParamChange::m_maxFrame, true, + m_imp->m_draggingEnabled, false)); } //--------------------------------------------------------- -void TSpectrumParam::setDefaultValue(const TSpectrum &value) -{ - assert(value.getKeyCount() == getKeyCount()); - for (int i = 0; i < getKeyCount(); i++) { - ColorKeyParam dstKeyParam = m_imp->getKey(i); - TSpectrum::Key srcKey = value.getKey(i); - dstKeyParam.first->setDefaultValue(srcKey.first); - dstKeyParam.second->setDefaultValue(srcKey.second); - } +void TSpectrumParam::setDefaultValue(const TSpectrum &value) { + assert(value.getKeyCount() == getKeyCount()); + for (int i = 0; i < getKeyCount(); i++) { + ColorKeyParam dstKeyParam = m_imp->getKey(i); + TSpectrum::Key srcKey = value.getKey(i); + dstKeyParam.first->setDefaultValue(srcKey.first); + dstKeyParam.second->setDefaultValue(srcKey.second); + } } //--------------------------------------------------------- -void TSpectrumParam::insertKey(int index, double s, const TPixel32 &color) -{ - assert(m_imp); - int keyCount = m_imp->getKeyCount(); - if (index < 0) - index = 0; - else if (index >= keyCount) - index = keyCount; - TDoubleParamP dp(s); - TPixelParamP pp(color); - pp->enableMatte(m_imp->m_isMatteEnabled); - ColorKeyParam ck(dp, pp); +void TSpectrumParam::insertKey(int index, double s, const TPixel32 &color) { + assert(m_imp); + int keyCount = m_imp->getKeyCount(); + if (index < 0) + index = 0; + else if (index >= keyCount) + index = keyCount; + TDoubleParamP dp(s); + TPixelParamP pp(color); + pp->enableMatte(m_imp->m_isMatteEnabled); + ColorKeyParam ck(dp, pp); - m_imp->insertKey(index, ck); + m_imp->insertKey(index, ck); } //--------------------------------------------------------- -void TSpectrumParam::addKey(double s, const TPixel32 &color) -{ - /* - assert(m_imp); - insertKey(m_imp->getKeyCount(), s,color); +void TSpectrumParam::addKey(double s, const TPixel32 &color) { + /* +assert(m_imp); +insertKey(m_imp->getKeyCount(), s,color); */ - int index = m_imp->getKeyCount(); - assert(m_imp); - int keyCount = m_imp->getKeyCount(); - if (index < 0) - index = 0; - else if (index >= keyCount) - index = keyCount; - TDoubleParamP dp(s); - TPixelParamP pp(color); - pp->enableMatte(m_imp->m_isMatteEnabled); - ColorKeyParam ck(dp, pp); + int index = m_imp->getKeyCount(); + assert(m_imp); + int keyCount = m_imp->getKeyCount(); + if (index < 0) + index = 0; + else if (index >= keyCount) + index = keyCount; + TDoubleParamP dp(s); + TPixelParamP pp(color); + pp->enableMatte(m_imp->m_isMatteEnabled); + ColorKeyParam ck(dp, pp); - m_imp->insertKey(index, ck); + m_imp->insertKey(index, ck); } //--------------------------------------------------------- -void TSpectrumParam::removeKey(int index) -{ - assert(m_imp); - int keyCount = m_imp->getKeyCount(); - if (index < 0 || index >= keyCount) - throw TException("TSpectrumParam::removeKey. Index out of range"); - m_imp->eraseKey(index); +void TSpectrumParam::removeKey(int index) { + assert(m_imp); + int keyCount = m_imp->getKeyCount(); + if (index < 0 || index >= keyCount) + throw TException("TSpectrumParam::removeKey. Index out of range"); + m_imp->eraseKey(index); } //--------------------------------------------------------- -bool TSpectrumParam::isKeyframe(double frame) const -{ - int keyCount = m_imp->getKeyCount(); - for (int i = 0; i < keyCount; i++) { - ColorKeyParam currentKey = m_imp->getKey(i); - if (currentKey.first->isKeyframe(frame)) - return true; - if (currentKey.second->isKeyframe(frame)) - return true; - } - return false; +bool TSpectrumParam::isKeyframe(double frame) const { + int keyCount = m_imp->getKeyCount(); + for (int i = 0; i < keyCount; i++) { + ColorKeyParam currentKey = m_imp->getKey(i); + if (currentKey.first->isKeyframe(frame)) return true; + if (currentKey.second->isKeyframe(frame)) return true; + } + return false; } //--------------------------------------------------------- -void TSpectrumParam::deleteKeyframe(double frame) -{ - int keyCount = m_imp->getKeyCount(); - for (int i = 0; i < keyCount; i++) { - ColorKeyParam currentKey = m_imp->getKey(i); - currentKey.first->deleteKeyframe(frame); - currentKey.second->deleteKeyframe(frame); - } +void TSpectrumParam::deleteKeyframe(double frame) { + int keyCount = m_imp->getKeyCount(); + for (int i = 0; i < keyCount; i++) { + ColorKeyParam currentKey = m_imp->getKey(i); + currentKey.first->deleteKeyframe(frame); + currentKey.second->deleteKeyframe(frame); + } } //--------------------------------------------------------- -void TSpectrumParam::clearKeyframes() -{ - assert(m_imp); +void TSpectrumParam::clearKeyframes() { + assert(m_imp); - int k, keyCount = m_imp->getKeyCount(); - for (k = 0; k < keyCount; ++k) { - const ColorKeyParam &key = m_imp->getKey(k); + int k, keyCount = m_imp->getKeyCount(); + for (k = 0; k < keyCount; ++k) { + const ColorKeyParam &key = m_imp->getKey(k); - key.first->clearKeyframes(); - key.second->clearKeyframes(); - } + key.first->clearKeyframes(); + key.second->clearKeyframes(); + } - m_imp->notify(TParamChange(this, TParamChange::m_minFrame, TParamChange::m_maxFrame, true, m_imp->m_draggingEnabled, false)); + m_imp->notify(TParamChange(this, TParamChange::m_minFrame, + TParamChange::m_maxFrame, true, + m_imp->m_draggingEnabled, false)); } //--------------------------------------------------------- -void TSpectrumParam::assignKeyframe( - double frame, - const TParamP &src, double srcFrame, - bool changedOnly) -{ - TSpectrumParamP spectrum = src; - if (!spectrum) - return; - int keyCount = m_imp->getKeyCount(); - if (keyCount != spectrum->m_imp->getKeyCount()) - return; - for (int i = 0; i < keyCount; i++) { - ColorKeyParam dstKey = m_imp->getKey(i); - ColorKeyParam srcKey = spectrum->m_imp->getKey(i); - dstKey.first->setValue(frame, srcKey.first->getValue(srcFrame)); - dstKey.second->setValue(frame, srcKey.second->getValue(srcFrame)); - } +void TSpectrumParam::assignKeyframe(double frame, const TParamP &src, + double srcFrame, bool changedOnly) { + TSpectrumParamP spectrum = src; + if (!spectrum) return; + int keyCount = m_imp->getKeyCount(); + if (keyCount != spectrum->m_imp->getKeyCount()) return; + for (int i = 0; i < keyCount; i++) { + ColorKeyParam dstKey = m_imp->getKey(i); + ColorKeyParam srcKey = spectrum->m_imp->getKey(i); + dstKey.first->setValue(frame, srcKey.first->getValue(srcFrame)); + dstKey.second->setValue(frame, srcKey.second->getValue(srcFrame)); + } } //--------------------------------------------------------- -void TSpectrumParam::loadData(TIStream &is) -{ - assert(m_imp); - m_imp->clearKeys(); - std::string tagName; - is.openChild(tagName); - assert(tagName == "spectrum"); - while (!is.eos()) { - TDoubleParamP pos(0.0); - TPixelParamP color(TPixel32::Black); - is.openChild(tagName); - pos->loadData(is); - is.closeChild(); - is.openChild(tagName); - color->loadData(is); - is.closeChild(); - ColorKeyParam ck(pos, color); - m_imp->addKey(ck); - } - is.closeChild(); -} - -//--------------------------------------------------------- - -void TSpectrumParam::saveData(TOStream &os) -{ - assert(m_imp); - int keyCount = m_imp->getKeyCount(); - os.openChild("spectrum"); - for (int i = 0; i < keyCount; i++) { - ColorKeyParam key = m_imp->getKey(i); - os.openChild("s_value"); - key.first->saveData(os); - os.closeChild(); - os.openChild("col_value"); - key.second->saveData(os); - os.closeChild(); - } - os.closeChild(); +void TSpectrumParam::loadData(TIStream &is) { + assert(m_imp); + m_imp->clearKeys(); + std::string tagName; + is.openChild(tagName); + assert(tagName == "spectrum"); + while (!is.eos()) { + TDoubleParamP pos(0.0); + TPixelParamP color(TPixel32::Black); + is.openChild(tagName); + pos->loadData(is); + is.closeChild(); + is.openChild(tagName); + color->loadData(is); + is.closeChild(); + ColorKeyParam ck(pos, color); + m_imp->addKey(ck); + } + is.closeChild(); +} + +//--------------------------------------------------------- + +void TSpectrumParam::saveData(TOStream &os) { + assert(m_imp); + int keyCount = m_imp->getKeyCount(); + os.openChild("spectrum"); + for (int i = 0; i < keyCount; i++) { + ColorKeyParam key = m_imp->getKey(i); + os.openChild("s_value"); + key.first->saveData(os); + os.closeChild(); + os.openChild("col_value"); + key.second->saveData(os); + os.closeChild(); + } + os.closeChild(); } //--------------------------------------------------------- -void TSpectrumParam::enableDragging(bool on) -{ - m_imp->m_draggingEnabled = on; -} +void TSpectrumParam::enableDragging(bool on) { m_imp->m_draggingEnabled = on; } //--------------------------------------------------------- -void TSpectrumParam::enableNotification(bool on) -{ - m_imp->m_notificationEnabled = on; +void TSpectrumParam::enableNotification(bool on) { + m_imp->m_notificationEnabled = on; } //--------------------------------------------------------- -bool TSpectrumParam::isNotificationEnabled() const -{ - return m_imp->m_notificationEnabled; +bool TSpectrumParam::isNotificationEnabled() const { + return m_imp->m_notificationEnabled; } //--------------------------------------------------------- -namespace -{ +namespace { -inline std::string to_string(const TPixel32 &color) -{ - std::string alias = "("; - alias += std::to_string(color.r) + ","; - alias += std::to_string(color.g) + ","; - alias += std::to_string(color.b) + ","; - alias += std::to_string(color.m); - alias += ")"; - return alias; +inline std::string to_string(const TPixel32 &color) { + std::string alias = "("; + alias += std::to_string(color.r) + ","; + alias += std::to_string(color.g) + ","; + alias += std::to_string(color.b) + ","; + alias += std::to_string(color.m); + alias += ")"; + return alias; } -inline std::string toString(const TSpectrum::ColorKey &key, int precision) -{ - std::string alias = "("; - alias += ::to_string(key.first, precision) + ","; - alias += to_string(key.second); - alias += ")"; - return alias; +inline std::string toString(const TSpectrum::ColorKey &key, int precision) { + std::string alias = "("; + alias += ::to_string(key.first, precision) + ","; + alias += to_string(key.second); + alias += ")"; + return alias; } -} // namespace +} // namespace -std::string TSpectrumParam::getValueAlias(double frame, int precision) -{ - std::vector keys; - int keyCount = m_imp->getKeyCount(); - for (int i = 0; i < keyCount; i++) { - ColorKeyParam paramKey = m_imp->getKey(i); - TSpectrum::ColorKey key( - paramKey.first->getValue(frame), - paramKey.second->getValue(frame)); - keys.push_back(key); - } - - std::string alias = "("; - - if (!keys.empty()) { - std::vector::iterator it = keys.begin(); - std::vector::iterator end = keys.begin(); - std::advance(end, keys.size() - 1); - for (; it != end; ++it) { - alias += toString(*it, precision); - alias += ","; - } - alias += toString(*it, precision); - } - - alias += ")"; - return alias; +std::string TSpectrumParam::getValueAlias(double frame, int precision) { + std::vector keys; + int keyCount = m_imp->getKeyCount(); + for (int i = 0; i < keyCount; i++) { + ColorKeyParam paramKey = m_imp->getKey(i); + TSpectrum::ColorKey key(paramKey.first->getValue(frame), + paramKey.second->getValue(frame)); + keys.push_back(key); + } + + std::string alias = "("; + + if (!keys.empty()) { + std::vector::iterator it = keys.begin(); + std::vector::iterator end = keys.begin(); + std::advance(end, keys.size() - 1); + for (; it != end; ++it) { + alias += toString(*it, precision); + alias += ","; + } + alias += toString(*it, precision); + } + + alias += ")"; + return alias; } //========================================================= //--------------------------------------------------------- -void TSpectrumParam::enableMatte(bool on) -{ - m_imp->m_isMatteEnabled = on; -} +void TSpectrumParam::enableMatte(bool on) { m_imp->m_isMatteEnabled = on; } //--------------------------------------------------------- -bool TSpectrumParam::isMatteEnabled() const -{ - return m_imp->m_isMatteEnabled; -} +bool TSpectrumParam::isMatteEnabled() const { return m_imp->m_isMatteEnabled; } //--------------------------------------------------------- -bool TSpectrumParam::hasKeyframes() const -{ - int keyCount = m_imp->getKeyCount(); - for (int i = 0; i < keyCount; i++) { - ColorKeyParam currentKey = m_imp->getKey(i); - if (currentKey.first->hasKeyframes() || currentKey.second->hasKeyframes()) - return true; - } - return false; +bool TSpectrumParam::hasKeyframes() const { + int keyCount = m_imp->getKeyCount(); + for (int i = 0; i < keyCount; i++) { + ColorKeyParam currentKey = m_imp->getKey(i); + if (currentKey.first->hasKeyframes() || currentKey.second->hasKeyframes()) + return true; + } + return false; } //--------------------------------------------------------- -void TSpectrumParam::getKeyframes(std::set &frames) const -{ - int keyCount = m_imp->getKeyCount(); - for (int i = 0; i < keyCount; i++) { - ColorKeyParam currentKey = m_imp->getKey(i); - currentKey.first->getKeyframes(frames); - currentKey.second->getKeyframes(frames); - } +void TSpectrumParam::getKeyframes(std::set &frames) const { + int keyCount = m_imp->getKeyCount(); + for (int i = 0; i < keyCount; i++) { + ColorKeyParam currentKey = m_imp->getKey(i); + currentKey.first->getKeyframes(frames); + currentKey.second->getKeyframes(frames); + } } //--------------------------------------------------------- -int TSpectrumParam::getNextKeyframe(double frame) const -{ - std::set frames; - getKeyframes(frames); - std::set::iterator it = frames.upper_bound(frame); - if (it == frames.end()) - return -1; - else - return std::distance(frames.begin(), it); +int TSpectrumParam::getNextKeyframe(double frame) const { + std::set frames; + getKeyframes(frames); + std::set::iterator it = frames.upper_bound(frame); + if (it == frames.end()) + return -1; + else + return std::distance(frames.begin(), it); } //--------------------------------------------------------- -int TSpectrumParam::getPrevKeyframe(double frame) const -{ - std::set frames; - getKeyframes(frames); - std::set::iterator it = frames.lower_bound(frame); - if (it == frames.begin()) - return -1; - else { - --it; - return std::distance(frames.begin(), it); - } +int TSpectrumParam::getPrevKeyframe(double frame) const { + std::set frames; + getKeyframes(frames); + std::set::iterator it = frames.lower_bound(frame); + if (it == frames.begin()) + return -1; + else { + --it; + return std::distance(frames.begin(), it); + } } //--------------------------------------------------------- -double TSpectrumParam::keyframeIndexToFrame(int index) const -{ - std::set frames; - getKeyframes(frames); - assert(0 <= index && index < (int)frames.size()); - std::set::const_iterator it = frames.begin(); - std::advance(it, index); - return *it; +double TSpectrumParam::keyframeIndexToFrame(int index) const { + std::set frames; + getKeyframes(frames); + assert(0 <= index && index < (int)frames.size()); + std::set::const_iterator it = frames.begin(); + std::advance(it, index); + return *it; } -TIStream &operator>>(TIStream &in, TSpectrumParamP &p) -{ - TPersist *tmp; - in >> tmp; - p = TSpectrumParamP(dynamic_cast(tmp)); - return in; +TIStream &operator>>(TIStream &in, TSpectrumParamP &p) { + TPersist *tmp; + in >> tmp; + p = TSpectrumParamP(dynamic_cast(tmp)); + return in; } diff --git a/toonz/sources/common/tparam/ttonecurveparam.cpp b/toonz/sources/common/tparam/ttonecurveparam.cpp index 5990cd2..24d95d3 100644 --- a/toonz/sources/common/tparam/ttonecurveparam.cpp +++ b/toonz/sources/common/tparam/ttonecurveparam.cpp @@ -12,385 +12,361 @@ PERSIST_IDENTIFIER(TToneCurveParam, "toneCurveParam") //--------------------------------------------------------- -TToneCurveParam::TToneCurveParam() - : TParam() -{ - m_toneChannel = RGBA; - - std::vector points; - //Inserisco dei punti fuori dal range(0-255) perche' mi consentono di gestire i primi punti come speciali. - points.push_back(TPointD(-40, 0)); - points.push_back(TPointD(-20, 0)); - points.push_back(TPointD(-20, 0)); - points.push_back(TPointD(0, 0)); - points.push_back(TPointD(16, 16)); - points.push_back(TPointD(239, 239)); - points.push_back(TPointD(255, 255)); - points.push_back(TPointD(275, 255)); - points.push_back(TPointD(275, 255)); - points.push_back(TPointD(295, 255)); - m_rgbaParamSet = new TParamSet("redgreenbluealphachannel"); - m_rgbParamSet = new TParamSet("redgreenbluechannel"); - m_rParamSet = new TParamSet("redchannel"); - m_gParamSet = new TParamSet("greenchannel"); - m_bParamSet = new TParamSet("bluechannel"); - m_aParamSet = new TParamSet("alphachannel"); - - m_isLinear = new TBoolParam(false); - - int i; - for (i = 0; i < (int)points.size(); i++) { - m_rgbaParamSet->addParam(new TPointParam(points[i]), "point"); - m_rgbParamSet->addParam(new TPointParam(points[i]), "point"); - m_rParamSet->addParam(new TPointParam(points[i]), "point"); - m_gParamSet->addParam(new TPointParam(points[i]), "point"); - m_bParamSet->addParam(new TPointParam(points[i]), "point"); - m_aParamSet->addParam(new TPointParam(points[i]), "point"); - } +TToneCurveParam::TToneCurveParam() : TParam() { + m_toneChannel = RGBA; + + std::vector points; + // Inserisco dei punti fuori dal range(0-255) perche' mi consentono di gestire + // i primi punti come speciali. + points.push_back(TPointD(-40, 0)); + points.push_back(TPointD(-20, 0)); + points.push_back(TPointD(-20, 0)); + points.push_back(TPointD(0, 0)); + points.push_back(TPointD(16, 16)); + points.push_back(TPointD(239, 239)); + points.push_back(TPointD(255, 255)); + points.push_back(TPointD(275, 255)); + points.push_back(TPointD(275, 255)); + points.push_back(TPointD(295, 255)); + m_rgbaParamSet = new TParamSet("redgreenbluealphachannel"); + m_rgbParamSet = new TParamSet("redgreenbluechannel"); + m_rParamSet = new TParamSet("redchannel"); + m_gParamSet = new TParamSet("greenchannel"); + m_bParamSet = new TParamSet("bluechannel"); + m_aParamSet = new TParamSet("alphachannel"); + + m_isLinear = new TBoolParam(false); + + int i; + for (i = 0; i < (int)points.size(); i++) { + m_rgbaParamSet->addParam(new TPointParam(points[i]), "point"); + m_rgbParamSet->addParam(new TPointParam(points[i]), "point"); + m_rParamSet->addParam(new TPointParam(points[i]), "point"); + m_gParamSet->addParam(new TPointParam(points[i]), "point"); + m_bParamSet->addParam(new TPointParam(points[i]), "point"); + m_aParamSet->addParam(new TPointParam(points[i]), "point"); + } } //--------------------------------------------------------- -TParamSetP getClonedParamSet(TParamSetP srcParamSet) -{ - TParamSetP dstParamSet = new TParamSet(srcParamSet->getName()); - int i; - for (i = 0; i < srcParamSet->getParamCount(); i++) { - TParamP param = srcParamSet->getParam(i); - dstParamSet->addParam(param->clone(), param->getName()); - } - return dstParamSet; +TParamSetP getClonedParamSet(TParamSetP srcParamSet) { + TParamSetP dstParamSet = new TParamSet(srcParamSet->getName()); + int i; + for (i = 0; i < srcParamSet->getParamCount(); i++) { + TParamP param = srcParamSet->getParam(i); + dstParamSet->addParam(param->clone(), param->getName()); + } + return dstParamSet; } //--------------------------------------------------------- TToneCurveParam::TToneCurveParam(const TToneCurveParam &src) - : TParam(src.getName()) -{ - m_rgbaParamSet = getClonedParamSet(src.getParamSet(RGBA)); - m_rgbParamSet = getClonedParamSet(src.getParamSet(RGB)); - m_rParamSet = getClonedParamSet(src.getParamSet(Red)); - m_gParamSet = getClonedParamSet(src.getParamSet(Green)); - m_bParamSet = getClonedParamSet(src.getParamSet(Blue)); - m_aParamSet = getClonedParamSet(src.getParamSet(Alpha)); - m_toneChannel = src.getCurrentChannel(); - m_isLinear = src.getIsLinearParam()->clone(); + : TParam(src.getName()) { + m_rgbaParamSet = getClonedParamSet(src.getParamSet(RGBA)); + m_rgbParamSet = getClonedParamSet(src.getParamSet(RGB)); + m_rParamSet = getClonedParamSet(src.getParamSet(Red)); + m_gParamSet = getClonedParamSet(src.getParamSet(Green)); + m_bParamSet = getClonedParamSet(src.getParamSet(Blue)); + m_aParamSet = getClonedParamSet(src.getParamSet(Alpha)); + m_toneChannel = src.getCurrentChannel(); + m_isLinear = src.getIsLinearParam()->clone(); } //--------------------------------------------------------- -void TToneCurveParam::copy(TParam *src) -{ - TToneCurveParam *p = dynamic_cast(src); - if (!p) - throw TException("invalid source for copy"); - setName(src->getName()); - m_rgbaParamSet->copy(p->getParamSet(RGBA).getPointer()); - m_rgbParamSet->copy(p->getParamSet(RGB).getPointer()); - m_rParamSet->copy(p->getParamSet(Red).getPointer()); - m_gParamSet->copy(p->getParamSet(Green).getPointer()); - m_bParamSet->copy(p->getParamSet(Blue).getPointer()); - m_aParamSet->copy(p->getParamSet(Alpha).getPointer()); - m_isLinear->copy(p->getIsLinearParam().getPointer()); - m_toneChannel = p->getCurrentChannel(); +void TToneCurveParam::copy(TParam *src) { + TToneCurveParam *p = dynamic_cast(src); + if (!p) throw TException("invalid source for copy"); + setName(src->getName()); + m_rgbaParamSet->copy(p->getParamSet(RGBA).getPointer()); + m_rgbParamSet->copy(p->getParamSet(RGB).getPointer()); + m_rParamSet->copy(p->getParamSet(Red).getPointer()); + m_gParamSet->copy(p->getParamSet(Green).getPointer()); + m_bParamSet->copy(p->getParamSet(Blue).getPointer()); + m_aParamSet->copy(p->getParamSet(Alpha).getPointer()); + m_isLinear->copy(p->getIsLinearParam().getPointer()); + m_toneChannel = p->getCurrentChannel(); } //--------------------------------------------------------- -void TToneCurveParam::addObserver(TParamObserver *observer) -{ - m_rgbaParamSet->addObserver(observer); - m_rgbParamSet->addObserver(observer); - m_rParamSet->addObserver(observer); - m_gParamSet->addObserver(observer); - m_bParamSet->addObserver(observer); - m_aParamSet->addObserver(observer); - m_isLinear->addObserver(observer); +void TToneCurveParam::addObserver(TParamObserver *observer) { + m_rgbaParamSet->addObserver(observer); + m_rgbParamSet->addObserver(observer); + m_rParamSet->addObserver(observer); + m_gParamSet->addObserver(observer); + m_bParamSet->addObserver(observer); + m_aParamSet->addObserver(observer); + m_isLinear->addObserver(observer); } //--------------------------------------------------------- -void TToneCurveParam::removeObserver(TParamObserver *observer) -{ - m_rgbaParamSet->removeObserver(observer); - m_rgbParamSet->removeObserver(observer); - m_rParamSet->removeObserver(observer); - m_gParamSet->removeObserver(observer); - m_bParamSet->removeObserver(observer); - m_aParamSet->removeObserver(observer); - m_isLinear->removeObserver(observer); +void TToneCurveParam::removeObserver(TParamObserver *observer) { + m_rgbaParamSet->removeObserver(observer); + m_rgbParamSet->removeObserver(observer); + m_rParamSet->removeObserver(observer); + m_gParamSet->removeObserver(observer); + m_bParamSet->removeObserver(observer); + m_aParamSet->removeObserver(observer); + m_isLinear->removeObserver(observer); } //--------------------------------------------------------- -TParamSetP TToneCurveParam::getParamSet(ToneChannel channel) const -{ - if (channel == RGBA) - return m_rgbaParamSet; - else if (channel == RGB) - return m_rgbParamSet; - else if (channel == Red) - return m_rParamSet; - else if (channel == Green) - return m_gParamSet; - else if (channel == Blue) - return m_bParamSet; - else if (channel == Alpha) - return m_aParamSet; - - return 0; +TParamSetP TToneCurveParam::getParamSet(ToneChannel channel) const { + if (channel == RGBA) + return m_rgbaParamSet; + else if (channel == RGB) + return m_rgbParamSet; + else if (channel == Red) + return m_rParamSet; + else if (channel == Green) + return m_gParamSet; + else if (channel == Blue) + return m_bParamSet; + else if (channel == Alpha) + return m_aParamSet; + + return 0; } //--------------------------------------------------------- -TParamSetP TToneCurveParam::getCurrentParamSet() const -{ - return getParamSet(m_toneChannel); +TParamSetP TToneCurveParam::getCurrentParamSet() const { + return getParamSet(m_toneChannel); } //--------------------------------------------------------- -void TToneCurveParam::setCurrentChannel(ToneChannel channel) -{ - m_toneChannel = channel; +void TToneCurveParam::setCurrentChannel(ToneChannel channel) { + m_toneChannel = channel; } //--------------------------------------------------------- -QList TToneCurveParam::getValue(double frame) const -{ - int i; - QList points; - for (i = 0; i < getCurrentParamSet()->getParamCount(); i++) { - TPointParamP pointParam = getCurrentParamSet()->getParam(i); - points.push_back(pointParam->getValue(frame)); - } - return points; +QList TToneCurveParam::getValue(double frame) const { + int i; + QList points; + for (i = 0; i < getCurrentParamSet()->getParamCount(); i++) { + TPointParamP pointParam = getCurrentParamSet()->getParam(i); + points.push_back(pointParam->getValue(frame)); + } + return points; } //--------------------------------------------------------- -void TToneCurveParam::setValue(double frame, const QList &value, bool undoing) -{ - if (value.size() == 0) - return; - int paramCount = getCurrentParamSet()->getParamCount(); - assert(paramCount == value.size()); - int i = 0; - for (i = 0; i < paramCount; i++) { - TPointParamP param = getCurrentParamSet()->getParam(i); - TPointD point = value.at(i); - param->setValue(frame, point); - } +void TToneCurveParam::setValue(double frame, const QList &value, + bool undoing) { + if (value.size() == 0) return; + int paramCount = getCurrentParamSet()->getParamCount(); + assert(paramCount == value.size()); + int i = 0; + for (i = 0; i < paramCount; i++) { + TPointParamP param = getCurrentParamSet()->getParam(i); + TPointD point = value.at(i); + param->setValue(frame, point); + } } //--------------------------------------------------------- -bool TToneCurveParam::isLinear() const -{ - return m_isLinear->getValue(); -} +bool TToneCurveParam::isLinear() const { return m_isLinear->getValue(); } //--------------------------------------------------------- -void TToneCurveParam::setIsLinear(bool isLinear) -{ - m_isLinear->setValue(isLinear); +void TToneCurveParam::setIsLinear(bool isLinear) { + m_isLinear->setValue(isLinear); } //--------------------------------------------------------- -void TToneCurveParam::addValue(double frame, const QList &value, int index) -{ - getCurrentParamSet()->insertParam(new TPointParam(value.at(index - 1)), "point", index - 1); - getCurrentParamSet()->insertParam(new TPointParam(value.at(index)), "point", index); - getCurrentParamSet()->insertParam(new TPointParam(value.at(index + 1)), "point", index + 1); +void TToneCurveParam::addValue(double frame, const QList &value, + int index) { + getCurrentParamSet()->insertParam(new TPointParam(value.at(index - 1)), + "point", index - 1); + getCurrentParamSet()->insertParam(new TPointParam(value.at(index)), "point", + index); + getCurrentParamSet()->insertParam(new TPointParam(value.at(index + 1)), + "point", index + 1); } //--------------------------------------------------------- -void TToneCurveParam::removeValue(double frame, int index) -{ - getCurrentParamSet()->removeParam(getCurrentParamSet()->getParam(index - 1)); - getCurrentParamSet()->removeParam(getCurrentParamSet()->getParam(index - 1)); - getCurrentParamSet()->removeParam(getCurrentParamSet()->getParam(index - 1)); +void TToneCurveParam::removeValue(double frame, int index) { + getCurrentParamSet()->removeParam(getCurrentParamSet()->getParam(index - 1)); + getCurrentParamSet()->removeParam(getCurrentParamSet()->getParam(index - 1)); + getCurrentParamSet()->removeParam(getCurrentParamSet()->getParam(index - 1)); } //--------------------------------------------------------- -void TToneCurveParam::setDefaultValue(const QList &value) -{ - int pointCount = value.size(); - if (pointCount == 0) - return; - - int paramCount = getCurrentParamSet()->getParamCount(); - assert(paramCount == pointCount); - - int i; - for (i = 0; i < pointCount; i++) { - TPointParamP param = getCurrentParamSet()->getParam(i); - TPointD paramPoint(param->getValue(0)); - TPointD strokePoint(value.at(i)); - param->setDefaultValue(strokePoint); - } - m_isLinear->setDefaultValue(false); +void TToneCurveParam::setDefaultValue(const QList &value) { + int pointCount = value.size(); + if (pointCount == 0) return; + + int paramCount = getCurrentParamSet()->getParamCount(); + assert(paramCount == pointCount); + + int i; + for (i = 0; i < pointCount; i++) { + TPointParamP param = getCurrentParamSet()->getParam(i); + TPointD paramPoint(param->getValue(0)); + TPointD strokePoint(value.at(i)); + param->setDefaultValue(strokePoint); + } + m_isLinear->setDefaultValue(false); } //--------------------------------------------------------- -std::string TToneCurveParam::getValueAlias(double frame, int precision) -{ - return getCurrentParamSet()->getValueAlias(frame, precision) + m_isLinear->getValueAlias(frame, precision); +std::string TToneCurveParam::getValueAlias(double frame, int precision) { + return getCurrentParamSet()->getValueAlias(frame, precision) + + m_isLinear->getValueAlias(frame, precision); } //--------------------------------------------------------- -bool TToneCurveParam::isKeyframe(double frame) const -{ - if (m_rgbaParamSet->isKeyframe(frame) || m_rgbParamSet->isKeyframe(frame) || m_rParamSet->isKeyframe(frame) || - m_gParamSet->isKeyframe(frame) || m_bParamSet->isKeyframe(frame) || m_aParamSet->isKeyframe(frame)) - return true; - return false; +bool TToneCurveParam::isKeyframe(double frame) const { + if (m_rgbaParamSet->isKeyframe(frame) || m_rgbParamSet->isKeyframe(frame) || + m_rParamSet->isKeyframe(frame) || m_gParamSet->isKeyframe(frame) || + m_bParamSet->isKeyframe(frame) || m_aParamSet->isKeyframe(frame)) + return true; + return false; } //--------------------------------------------------------- -void TToneCurveParam::deleteKeyframe(double frame) -{ - m_rgbaParamSet->deleteKeyframe(frame); - m_rgbParamSet->deleteKeyframe(frame); - m_rParamSet->deleteKeyframe(frame); - m_gParamSet->deleteKeyframe(frame); - m_bParamSet->deleteKeyframe(frame); - m_aParamSet->deleteKeyframe(frame); +void TToneCurveParam::deleteKeyframe(double frame) { + m_rgbaParamSet->deleteKeyframe(frame); + m_rgbParamSet->deleteKeyframe(frame); + m_rParamSet->deleteKeyframe(frame); + m_gParamSet->deleteKeyframe(frame); + m_bParamSet->deleteKeyframe(frame); + m_aParamSet->deleteKeyframe(frame); } //--------------------------------------------------------- -void TToneCurveParam::clearKeyframes() -{ - m_rgbaParamSet->clearKeyframes(); - m_rgbParamSet->clearKeyframes(); - m_rParamSet->clearKeyframes(); - m_gParamSet->clearKeyframes(); - m_bParamSet->clearKeyframes(); - m_aParamSet->clearKeyframes(); +void TToneCurveParam::clearKeyframes() { + m_rgbaParamSet->clearKeyframes(); + m_rgbParamSet->clearKeyframes(); + m_rParamSet->clearKeyframes(); + m_gParamSet->clearKeyframes(); + m_bParamSet->clearKeyframes(); + m_aParamSet->clearKeyframes(); } //--------------------------------------------------------- -void TToneCurveParam::assignKeyframe(double frame, const TSmartPointerT &src, - double srcFrame, bool changedOnly) -{ - m_rgbaParamSet->assignKeyframe(frame, src, srcFrame, changedOnly); - m_rgbParamSet->assignKeyframe(frame, src, srcFrame, changedOnly); - m_rParamSet->assignKeyframe(frame, src, srcFrame, changedOnly); - m_gParamSet->assignKeyframe(frame, src, srcFrame, changedOnly); - m_bParamSet->assignKeyframe(frame, src, srcFrame, changedOnly); - m_aParamSet->assignKeyframe(frame, src, srcFrame, changedOnly); +void TToneCurveParam::assignKeyframe(double frame, + const TSmartPointerT &src, + double srcFrame, bool changedOnly) { + m_rgbaParamSet->assignKeyframe(frame, src, srcFrame, changedOnly); + m_rgbParamSet->assignKeyframe(frame, src, srcFrame, changedOnly); + m_rParamSet->assignKeyframe(frame, src, srcFrame, changedOnly); + m_gParamSet->assignKeyframe(frame, src, srcFrame, changedOnly); + m_bParamSet->assignKeyframe(frame, src, srcFrame, changedOnly); + m_aParamSet->assignKeyframe(frame, src, srcFrame, changedOnly); } //--------------------------------------------------------- -void TToneCurveParam::getKeyframes(std::set &frames) const -{ - m_rgbaParamSet->getKeyframes(frames); - m_rgbParamSet->getKeyframes(frames); - m_rParamSet->getKeyframes(frames); - m_gParamSet->getKeyframes(frames); - m_bParamSet->getKeyframes(frames); - m_aParamSet->getKeyframes(frames); +void TToneCurveParam::getKeyframes(std::set &frames) const { + m_rgbaParamSet->getKeyframes(frames); + m_rgbParamSet->getKeyframes(frames); + m_rParamSet->getKeyframes(frames); + m_gParamSet->getKeyframes(frames); + m_bParamSet->getKeyframes(frames); + m_aParamSet->getKeyframes(frames); } //--------------------------------------------------------- -bool TToneCurveParam::hasKeyframes() const -{ - if (m_rgbaParamSet->hasKeyframes() || m_rgbParamSet->hasKeyframes() || m_rParamSet->hasKeyframes() || - m_gParamSet->hasKeyframes() || m_bParamSet->hasKeyframes() || m_aParamSet->hasKeyframes()) - return true; - return false; +bool TToneCurveParam::hasKeyframes() const { + if (m_rgbaParamSet->hasKeyframes() || m_rgbParamSet->hasKeyframes() || + m_rParamSet->hasKeyframes() || m_gParamSet->hasKeyframes() || + m_bParamSet->hasKeyframes() || m_aParamSet->hasKeyframes()) + return true; + return false; } //--------------------------------------------------------- -int TToneCurveParam::getNextKeyframe(double frame) const -{ - std::set frames; - getKeyframes(frames); - std::set::iterator it = frames.upper_bound(frame); - if (it == frames.end()) - return -1; - else - return std::distance(frames.begin(), it); +int TToneCurveParam::getNextKeyframe(double frame) const { + std::set frames; + getKeyframes(frames); + std::set::iterator it = frames.upper_bound(frame); + if (it == frames.end()) + return -1; + else + return std::distance(frames.begin(), it); } //--------------------------------------------------------- -int TToneCurveParam::getPrevKeyframe(double frame) const -{ - std::set frames; - getKeyframes(frames); - std::set::iterator it = frames.lower_bound(frame); - if (it == frames.begin()) - return -1; - else { - --it; - return std::distance(frames.begin(), it); - } +int TToneCurveParam::getPrevKeyframe(double frame) const { + std::set frames; + getKeyframes(frames); + std::set::iterator it = frames.lower_bound(frame); + if (it == frames.begin()) + return -1; + else { + --it; + return std::distance(frames.begin(), it); + } } //--------------------------------------------------------- -double TToneCurveParam::keyframeIndexToFrame(int index) const -{ - std::set frames; - getKeyframes(frames); - assert(0 <= index && index < (int)frames.size()); - std::set::const_iterator it = frames.begin(); - std::advance(it, index); - return *it; +double TToneCurveParam::keyframeIndexToFrame(int index) const { + std::set frames; + getKeyframes(frames); + assert(0 <= index && index < (int)frames.size()); + std::set::const_iterator it = frames.begin(); + std::advance(it, index); + return *it; } //--------------------------------------------------------- -void TToneCurveParam::loadData(TIStream &is) -{ - std::string tagName; - is.openChild(tagName); - assert(tagName == "tonecurve"); - m_rgbaParamSet->removeAllParam(); - m_rgbaParamSet->loadData(is); - m_rgbParamSet->removeAllParam(); - m_rgbParamSet->loadData(is); - m_rParamSet->removeAllParam(); - m_rParamSet->loadData(is); - m_gParamSet->removeAllParam(); - m_gParamSet->loadData(is); - m_bParamSet->removeAllParam(); - m_bParamSet->loadData(is); - m_aParamSet->removeAllParam(); - m_aParamSet->loadData(is); - is.openChild(tagName); - m_isLinear->loadData(is); - is.closeChild(); - is.closeChild(); +void TToneCurveParam::loadData(TIStream &is) { + std::string tagName; + is.openChild(tagName); + assert(tagName == "tonecurve"); + m_rgbaParamSet->removeAllParam(); + m_rgbaParamSet->loadData(is); + m_rgbParamSet->removeAllParam(); + m_rgbParamSet->loadData(is); + m_rParamSet->removeAllParam(); + m_rParamSet->loadData(is); + m_gParamSet->removeAllParam(); + m_gParamSet->loadData(is); + m_bParamSet->removeAllParam(); + m_bParamSet->loadData(is); + m_aParamSet->removeAllParam(); + m_aParamSet->loadData(is); + is.openChild(tagName); + m_isLinear->loadData(is); + is.closeChild(); + is.closeChild(); } //--------------------------------------------------------- -void TToneCurveParam::saveData(TOStream &os) -{ - os.openChild("tonecurve"); - m_rgbaParamSet->saveData(os); - m_rgbParamSet->saveData(os); - m_rParamSet->saveData(os); - m_gParamSet->saveData(os); - m_bParamSet->saveData(os); - m_aParamSet->saveData(os); - os.openChild("isLineaer"); - m_isLinear->saveData(os); - os.closeChild(); - os.closeChild(); +void TToneCurveParam::saveData(TOStream &os) { + os.openChild("tonecurve"); + m_rgbaParamSet->saveData(os); + m_rgbParamSet->saveData(os); + m_rParamSet->saveData(os); + m_gParamSet->saveData(os); + m_bParamSet->saveData(os); + m_aParamSet->saveData(os); + os.openChild("isLineaer"); + m_isLinear->saveData(os); + os.closeChild(); + os.closeChild(); } diff --git a/toonz/sources/common/tproperty.cpp b/toonz/sources/common/tproperty.cpp index 00544bf..2765e40 100644 --- a/toonz/sources/common/tproperty.cpp +++ b/toonz/sources/common/tproperty.cpp @@ -5,315 +5,281 @@ #include "texception.h" //#include "tconvert.h" -void TProperty::addListener(Listener *listener) -{ - if (std::find(m_listeners.begin(), m_listeners.end(), listener) == m_listeners.end()) - m_listeners.push_back(listener); +void TProperty::addListener(Listener *listener) { + if (std::find(m_listeners.begin(), m_listeners.end(), listener) == + m_listeners.end()) + m_listeners.push_back(listener); } -void TProperty::removeListener(Listener *listener) -{ - m_listeners.erase(std::remove(m_listeners.begin(), m_listeners.end(), listener), m_listeners.end()); +void TProperty::removeListener(Listener *listener) { + m_listeners.erase( + std::remove(m_listeners.begin(), m_listeners.end(), listener), + m_listeners.end()); } -void TProperty::notifyListeners() const -{ - std::vector::const_iterator it; - for (it = m_listeners.begin(); it != m_listeners.end(); ++it) - (*it)->onPropertyChanged(); +void TProperty::notifyListeners() const { + std::vector::const_iterator it; + for (it = m_listeners.begin(); it != m_listeners.end(); ++it) + (*it)->onPropertyChanged(); } //============================================================================= -TPropertyGroup::TPropertyGroup() -{ -} +TPropertyGroup::TPropertyGroup() {} -TPropertyGroup::~TPropertyGroup() -{ - for (PropertyVector::iterator it = m_properties.begin(); - it != m_properties.end(); ++it) - if (it->second) - delete it->first; +TPropertyGroup::~TPropertyGroup() { + for (PropertyVector::iterator it = m_properties.begin(); + it != m_properties.end(); ++it) + if (it->second) delete it->first; } -void TPropertyGroup::clear() -{ - m_properties.clear(); - m_table.clear(); +void TPropertyGroup::clear() { + m_properties.clear(); + m_table.clear(); } -TPropertyGroup *TPropertyGroup::clone() const -{ - TPropertyGroup *g = new TPropertyGroup(); - for (PropertyVector::const_iterator i = m_properties.begin(); - i != m_properties.end(); ++i) - g->add(i->first->clone()); - return g; +TPropertyGroup *TPropertyGroup::clone() const { + TPropertyGroup *g = new TPropertyGroup(); + for (PropertyVector::const_iterator i = m_properties.begin(); + i != m_properties.end(); ++i) + g->add(i->first->clone()); + return g; } -void TPropertyGroup::add(TProperty *p) -{ - std::string name = p->getName(); - assert(m_table.find(name) == m_table.end()); - m_properties.push_back(std::make_pair(p, true)); - m_table[name] = p; +void TPropertyGroup::add(TProperty *p) { + std::string name = p->getName(); + assert(m_table.find(name) == m_table.end()); + m_properties.push_back(std::make_pair(p, true)); + m_table[name] = p; } -void TPropertyGroup::bind(TProperty &p) -{ - std::string name = p.getName(); - assert(m_table.find(name) == m_table.end()); - m_properties.push_back(std::make_pair(&p, false)); - m_table[name] = &p; +void TPropertyGroup::bind(TProperty &p) { + std::string name = p.getName(); + assert(m_table.find(name) == m_table.end()); + m_properties.push_back(std::make_pair(&p, false)); + m_table[name] = &p; } -TProperty *TPropertyGroup::getProperty(std::string name) -{ - PropertyTable::iterator i = m_table.find(name); - if (i == m_table.end()) - return 0; - else - return i->second; +TProperty *TPropertyGroup::getProperty(std::string name) { + PropertyTable::iterator i = m_table.find(name); + if (i == m_table.end()) + return 0; + else + return i->second; } template -void assign(Property *dst, TProperty *src) -{ - Property *s = dynamic_cast(src); - if (!s) - throw TProperty::TypeError(); - dst->setValue(s->getValue()); +void assign(Property *dst, TProperty *src) { + Property *s = dynamic_cast(src); + if (!s) throw TProperty::TypeError(); + dst->setValue(s->getValue()); } -class Setter : public TProperty::Visitor -{ - TProperty *m_src; +class Setter : public TProperty::Visitor { + TProperty *m_src; public: - Setter(TProperty *src) : m_src(src) {} + Setter(TProperty *src) : m_src(src) {} - void visit(TDoubleProperty *dst) { assign(dst, m_src); } - void visit(TIntProperty *dst) { assign(dst, m_src); } - void visit(TStringProperty *dst) { assign(dst, m_src); } - void visit(TBoolProperty *dst) { assign(dst, m_src); } - void visit(TEnumProperty *dst) { assign(dst, m_src); } - void visit(TDoublePairProperty *dst) { assign(dst, m_src); } - void visit(TIntPairProperty *dst) { assign(dst, m_src); } - void visit(TStyleIndexProperty *dst) { assign(dst, m_src); } - void visit(TPointerProperty *dst) { assign(dst, m_src); } + void visit(TDoubleProperty *dst) { assign(dst, m_src); } + void visit(TIntProperty *dst) { assign(dst, m_src); } + void visit(TStringProperty *dst) { assign(dst, m_src); } + void visit(TBoolProperty *dst) { assign(dst, m_src); } + void visit(TEnumProperty *dst) { assign(dst, m_src); } + void visit(TDoublePairProperty *dst) { assign(dst, m_src); } + void visit(TIntPairProperty *dst) { assign(dst, m_src); } + void visit(TStyleIndexProperty *dst) { assign(dst, m_src); } + void visit(TPointerProperty *dst) { assign(dst, m_src); } }; -void TPropertyGroup::setProperties(TPropertyGroup *g) -{ - for (PropertyVector::const_iterator i = g->m_properties.begin(); - i != g->m_properties.end(); ++i) { - TProperty *src = i->first; - TProperty *dst = getProperty(src->getName()); - if (dst) { - Setter setter(src); - TProperty::Visitor *visitor = &setter; - dst->accept(*visitor); - } - } +void TPropertyGroup::setProperties(TPropertyGroup *g) { + for (PropertyVector::const_iterator i = g->m_properties.begin(); + i != g->m_properties.end(); ++i) { + TProperty *src = i->first; + TProperty *dst = getProperty(src->getName()); + if (dst) { + Setter setter(src); + TProperty::Visitor *visitor = &setter; + dst->accept(*visitor); + } + } } -void TPropertyGroup::accept(TProperty::Visitor &v) -{ - for (PropertyVector::const_iterator i = m_properties.begin(); - i != m_properties.end(); ++i) - i->first->accept(v); +void TPropertyGroup::accept(TProperty::Visitor &v) { + for (PropertyVector::const_iterator i = m_properties.begin(); + i != m_properties.end(); ++i) + i->first->accept(v); } -class PropertyWriter : public TProperty::Visitor -{ - TOStream &m_os; +class PropertyWriter : public TProperty::Visitor { + TOStream &m_os; public: - PropertyWriter(TOStream &os) : m_os(os) {} + PropertyWriter(TOStream &os) : m_os(os) {} - void visit(TDoubleProperty *p) - { - std::map attr; - attr["type"] = "double"; - attr["name"] = p->getName(); - attr["min"] = std::to_string(p->getRange().first); - attr["max"] = std::to_string(p->getRange().second); - attr["value"] = std::to_string(p->getValue()); - m_os.openCloseChild("property", attr); - } - void visit(TDoublePairProperty *p) - { - std::map attr; - attr["type"] = "pair"; - attr["name"] = p->getName(); - attr["min"] = std::to_string(p->getRange().first); - attr["max"] = std::to_string(p->getRange().second); - TDoublePairProperty::Value value = p->getValue(); - attr["value"] = std::to_string(value.first) + " " + std::to_string(value.second); - m_os.openCloseChild("property", attr); - } - void visit(TIntPairProperty *p) - { - std::map attr; - attr["type"] = "pair"; - attr["name"] = p->getName(); - attr["min"] = std::to_string(p->getRange().first); - attr["max"] = std::to_string(p->getRange().second); - TIntPairProperty::Value value = p->getValue(); - attr["value"] = std::to_string(value.first) + " " + std::to_string(value.second); - m_os.openCloseChild("property", attr); - } - void visit(TIntProperty *p) - { - std::map attr; - attr["type"] = "int"; - attr["name"] = p->getName(); - attr["min"] = std::to_string(p->getRange().first); - attr["max"] = std::to_string(p->getRange().second); - attr["value"] = std::to_string(p->getValue()); - m_os.openCloseChild("property", attr); - } - void visit(TBoolProperty *p) - { - std::map attr; - attr["type"] = "bool"; - attr["name"] = p->getName(); - attr["value"] = p->getValue() ? "true" : "false"; - m_os.openCloseChild("property", attr); - } - void visit(TStringProperty *p) - { - std::map attr; - attr["type"] = "string"; - attr["name"] = p->getName(); - attr["value"] = ::to_string(p->getValue()); - m_os.openCloseChild("property", attr); - } + void visit(TDoubleProperty *p) { + std::map attr; + attr["type"] = "double"; + attr["name"] = p->getName(); + attr["min"] = std::to_string(p->getRange().first); + attr["max"] = std::to_string(p->getRange().second); + attr["value"] = std::to_string(p->getValue()); + m_os.openCloseChild("property", attr); + } + void visit(TDoublePairProperty *p) { + std::map attr; + attr["type"] = "pair"; + attr["name"] = p->getName(); + attr["min"] = std::to_string(p->getRange().first); + attr["max"] = std::to_string(p->getRange().second); + TDoublePairProperty::Value value = p->getValue(); + attr["value"] = + std::to_string(value.first) + " " + std::to_string(value.second); + m_os.openCloseChild("property", attr); + } + void visit(TIntPairProperty *p) { + std::map attr; + attr["type"] = "pair"; + attr["name"] = p->getName(); + attr["min"] = std::to_string(p->getRange().first); + attr["max"] = std::to_string(p->getRange().second); + TIntPairProperty::Value value = p->getValue(); + attr["value"] = + std::to_string(value.first) + " " + std::to_string(value.second); + m_os.openCloseChild("property", attr); + } + void visit(TIntProperty *p) { + std::map attr; + attr["type"] = "int"; + attr["name"] = p->getName(); + attr["min"] = std::to_string(p->getRange().first); + attr["max"] = std::to_string(p->getRange().second); + attr["value"] = std::to_string(p->getValue()); + m_os.openCloseChild("property", attr); + } + void visit(TBoolProperty *p) { + std::map attr; + attr["type"] = "bool"; + attr["name"] = p->getName(); + attr["value"] = p->getValue() ? "true" : "false"; + m_os.openCloseChild("property", attr); + } + void visit(TStringProperty *p) { + std::map attr; + attr["type"] = "string"; + attr["name"] = p->getName(); + attr["value"] = ::to_string(p->getValue()); + m_os.openCloseChild("property", attr); + } - void visit(TStyleIndexProperty *p) - { - std::map attr; - attr["type"] = "string"; - attr["name"] = p->getName(); - attr["value"] = p->getValueAsString(); - m_os.openCloseChild("property", attr); - } + void visit(TStyleIndexProperty *p) { + std::map attr; + attr["type"] = "string"; + attr["name"] = p->getName(); + attr["value"] = p->getValueAsString(); + m_os.openCloseChild("property", attr); + } - void visit(TEnumProperty *p) - { - std::map attr; - attr["type"] = "enum"; - attr["name"] = p->getName(); - attr["value"] = ::to_string(p->getValue()); - if (TEnumProperty::isRangeSavingEnabled()) { - m_os.openChild("property", attr); - std::vector range = p->getRange(); - for (int i = 0; i < (int)range.size(); i++) { - attr.clear(); - attr["value"] = ::to_string(range[i]); - m_os.openCloseChild("item", attr); - } - m_os.closeChild(); - } else - m_os.openCloseChild("property", attr); - } - void visit(TPointerProperty *p) - { - std::map attr; - attr["type"] = "pointer"; - attr["name"] = p->getName(); - attr["value"] = p->getValueAsString(); - m_os.openCloseChild("property", attr); - } + void visit(TEnumProperty *p) { + std::map attr; + attr["type"] = "enum"; + attr["name"] = p->getName(); + attr["value"] = ::to_string(p->getValue()); + if (TEnumProperty::isRangeSavingEnabled()) { + m_os.openChild("property", attr); + std::vector range = p->getRange(); + for (int i = 0; i < (int)range.size(); i++) { + attr.clear(); + attr["value"] = ::to_string(range[i]); + m_os.openCloseChild("item", attr); + } + m_os.closeChild(); + } else + m_os.openCloseChild("property", attr); + } + void visit(TPointerProperty *p) { + std::map attr; + attr["type"] = "pointer"; + attr["name"] = p->getName(); + attr["value"] = p->getValueAsString(); + m_os.openCloseChild("property", attr); + } }; -void TPropertyGroup::loadData(TIStream &is) -{ - for (PropertyVector::iterator it = m_properties.begin(); - it != m_properties.end(); ++it) - if (it->second) - delete it->first; - m_properties.clear(); - m_table.clear(); - std::string tagName; - while (is.matchTag(tagName)) { - if (tagName == "property") { - std::string name = is.getTagAttribute("name"); - std::string type = is.getTagAttribute("type"); - std::string svalue = is.getTagAttribute("value"); - if (name == "") - throw TException("missing property name"); - if (type == "") - throw TException("missing property type"); - if (type != "string" && svalue == "") - throw TException("missing property value"); - if (type == "double") { - double min = std::stod(is.getTagAttribute("min")); - double max = std::stod(is.getTagAttribute("max")); - add(new TDoubleProperty(name, min, max, std::stod(svalue))); - } - if (type == "pair") { - double min = std::stod(is.getTagAttribute("min")); - double max = std::stod(is.getTagAttribute("max")); - TDoublePairProperty::Value v(0, 0); - int i = svalue.find(' '); - if (i != (int)std::string::npos) { - v.first = std::stod(svalue.substr(0, i)); - v.second = std::stod(svalue.substr(i + 1)); - } - add(new TDoublePairProperty(name, min, max, v.first, v.second)); - } else if (type == "int") { - int min = std::stoi(is.getTagAttribute("min")); - int max = std::stoi(is.getTagAttribute("max")); - add(new TIntProperty(name, min, max, std::stoi(svalue))); - } else if (type == "bool") { - if (svalue != "true" && svalue != "false") - throw TException("bad boolean property value"); - add(new TBoolProperty(name, svalue == "true" ? true : false)); - } else if (type == "string") { - add(new TStringProperty(name, ::to_wstring(svalue))); - } else if (type == "enum") { - TEnumProperty *p = new TEnumProperty(name); - if (is.isBeginEndTag()) - p->addValue(::to_wstring(svalue)); - else { - while (is.matchTag(tagName)) { - if (tagName == "item") { - std::string item = is.getTagAttribute("value"); - p->addValue(::to_wstring(item)); - } else - throw TException("expected range property "); - } - is.closeChild(); - } - p->setValue(::to_wstring(svalue)); - add(p); - } else - throw TException("unrecognized property type : " + type); - } else - throw TException("expected "); - // is.closeChild(); - } +void TPropertyGroup::loadData(TIStream &is) { + for (PropertyVector::iterator it = m_properties.begin(); + it != m_properties.end(); ++it) + if (it->second) delete it->first; + m_properties.clear(); + m_table.clear(); + std::string tagName; + while (is.matchTag(tagName)) { + if (tagName == "property") { + std::string name = is.getTagAttribute("name"); + std::string type = is.getTagAttribute("type"); + std::string svalue = is.getTagAttribute("value"); + if (name == "") throw TException("missing property name"); + if (type == "") throw TException("missing property type"); + if (type != "string" && svalue == "") + throw TException("missing property value"); + if (type == "double") { + double min = std::stod(is.getTagAttribute("min")); + double max = std::stod(is.getTagAttribute("max")); + add(new TDoubleProperty(name, min, max, std::stod(svalue))); + } + if (type == "pair") { + double min = std::stod(is.getTagAttribute("min")); + double max = std::stod(is.getTagAttribute("max")); + TDoublePairProperty::Value v(0, 0); + int i = svalue.find(' '); + if (i != (int)std::string::npos) { + v.first = std::stod(svalue.substr(0, i)); + v.second = std::stod(svalue.substr(i + 1)); + } + add(new TDoublePairProperty(name, min, max, v.first, v.second)); + } else if (type == "int") { + int min = std::stoi(is.getTagAttribute("min")); + int max = std::stoi(is.getTagAttribute("max")); + add(new TIntProperty(name, min, max, std::stoi(svalue))); + } else if (type == "bool") { + if (svalue != "true" && svalue != "false") + throw TException("bad boolean property value"); + add(new TBoolProperty(name, svalue == "true" ? true : false)); + } else if (type == "string") { + add(new TStringProperty(name, ::to_wstring(svalue))); + } else if (type == "enum") { + TEnumProperty *p = new TEnumProperty(name); + if (is.isBeginEndTag()) + p->addValue(::to_wstring(svalue)); + else { + while (is.matchTag(tagName)) { + if (tagName == "item") { + std::string item = is.getTagAttribute("value"); + p->addValue(::to_wstring(item)); + } else + throw TException("expected range property "); + } + is.closeChild(); + } + p->setValue(::to_wstring(svalue)); + add(p); + } else + throw TException("unrecognized property type : " + type); + } else + throw TException("expected "); + // is.closeChild(); + } } -void TPropertyGroup::saveData(TOStream &os) const -{ - PropertyWriter writer(os); - const_cast(this)->accept(writer); +void TPropertyGroup::saveData(TOStream &os) const { + PropertyWriter writer(os); + const_cast(this)->accept(writer); } -namespace -{ +namespace { bool EnumRangeSavingEnabled = true; } -void TEnumProperty::enableRangeSaving(bool on) -{ - EnumRangeSavingEnabled = on; -} +void TEnumProperty::enableRangeSaving(bool on) { EnumRangeSavingEnabled = on; } -bool TEnumProperty::isRangeSavingEnabled() -{ - return EnumRangeSavingEnabled; -} +bool TEnumProperty::isRangeSavingEnabled() { return EnumRangeSavingEnabled; } diff --git a/toonz/sources/common/traster/traster.cpp b/toonz/sources/common/traster/traster.cpp index 9e978a0..e219a79 100644 --- a/toonz/sources/common/traster/traster.cpp +++ b/toonz/sources/common/traster/traster.cpp @@ -19,154 +19,161 @@ DEFINE_CLASS_CODE(TRaster, 1) //------------------------------------------------------------ TRaster::TRaster(int lx, int ly, int pixelSize) - : TSmartObject(m_classCode), m_pixelSize(pixelSize), m_lx(lx), m_ly(ly), m_wrap(lx), m_parent(0), m_bufferOwner(true), m_buffer(0), m_lockCount(0) + : TSmartObject(m_classCode) + , m_pixelSize(pixelSize) + , m_lx(lx) + , m_ly(ly) + , m_wrap(lx) + , m_parent(0) + , m_bufferOwner(true) + , m_buffer(0) + , m_lockCount(0) #ifdef _DEBUG - , - m_cashed(false) + , m_cashed(false) #endif { - //try - { - assert(pixelSize > 0); - assert(lx > 0 && ly > 0); - TBigMemoryManager::instance()->putRaster(this); + // try + { + assert(pixelSize > 0); + assert(lx > 0 && ly > 0); + TBigMemoryManager::instance()->putRaster(this); - //m_buffer = new UCHAR[lx*ly*pixelSize]; + // m_buffer = new UCHAR[lx*ly*pixelSize]; - if (!m_buffer) { + if (!m_buffer) { #ifdef _WIN32 - static bool firstTime = true; - if (firstTime) { - firstTime = false; - unsigned long size = pixelSize * lx * ly; - TImageCache::instance()->outputMap(size, "C:\\runout"); - (*TBigMemoryManager::instance()->m_runOutCallback)(size); - } + static bool firstTime = true; + if (firstTime) { + firstTime = false; + unsigned long size = pixelSize * lx * ly; + TImageCache::instance()->outputMap(size, "C:\\runout"); + (*TBigMemoryManager::instance()->m_runOutCallback)(size); + } #endif - return; - } - - // TBigMemoryManager::instance()->checkConsistency(); - - //m_totalMemory += ((lx*ly*pixelSize)>>10); - } - /* catch(...) - { - TImageCache::instance()->putAllOnDisk(); - m_buffer = BigMemoryManager.getMemoryChunk(lx*ly*pixelSize, this); - //m_buffer = new UCHAR[lx*ly*pixelSize]; - m_totalMemory += ((lx*ly*pixelSize)>>10); - #ifdef _WIN32 - MessageBox( NULL, "Run out of contiguos phisical memory: please save all and restart toonz!", "Warning", MB_OK); - #endif - }*/ + return; + } + + // TBigMemoryManager::instance()->checkConsistency(); + + // m_totalMemory += ((lx*ly*pixelSize)>>10); + } + /* catch(...) +{ +TImageCache::instance()->putAllOnDisk(); +m_buffer = BigMemoryManager.getMemoryChunk(lx*ly*pixelSize, this); +//m_buffer = new UCHAR[lx*ly*pixelSize]; +m_totalMemory += ((lx*ly*pixelSize)>>10); +#ifdef _WIN32 +MessageBox( NULL, "Run out of contiguos phisical memory: please save all and +restart toonz!", "Warning", MB_OK); +#endif +}*/ } //------------------------------------------------------------ -TRaster::TRaster(int lx, int ly, int pixelSize, - int wrap, UCHAR *buffer, TRaster *parent, bool bufferOwner) - : TSmartObject(m_classCode), m_pixelSize(pixelSize), m_lx(lx), m_ly(ly), m_wrap(wrap), m_buffer(buffer), m_bufferOwner(bufferOwner), m_lockCount(0) +TRaster::TRaster(int lx, int ly, int pixelSize, int wrap, UCHAR *buffer, + TRaster *parent, bool bufferOwner) + : TSmartObject(m_classCode) + , m_pixelSize(pixelSize) + , m_lx(lx) + , m_ly(ly) + , m_wrap(wrap) + , m_buffer(buffer) + , m_bufferOwner(bufferOwner) + , m_lockCount(0) #ifdef _DEBUG - , - m_cashed(false) + , m_cashed(false) #endif { - if (parent) { - assert(bufferOwner == false); - while (parent->m_parent) - parent = parent->m_parent; - parent->addRef(); - } + if (parent) { + assert(bufferOwner == false); + while (parent->m_parent) parent = parent->m_parent; + parent->addRef(); + } #ifdef _DEBUG - else if (bufferOwner) - TBigMemoryManager::instance()->m_totRasterMemInKb += ((m_lx * m_ly * m_pixelSize) >> 10); + else if (bufferOwner) + TBigMemoryManager::instance()->m_totRasterMemInKb += + ((m_lx * m_ly * m_pixelSize) >> 10); #endif - m_parent = parent; + m_parent = parent; - assert(pixelSize > 0); - assert(lx > 0 && ly > 0); - assert(wrap >= lx); - assert(m_buffer); - //if (parent) - TBigMemoryManager::instance()->putRaster(this); + assert(pixelSize > 0); + assert(lx > 0 && ly > 0); + assert(wrap >= lx); + assert(m_buffer); + // if (parent) + TBigMemoryManager::instance()->putRaster(this); - // TBigMemoryManager::instance()->checkConsistency(); + // TBigMemoryManager::instance()->checkConsistency(); } //------------------------------------------------------------ -//TAtomicVar TRaster::m_totalMemory; +// TAtomicVar TRaster::m_totalMemory; //------------------------------------------------------------ -//unsigned long TRaster::getTotalMemoryInKB(){ return m_totalMemory;} +// unsigned long TRaster::getTotalMemoryInKB(){ return m_totalMemory;} //------------------------------------------------------------ -TRaster::~TRaster() -{ - bool parent = false; +TRaster::~TRaster() { + bool parent = false; #ifdef _DEBUG -//TBigMemoryManager::instance()->checkConsistency(); +// TBigMemoryManager::instance()->checkConsistency(); #endif - //bool ret = - TBigMemoryManager::instance()->releaseRaster(this); + // bool ret = + TBigMemoryManager::instance()->releaseRaster(this); #ifdef _DEBUG -//TBigMemoryManager::instance()->checkConsistency(); +// TBigMemoryManager::instance()->checkConsistency(); #endif - if (m_parent) { - assert(!m_bufferOwner); - m_parent->release(); - m_parent = 0; - parent = true; - } - - //if(m_buffer && m_bufferOwner) - // { - //delete [] m_buffer; - //m_totalMemory += -((m_lx*m_ly*m_pixelSize)>>10); - //assert(m_totalMemory>=0); - // } - // UCHAR* aux = m_buffer; - m_buffer = 0; + if (m_parent) { + assert(!m_bufferOwner); + m_parent->release(); + m_parent = 0; + parent = true; + } + + // if(m_buffer && m_bufferOwner) + // { + // delete [] m_buffer; + // m_totalMemory += -((m_lx*m_ly*m_pixelSize)>>10); + // assert(m_totalMemory>=0); + // } + // UCHAR* aux = m_buffer; + m_buffer = 0; #ifdef _DEBUG -//TBigMemoryManager::instance()->checkConsistency(); +// TBigMemoryManager::instance()->checkConsistency(); #endif } //------------------------------------------------------------ -void TRaster::beginRemapping() -{ - m_mutex.lock(); -} +void TRaster::beginRemapping() { m_mutex.lock(); } -void TRaster::endRemapping() -{ - m_mutex.unlock(); -} +void TRaster::endRemapping() { m_mutex.unlock(); } /* - void TRaster::lock() + void TRaster::lock() { if (m_parent) m_parent->lock(); else ++m_lockCount; //TBigMemoryManager::instance()->lock(m_parent?(m_parent->m_buffer):m_buffer); } - + void TRaster::unlock() { if (m_parent) m_parent->unlock(); - else + else { assert(m_lockCount>0); --m_lockCount; } - + //TBigMemoryManager::instance()->unlock(m_parent?(m_parent->m_buffer):m_buffer); } */ @@ -177,295 +184,281 @@ template // utilizzo di un raster preesistente template - TRasterT::TRasterT(int lx, int ly, int wrap, T *buffer, TRasterT *parent) + TRasterT::TRasterT(int lx, int ly, int wrap, T *buffer, TRasterT +*parent) : TRaster(lx,ly,sizeof(T), wrap , reinterpret_cast(buffer), parent) {} */ //------------------------------------------------------------ -void TRaster::fillRawData(const UCHAR *color) -{ - if (m_lx == 0 || m_ly == 0) - return; - - // N.B. uso la convenzione stl per end() - - const int wrapSize = m_wrap * m_pixelSize; - const int rowSize = m_lx * m_pixelSize; - UCHAR *buf1 = m_parent ? m_parent->m_buffer : m_buffer; - lock(); - unsigned char *firstPixel = getRawData(); - const unsigned char *lastPixel = firstPixel + - wrapSize * (m_ly - 1) + m_pixelSize * (m_lx - 1); - - // riempio la prima riga - unsigned char *pixel = firstPixel; - const unsigned char *endpixel = firstPixel + rowSize; - while (pixel < endpixel) { - assert(firstPixel <= pixel && pixel <= lastPixel); - ::memcpy(pixel, color, m_pixelSize); - pixel += m_pixelSize; - } - - // riempio le altre - pixel += wrapSize - rowSize; - const unsigned char *endrow = pixel + wrapSize * (m_ly - 1); - while (pixel < endrow) { - assert(firstPixel <= pixel && pixel + rowSize - m_pixelSize <= lastPixel); - ::memcpy(pixel, firstPixel, rowSize); - pixel += wrapSize; - } - UCHAR *buf2 = m_parent ? m_parent->m_buffer : m_buffer; - unlock(); +void TRaster::fillRawData(const UCHAR *color) { + if (m_lx == 0 || m_ly == 0) return; + + // N.B. uso la convenzione stl per end() + + const int wrapSize = m_wrap * m_pixelSize; + const int rowSize = m_lx * m_pixelSize; + UCHAR *buf1 = m_parent ? m_parent->m_buffer : m_buffer; + lock(); + unsigned char *firstPixel = getRawData(); + const unsigned char *lastPixel = + firstPixel + wrapSize * (m_ly - 1) + m_pixelSize * (m_lx - 1); + + // riempio la prima riga + unsigned char *pixel = firstPixel; + const unsigned char *endpixel = firstPixel + rowSize; + while (pixel < endpixel) { + assert(firstPixel <= pixel && pixel <= lastPixel); + ::memcpy(pixel, color, m_pixelSize); + pixel += m_pixelSize; + } + + // riempio le altre + pixel += wrapSize - rowSize; + const unsigned char *endrow = pixel + wrapSize * (m_ly - 1); + while (pixel < endrow) { + assert(firstPixel <= pixel && pixel + rowSize - m_pixelSize <= lastPixel); + ::memcpy(pixel, firstPixel, rowSize); + pixel += wrapSize; + } + UCHAR *buf2 = m_parent ? m_parent->m_buffer : m_buffer; + unlock(); } //------------------------------------------------------------ -void TRaster::fillRawDataOutside(const TRect &rect, const unsigned char *pixel) -{ - if (m_lx == 0 || m_ly == 0) - return; - TRect r = rect * getBounds(); - if (r.isEmpty()) - return; - - if (r.y0 > 0) // fascia "inferiore" - { - TRect bounds(0, 0, m_lx - 1, r.y0 - 1); - extract(bounds)->fillRawData(pixel); - } - - if (rect.y1 < m_ly - 1) // fascia "superiore" - { - TRect bounds(0, r.y1 + 1, m_lx - 1, m_ly - 1); - extract(bounds)->fillRawData(pixel); - } - - if (rect.x0 > 0) // zona "a sinistra" - { - TRect bounds(0, r.y0, r.x0 - 1, r.y1); - extract(bounds)->fillRawData(pixel); - } - - if (rect.x1 < m_lx - 1) // zona "a destra" - { - TRect bounds(r.x1 + 1, r.y0, m_lx - 1, r.y1); - extract(bounds)->fillRawData(pixel); - } +void TRaster::fillRawDataOutside(const TRect &rect, + const unsigned char *pixel) { + if (m_lx == 0 || m_ly == 0) return; + TRect r = rect * getBounds(); + if (r.isEmpty()) return; + + if (r.y0 > 0) // fascia "inferiore" + { + TRect bounds(0, 0, m_lx - 1, r.y0 - 1); + extract(bounds)->fillRawData(pixel); + } + + if (rect.y1 < m_ly - 1) // fascia "superiore" + { + TRect bounds(0, r.y1 + 1, m_lx - 1, m_ly - 1); + extract(bounds)->fillRawData(pixel); + } + + if (rect.x0 > 0) // zona "a sinistra" + { + TRect bounds(0, r.y0, r.x0 - 1, r.y1); + extract(bounds)->fillRawData(pixel); + } + + if (rect.x1 < m_lx - 1) // zona "a destra" + { + TRect bounds(r.x1 + 1, r.y0, m_lx - 1, r.y1); + extract(bounds)->fillRawData(pixel); + } } //------------------------------------------------------------ -void TRaster::copy(const TRasterP &src0, const TPoint &offset) -{ - assert(m_pixelSize == src0->getPixelSize()); - TRect rect = getBounds() * (src0->getBounds() + offset); - if (rect.isEmpty()) - return; - TRasterP dst = extract(rect); - TRect r(rect); - r -= offset; - //TRasterP src = src0->extract(rect - offset); - TRasterP src = src0->extract(r); - assert(dst->getSize() == src->getSize()); - dst->lock(); - src0->lock(); - if (dst->getLx() == dst->getWrap() && src->getLx() == src->getWrap()) { - int size = rect.getLx() * rect.getLy() * m_pixelSize; - ::memcpy(dst->getRawData(), src->getRawData(), size); - } else { - int rowSize = dst->getLx() * m_pixelSize; - int srcWrapSize = src->getWrap() * m_pixelSize; - int dstWrapSize = dst->getWrap() * m_pixelSize; - const UCHAR *srcRow = src->getRawData(); - UCHAR *dstRow = dst->getRawData(); - UCHAR *maxDstRow = dstRow + dstWrapSize * dst->getLy(); - while (dstRow < maxDstRow) { - ::memcpy(dstRow, srcRow, rowSize); - dstRow += dstWrapSize; - srcRow += srcWrapSize; - } - } - dst->unlock(); - src0->unlock(); +void TRaster::copy(const TRasterP &src0, const TPoint &offset) { + assert(m_pixelSize == src0->getPixelSize()); + TRect rect = getBounds() * (src0->getBounds() + offset); + if (rect.isEmpty()) return; + TRasterP dst = extract(rect); + TRect r(rect); + r -= offset; + // TRasterP src = src0->extract(rect - offset); + TRasterP src = src0->extract(r); + assert(dst->getSize() == src->getSize()); + dst->lock(); + src0->lock(); + if (dst->getLx() == dst->getWrap() && src->getLx() == src->getWrap()) { + int size = rect.getLx() * rect.getLy() * m_pixelSize; + ::memcpy(dst->getRawData(), src->getRawData(), size); + } else { + int rowSize = dst->getLx() * m_pixelSize; + int srcWrapSize = src->getWrap() * m_pixelSize; + int dstWrapSize = dst->getWrap() * m_pixelSize; + const UCHAR *srcRow = src->getRawData(); + UCHAR *dstRow = dst->getRawData(); + UCHAR *maxDstRow = dstRow + dstWrapSize * dst->getLy(); + while (dstRow < maxDstRow) { + ::memcpy(dstRow, srcRow, rowSize); + dstRow += dstWrapSize; + srcRow += srcWrapSize; + } + } + dst->unlock(); + src0->unlock(); } //------------------------------------------------------------ -void TRaster::yMirror() -{ - const int rowSize = m_lx * m_pixelSize; - const int wrapSize = m_wrap * m_pixelSize; - std::unique_ptr auxBuf(new UCHAR[rowSize]); - lock(); - UCHAR *buff1 = getRawData(); - UCHAR *buff2 = getRawData(0, (m_ly - 1)); - while (buff1 < buff2) { - ::memcpy(auxBuf.get(), buff1, rowSize); - ::memcpy(buff1, buff2, rowSize); - ::memcpy(buff2, auxBuf.get(), rowSize); - buff1 += wrapSize; - buff2 -= wrapSize; - } - unlock(); +void TRaster::yMirror() { + const int rowSize = m_lx * m_pixelSize; + const int wrapSize = m_wrap * m_pixelSize; + std::unique_ptr auxBuf(new UCHAR[rowSize]); + lock(); + UCHAR *buff1 = getRawData(); + UCHAR *buff2 = getRawData(0, (m_ly - 1)); + while (buff1 < buff2) { + ::memcpy(auxBuf.get(), buff1, rowSize); + ::memcpy(buff1, buff2, rowSize); + ::memcpy(buff2, auxBuf.get(), rowSize); + buff1 += wrapSize; + buff2 -= wrapSize; + } + unlock(); } //------------------------------------------------------------ -void TRaster::xMirror() -{ - const int wrapSize = m_wrap * m_pixelSize; - const int lastPixelOffset = (m_lx - 1) * m_pixelSize; - std::unique_ptr auxBuf(new UCHAR[m_pixelSize]); - lock(); - UCHAR *row = getRawData(); - for (int i = 0; i < m_ly; i++) { - UCHAR *a = row, *b = row + lastPixelOffset; - while (a < b) { - ::memcpy(auxBuf.get(), a, m_pixelSize); - ::memcpy(a, b, m_pixelSize); - ::memcpy(b, auxBuf.get(), m_pixelSize); - a += m_pixelSize; - b -= m_pixelSize; - } - row += wrapSize; - } - unlock(); +void TRaster::xMirror() { + const int wrapSize = m_wrap * m_pixelSize; + const int lastPixelOffset = (m_lx - 1) * m_pixelSize; + std::unique_ptr auxBuf(new UCHAR[m_pixelSize]); + lock(); + UCHAR *row = getRawData(); + for (int i = 0; i < m_ly; i++) { + UCHAR *a = row, *b = row + lastPixelOffset; + while (a < b) { + ::memcpy(auxBuf.get(), a, m_pixelSize); + ::memcpy(a, b, m_pixelSize); + ::memcpy(b, auxBuf.get(), m_pixelSize); + a += m_pixelSize; + b -= m_pixelSize; + } + row += wrapSize; + } + unlock(); } //------------------------------------------------------------ -void TRaster::rotate180() -{ - //const int rowSize = m_lx * m_pixelSize; - const int wrapSize = m_wrap * m_pixelSize; - std::unique_ptr auxBuf(new UCHAR[m_pixelSize]); - lock(); - UCHAR *buff1 = getRawData(); - UCHAR *buff2 = buff1 + wrapSize * (m_ly - 1) + m_pixelSize * (m_lx - 1); - if (m_wrap == m_lx) { - while (buff1 < buff2) { - ::memcpy(auxBuf.get(), buff1, m_pixelSize); - ::memcpy(buff1, buff2, m_pixelSize); - ::memcpy(buff2, auxBuf.get(), m_pixelSize); - buff1 += m_pixelSize; - buff2 -= m_pixelSize; - } - } else { - for (int y = 0; y < m_ly / 2; y++) { - UCHAR *a = buff1, *b = buff2; - for (int x = 0; x < m_lx; x++) { - ::memcpy(auxBuf.get(), a, m_pixelSize); - ::memcpy(a, b, m_pixelSize); - ::memcpy(b, auxBuf.get(), m_pixelSize); - a += m_pixelSize; - b -= m_pixelSize; - } - buff1 += wrapSize; - buff2 -= wrapSize; - } - } - unlock(); +void TRaster::rotate180() { + // const int rowSize = m_lx * m_pixelSize; + const int wrapSize = m_wrap * m_pixelSize; + std::unique_ptr auxBuf(new UCHAR[m_pixelSize]); + lock(); + UCHAR *buff1 = getRawData(); + UCHAR *buff2 = buff1 + wrapSize * (m_ly - 1) + m_pixelSize * (m_lx - 1); + if (m_wrap == m_lx) { + while (buff1 < buff2) { + ::memcpy(auxBuf.get(), buff1, m_pixelSize); + ::memcpy(buff1, buff2, m_pixelSize); + ::memcpy(buff2, auxBuf.get(), m_pixelSize); + buff1 += m_pixelSize; + buff2 -= m_pixelSize; + } + } else { + for (int y = 0; y < m_ly / 2; y++) { + UCHAR *a = buff1, *b = buff2; + for (int x = 0; x < m_lx; x++) { + ::memcpy(auxBuf.get(), a, m_pixelSize); + ::memcpy(a, b, m_pixelSize); + ::memcpy(b, auxBuf.get(), m_pixelSize); + a += m_pixelSize; + b -= m_pixelSize; + } + buff1 += wrapSize; + buff2 -= wrapSize; + } + } + unlock(); } //------------------------------------------------------------ -void TRaster::rotate90() -{ - /* - UCHAR *auxBuf= new UCHAR[m_pixelSize]; +void TRaster::rotate90() { + /* + UCHAR *auxBuf= new UCHAR[m_pixelSize]; - - for(int y=m_ly;y>0;y--) - { - UCHAR *a = getRawData() + wrapSize * (y-1) + m_pixelSize * (m_lx-1); - for (int x=m_lx-1;x>=0;x--) - { - UCHAR *b = a - (m_ly-1)*m_pixelSize *(m_lx-x); - ::memcpy(auxBuf, a, m_pixelSize); - ::memcpy(a, b, m_pixelSize); - ::memcpy(b, auxBuf, m_pixelSize); - a-=m_pixelSize; - } +for(int y=m_ly;y>0;y--) +{ + UCHAR *a = getRawData() + wrapSize * (y-1) + m_pixelSize * (m_lx-1); +for (int x=m_lx-1;x>=0;x--) + { + UCHAR *b = a - (m_ly-1)*m_pixelSize *(m_lx-x); + ::memcpy(auxBuf, a, m_pixelSize); + ::memcpy(a, b, m_pixelSize); + ::memcpy(b, auxBuf, m_pixelSize); + a-=m_pixelSize; } - */ + +} +*/ } //------------------------------------------------------------ -void TRaster::clear() -{ - TRasterCM32 *ras = dynamic_cast(this); - if (ras) { - // ras->fill(TPixelCM32(0,BackgroundStyle,TPixelCM32::getMaxTone())); - ras->fill(TPixelCM32()); - } else { - const int rowSize = getRowSize(); - lock(); - if (m_wrap == m_lx) { - int bufferSize = rowSize * m_ly; - memset(getRawData(), 0, bufferSize); - } else - for (int y = m_ly - 1; y >= 0; y--) { - UCHAR *buffer = getRawData(0, y); - memset(buffer, 0, rowSize); - } - unlock(); - } +void TRaster::clear() { + TRasterCM32 *ras = dynamic_cast(this); + if (ras) { + // ras->fill(TPixelCM32(0,BackgroundStyle,TPixelCM32::getMaxTone())); + ras->fill(TPixelCM32()); + } else { + const int rowSize = getRowSize(); + lock(); + if (m_wrap == m_lx) { + int bufferSize = rowSize * m_ly; + memset(getRawData(), 0, bufferSize); + } else + for (int y = m_ly - 1; y >= 0; y--) { + UCHAR *buffer = getRawData(0, y); + memset(buffer, 0, rowSize); + } + unlock(); + } } //------------------------------------------------------------ -void TRaster::remap(UCHAR *newLocation) -{ - if (m_parent) { - assert(m_parent->m_buffer > newLocation); +void TRaster::remap(UCHAR *newLocation) { + if (m_parent) { + assert(m_parent->m_buffer > newLocation); - assert(m_parent->m_parent == 0); + assert(m_parent->m_parent == 0); - int offset = (int)(m_buffer - m_parent->m_buffer); - assert(offset >= 0); + int offset = (int)(m_buffer - m_parent->m_buffer); + assert(offset >= 0); - //m_parent->remap(newLocation); - m_buffer = newLocation + offset; - } else { - assert(m_buffer > newLocation); - m_buffer = newLocation; - } + // m_parent->remap(newLocation); + m_buffer = newLocation + offset; + } else { + assert(m_buffer > newLocation); + m_buffer = newLocation; + } } //------------------------------------------------------------ -void TRaster::clearOutside(const TRect &rect) -{ - if (m_lx == 0 || m_ly == 0) - return; - TRect r = rect * getBounds(); - if (r.isEmpty()) - return; - - if (r.y0 > 0) // fascia "inferiore" - { - TRect bounds(0, 0, m_lx - 1, r.y0 - 1); - extract(bounds)->clear(); - } - - if (rect.y1 < m_ly - 1) // fascia "superiore" - { - TRect bounds(0, r.y1 + 1, m_lx - 1, m_ly - 1); - extract(bounds)->clear(); - } - - if (rect.x0 > 0) // zona "a sinistra" - { - TRect bounds(0, r.y0, r.x0 - 1, r.y1); - extract(bounds)->clear(); - } - - if (rect.x1 < m_lx - 1) // zona "a destra" - { - TRect bounds(r.x1 + 1, r.y0, m_lx - 1, r.y1); - extract(bounds)->clear(); - } +void TRaster::clearOutside(const TRect &rect) { + if (m_lx == 0 || m_ly == 0) return; + TRect r = rect * getBounds(); + if (r.isEmpty()) return; + + if (r.y0 > 0) // fascia "inferiore" + { + TRect bounds(0, 0, m_lx - 1, r.y0 - 1); + extract(bounds)->clear(); + } + + if (rect.y1 < m_ly - 1) // fascia "superiore" + { + TRect bounds(0, r.y1 + 1, m_lx - 1, m_ly - 1); + extract(bounds)->clear(); + } + + if (rect.x0 > 0) // zona "a sinistra" + { + TRect bounds(0, r.y0, r.x0 - 1, r.y1); + extract(bounds)->clear(); + } + + if (rect.x1 < m_lx - 1) // zona "a destra" + { + TRect bounds(r.x1 + 1, r.y0, m_lx - 1, r.y1); + extract(bounds)->clear(); + } } diff --git a/toonz/sources/common/trasterimage/tcachedlevel.cpp b/toonz/sources/common/trasterimage/tcachedlevel.cpp index 8edcccd..c05bb3a 100644 --- a/toonz/sources/common/trasterimage/tcachedlevel.cpp +++ b/toonz/sources/common/trasterimage/tcachedlevel.cpp @@ -1,4 +1,4 @@ - +#include #include "tsystem.h" #include "tcachedlevel.h" @@ -36,165 +36,159 @@ // TDiskCachePersist //------------------------------------------------------------------------------ -class ImpPD -{ +class ImpPD { public: - ImpPD(const TFilePath &fn) - : m_fname(fn), m_chunkSize(0), m_currentFileSize(0), m_fileMapAddress(0), m_mapOffset(0) - { - TFileStatus fileStatus(fn); - if (fileStatus.doesExist()) - m_currentFileSize = fileStatus.getSize(); - else - m_currentFileSize = ImpPD::m_defaultFileSize; - }; - virtual ~ImpPD() {} - virtual void openFile(const TFilePath &, TINT64 fileSize) = 0; - virtual void setCurrentView(int pos, int &newLowPos, int &newHiPos) = 0; - TFilePath m_fname; - - TINT64 m_chunkSize; - TINT64 m_currentFileSize; - void *m_fileMapAddress; - TINT64 m_mapOffset; - - // quantita' espresse in byte - static TINT64 m_defaultFileSize; - TUINT32 m_viewSize; - TINT64 m_reallocSize; + ImpPD(const TFilePath &fn) + : m_fname(fn) + , m_chunkSize(0) + , m_currentFileSize(0) + , m_fileMapAddress(0) + , m_mapOffset(0) { + TFileStatus fileStatus(fn); + if (fileStatus.doesExist()) + m_currentFileSize = fileStatus.getSize(); + else + m_currentFileSize = ImpPD::m_defaultFileSize; + }; + virtual ~ImpPD() {} + virtual void openFile(const TFilePath &, TINT64 fileSize) = 0; + virtual void setCurrentView(int pos, int &newLowPos, int &newHiPos) = 0; + TFilePath m_fname; + + TINT64 m_chunkSize; + TINT64 m_currentFileSize; + void *m_fileMapAddress; + TINT64 m_mapOffset; + + // quantita' espresse in byte + static TINT64 m_defaultFileSize; + TUINT32 m_viewSize; + TINT64 m_reallocSize; }; TINT64 ImpPD::m_defaultFileSize(100 * 1024 * 1024); //------------------------------------------------------------------------------ -class TDiskCachePersist::Imp -{ +class TDiskCachePersist::Imp { public: - Imp(const TFilePath &fp); - ~Imp(); - - bool put(int frame, UCHAR *data, TUINT32 dataSize); - UCHAR *get(int pos, TUINT32 *size); - void openFile(const TFilePath &fp, TINT64 fileSize); - void setCurrentView(int frame) - { - if (!m_force && ((m_lowFrame <= frame) && (frame < m_hiFrame))) - return; //la vista corrente gia' copre il frame - m_force = false; - m_impPD->setCurrentView(frame, m_lowFrame, m_hiFrame); - } - - ImpPD *m_impPD; - - int m_lowFrame, m_hiFrame; - TThread::Mutex m_mutex; - - bool m_force; + Imp(const TFilePath &fp); + ~Imp(); + + bool put(int frame, UCHAR *data, TUINT32 dataSize); + UCHAR *get(int pos, TUINT32 *size); + void openFile(const TFilePath &fp, TINT64 fileSize); + void setCurrentView(int frame) { + if (!m_force && ((m_lowFrame <= frame) && (frame < m_hiFrame))) + return; // la vista corrente gia' copre il frame + m_force = false; + m_impPD->setCurrentView(frame, m_lowFrame, m_hiFrame); + } + + ImpPD *m_impPD; + + int m_lowFrame, m_hiFrame; + TThread::Mutex m_mutex; + + bool m_force; }; #ifdef WIN32 -class ImpPDW : public ImpPD -{ +class ImpPDW : public ImpPD { private: - string getLastErrorMessage() - { - LPVOID lpMsgBuf; - - DWORD err = GetLastError(); - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - err, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - (LPTSTR)&lpMsgBuf, - 0, - NULL); - - string msg((LPCTSTR)lpMsgBuf); - - // Free the buffer. - LocalFree(lpMsgBuf); - return msg; - } + string getLastErrorMessage() { + LPVOID lpMsgBuf; + + DWORD err = GetLastError(); + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, err, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR)&lpMsgBuf, 0, NULL); + + string msg((LPCTSTR)lpMsgBuf); + + // Free the buffer. + LocalFree(lpMsgBuf); + return msg; + } public: - ImpPDW(const TFilePath &fp); - ~ImpPDW(); - void openFile(const TFilePath &fname, TINT64 fileSize); - void setCurrentView(int pos, int &newLowPos, int &newHiPos); + ImpPDW(const TFilePath &fp); + ~ImpPDW(); + void openFile(const TFilePath &fname, TINT64 fileSize); + void setCurrentView(int pos, int &newLowPos, int &newHiPos); private: - HANDLE m_hFile; - HANDLE m_hMap; + HANDLE m_hFile; + HANDLE m_hMap; - SYSTEM_INFO m_systemInfo; + SYSTEM_INFO m_systemInfo; }; #else -class ImpPDX : public ImpPD -{ +class ImpPDX : public ImpPD { private: - class TCachedLevelException : public TException - { - static string msgFromErrorCode(int errorCode) - { - switch (errorCode) { - case EBADF: - return " fd is not a valid file descriptor (and MAP_ANONY­MOUS was not set)."; - break; - /* - case EACCES_MAP_PRIVATE: - return "Map private was requested, but fd is not open for reading. Or MAP_SHARED was requested and PROT_WRITE is set, but fd is not open in read/write O_RDWR) mode."; - break; + class TCachedLevelException : public TException { + static string msgFromErrorCode(int errorCode) { + switch (errorCode) { + case EBADF: + return " fd is not a valid file descriptor (and MAP_ANONY­MOUS was " + "not set)."; + break; + /* +case EACCES_MAP_PRIVATE: +return "Map private was requested, but fd is not open for reading. Or MAP_SHARED +was requested and PROT_WRITE is set, but fd is not open in read/write O_RDWR) +mode."; +break; */ - case EINVAL: - return "We don't like start or length or offset. (E.g., they are too large, or not aligned on a PAGESIZE boundary.)"; - break; - - case ETXTBSY: - return "MAP_DENYWRITE was set but the object specified by fd is open for writing."; - break; - - case EAGAIN: - return "The file has been locked, or too much memory has been locked."; - break; - - case ENOMEM: - return "No memory is available."; - break; - - default: - char *sysErr = strerror(errorCode); - ostrstream os; - os << errorCode << '\0'; - os.freeze(false); - return string(sysErr) + "(" + os.str() + ")"; - break; - } - return ""; - } - - public: - TCachedLevelException(int errorCode) - : TException(msgFromErrorCode(errorCode)) - { - } - ~TCachedLevelException() {} - }; + case EINVAL: + return "We don't like start or length or offset. (E.g., they are " + "too large, or not aligned on a PAGESIZE boundary.)"; + break; + + case ETXTBSY: + return "MAP_DENYWRITE was set but the object specified by fd is open " + "for writing."; + break; + + case EAGAIN: + return "The file has been locked, or too much memory has been " + "locked."; + break; + + case ENOMEM: + return "No memory is available."; + break; + + default: + char *sysErr = strerror(errorCode); + ostringstream os; + os << errorCode << '\0'; + return string(sysErr) + "(" + os.str() + ")"; + break; + } + return ""; + } + + public: + TCachedLevelException(int errorCode) + : TException(msgFromErrorCode(errorCode)) {} + ~TCachedLevelException() {} + }; public: - ImpPDX(const TFilePath &fp); - ~ImpPDX(); - void openFile(const TFilePath &fname, TINT64 fileSize); - void setCurrentView(int pos, int &newLowPos, int &newHiPos); + ImpPDX(const TFilePath &fp); + ~ImpPDX(); + void openFile(const TFilePath &fname, TINT64 fileSize); + void setCurrentView(int pos, int &newLowPos, int &newHiPos); private: - int m_fd; - size_t m_pageSize; + int m_fd; + size_t m_pageSize; }; #endif @@ -203,263 +197,241 @@ private: //------------------------------------------------------------------------------ TDiskCachePersist::TDiskCachePersist(TRasterCodec *codec, const TFilePath &fp) - : TCachePersist(codec), m_imp(new Imp(fp)) -{ -} + : TCachePersist(codec), m_imp(new Imp(fp)) {} //------------------------------------------------------------------------------ -TDiskCachePersist::~TDiskCachePersist() -{ - delete m_imp; -} +TDiskCachePersist::~TDiskCachePersist() { delete m_imp; } //------------------------------------------------------------------------------ -void TDiskCachePersist::setFrameSize(int lx, int ly, int bpp) -{ - m_imp->m_impPD->m_chunkSize = lx * ly * (bpp >> 3) + m_codec->getHeaderSize(); - m_imp->m_force = true; +void TDiskCachePersist::setFrameSize(int lx, int ly, int bpp) { + m_imp->m_impPD->m_chunkSize = lx * ly * (bpp >> 3) + m_codec->getHeaderSize(); + m_imp->m_force = true; } //------------------------------------------------------------------------------ -TRasterP TDiskCachePersist::doGetRaster(int frame) -{ - TRasterP rasP; - TUINT32 size; - UCHAR *src = m_imp->get(frame, &size); - m_codec->decompress(src, size, rasP); - delete[] src; - return rasP; +TRasterP TDiskCachePersist::doGetRaster(int frame) { + TRasterP rasP; + TUINT32 size; + UCHAR *src = m_imp->get(frame, &size); + m_codec->decompress(src, size, rasP); + delete[] src; + return rasP; } //------------------------------------------------------------------------------ -bool TDiskCachePersist::doGetRaster(int frame, TRaster32P &ras) const -{ - assert(false); - return false; +bool TDiskCachePersist::doGetRaster(int frame, TRaster32P &ras) const { + assert(false); + return false; } //------------------------------------------------------------------------------ -bool TDiskCachePersist::doPutRaster(int frame, const TRasterP &ras) -{ - UCHAR *outData = 0; - TINT32 outDataSize = 0; - m_codec->compress(ras, 1, &outData, outDataSize); - bool cached = m_imp->put(frame, outData, outDataSize); - delete[] outData; - return cached; +bool TDiskCachePersist::doPutRaster(int frame, const TRasterP &ras) { + UCHAR *outData = 0; + TINT32 outDataSize = 0; + m_codec->compress(ras, 1, &outData, outDataSize); + bool cached = m_imp->put(frame, outData, outDataSize); + delete[] outData; + return cached; } //------------------------------------------------------------------------------ -UCHAR *TDiskCachePersist::getRawData(int frame, TINT32 &size, int &lx, int &ly) -{ - TUINT32 inDataSize; - UCHAR *src = m_imp->get(frame, &inDataSize); - return m_codec->removeHeader(src, inDataSize, size, lx, ly); +UCHAR *TDiskCachePersist::getRawData(int frame, TINT32 &size, int &lx, + int &ly) { + TUINT32 inDataSize; + UCHAR *src = m_imp->get(frame, &inDataSize); + return m_codec->removeHeader(src, inDataSize, size, lx, ly); } //------------------------------------------------------------------------------ // MEDIUM -TDiskCachePersist::Imp::Imp(const TFilePath &fp) - : m_impPD(0) -{ +TDiskCachePersist::Imp::Imp(const TFilePath &fp) : m_impPD(0) { #ifdef WIN32 - m_impPD = new ImpPDW(fp); + m_impPD = new ImpPDW(fp); #else - m_impPD = new ImpPDX(fp); + m_impPD = new ImpPDX(fp); #endif - m_impPD->m_currentFileSize = TFileStatus(fp).doesExist() ? TFileStatus(fp).getSize() : 0; // per gli arrotondamenti... + m_impPD->m_currentFileSize = TFileStatus(fp).doesExist() + ? TFileStatus(fp).getSize() + : 0; // per gli arrotondamenti... } //------------------------------------------------------------------------------ -TDiskCachePersist::Imp::~Imp() -{ - delete m_impPD; -} +TDiskCachePersist::Imp::~Imp() { delete m_impPD; } //------------------------------------------------------------------------------ // LOW #ifdef WIN32 -ImpPDW::ImpPDW(const TFilePath &fp) - : ImpPD(fp), m_hFile(0), m_hMap(0) -{ - GetSystemInfo(&m_systemInfo); +ImpPDW::ImpPDW(const TFilePath &fp) : ImpPD(fp), m_hFile(0), m_hMap(0) { + GetSystemInfo(&m_systemInfo); - m_viewSize = 100 * 1024 * 1024; - m_reallocSize = 250 * 1024 * 1024; + m_viewSize = 100 * 1024 * 1024; + m_reallocSize = 250 * 1024 * 1024; - TINT64 allocUnitCount = m_reallocSize / m_systemInfo.dwAllocationGranularity; + TINT64 allocUnitCount = m_reallocSize / m_systemInfo.dwAllocationGranularity; - // rendo m_reallocSize multiplo di m_systemInfo.dwAllocationGranularity - if ((m_reallocSize % m_systemInfo.dwAllocationGranularity) != 0) - ++allocUnitCount; + // rendo m_reallocSize multiplo di m_systemInfo.dwAllocationGranularity + if ((m_reallocSize % m_systemInfo.dwAllocationGranularity) != 0) + ++allocUnitCount; - m_reallocSize = allocUnitCount * m_systemInfo.dwAllocationGranularity; + m_reallocSize = allocUnitCount * m_systemInfo.dwAllocationGranularity; - TINT64 fileSize = m_defaultFileSize; + TINT64 fileSize = m_defaultFileSize; - TFileStatus fileStatus(fp); - if (fileStatus.doesExist()) - fileSize = fileStatus.getSize(); + TFileStatus fileStatus(fp); + if (fileStatus.doesExist()) fileSize = fileStatus.getSize(); - try { - openFile(fp, fileSize); - } catch (TException &e) { - m_currentFileSize = 0; - throw e; - } + try { + openFile(fp, fileSize); + } catch (TException &e) { + m_currentFileSize = 0; + throw e; + } - m_currentFileSize = fileSize; + m_currentFileSize = fileSize; } //------------------------------------------------------------------------------ -ImpPDW::~ImpPDW() -{ - if (m_fileMapAddress) - UnmapViewOfFile(m_fileMapAddress); - CloseHandle(m_hMap); - CloseHandle(m_hFile); +ImpPDW::~ImpPDW() { + if (m_fileMapAddress) UnmapViewOfFile(m_fileMapAddress); + CloseHandle(m_hMap); + CloseHandle(m_hFile); } //------------------------------------------------------------------------------ -void ImpPDW::openFile(const TFilePath &fname, TINT64 fileSize) -{ - DWORD dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; - DWORD dwShareMode = 0; // dwShareMode == 0 --> accesso esclusivo - - // lpSecurityAttributes == NULL --> l'handle non puo' essere - // ereditato da processi figli - LPSECURITY_ATTRIBUTES lpSecurityAttributes = NULL; - - DWORD dwCreationDisposition = OPEN_ALWAYS; //CREATE_ALWAYS; - DWORD dwFlagsAndAttributes = FILE_FLAG_SEQUENTIAL_SCAN; //FILE_ATTRIBUTE_NORMAL;// - - HANDLE hTemplateFile = NULL; - - m_hFile = CreateFileW( - fname.getWideString().c_str(), // file name - dwDesiredAccess, // access mode - dwShareMode, // share mode - NULL, // SD - dwCreationDisposition, // how to create - dwFlagsAndAttributes, // file attributes - hTemplateFile // handle to template file - ); - - if (m_hFile == INVALID_HANDLE_VALUE) { - string errMsg = getLastErrorMessage(); - throw TException(wstring(L"Unable to open cache file: ") + fname.getWideString() + L"\n" + toWideString(errMsg)); - } - - DWORD flProtect = PAGE_READWRITE; - DWORD dwMaximumSizeHigh = DWORDLONG_HI_DWORD(fileSize); - DWORD dwMaximumSizeLow = DWORDLONG_LO_DWORD(fileSize); - LPCTSTR lpName = NULL; // l'oggetto non ha nome - - m_hMap = CreateFileMapping( - m_hFile, // handle to file - NULL, // security - flProtect, // protection - dwMaximumSizeHigh, // high-order DWORD of size - dwMaximumSizeLow, // low-order DWORD of size - lpName // object name - ); - - if (m_hMap == NULL) { - string errMsg = getLastErrorMessage(); - CloseHandle(m_hFile); - m_hFile = 0; - throw TException("Unable to create file mapping. " + errMsg); - } +void ImpPDW::openFile(const TFilePath &fname, TINT64 fileSize) { + DWORD dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; + DWORD dwShareMode = 0; // dwShareMode == 0 --> accesso esclusivo + + // lpSecurityAttributes == NULL --> l'handle non puo' essere + // ereditato da processi figli + LPSECURITY_ATTRIBUTES lpSecurityAttributes = NULL; + + DWORD dwCreationDisposition = OPEN_ALWAYS; // CREATE_ALWAYS; + DWORD dwFlagsAndAttributes = + FILE_FLAG_SEQUENTIAL_SCAN; // FILE_ATTRIBUTE_NORMAL;// + + HANDLE hTemplateFile = NULL; + + m_hFile = CreateFileW(fname.getWideString().c_str(), // file name + dwDesiredAccess, // access mode + dwShareMode, // share mode + NULL, // SD + dwCreationDisposition, // how to create + dwFlagsAndAttributes, // file attributes + hTemplateFile // handle to template file + ); + + if (m_hFile == INVALID_HANDLE_VALUE) { + string errMsg = getLastErrorMessage(); + throw TException(wstring(L"Unable to open cache file: ") + + fname.getWideString() + L"\n" + toWideString(errMsg)); + } + + DWORD flProtect = PAGE_READWRITE; + DWORD dwMaximumSizeHigh = DWORDLONG_HI_DWORD(fileSize); + DWORD dwMaximumSizeLow = DWORDLONG_LO_DWORD(fileSize); + LPCTSTR lpName = NULL; // l'oggetto non ha nome + + m_hMap = CreateFileMapping(m_hFile, // handle to file + NULL, // security + flProtect, // protection + dwMaximumSizeHigh, // high-order DWORD of size + dwMaximumSizeLow, // low-order DWORD of size + lpName // object name + ); + + if (m_hMap == NULL) { + string errMsg = getLastErrorMessage(); + CloseHandle(m_hFile); + m_hFile = 0; + throw TException("Unable to create file mapping. " + errMsg); + } } //------------------------------------------------------------------------------ -void ImpPDW::setCurrentView(int frame, int &newLowFrame, int &newHiFrame) -{ - if (m_fileMapAddress) - UnmapViewOfFile(m_fileMapAddress); - - newLowFrame = frame; +void ImpPDW::setCurrentView(int frame, int &newLowFrame, int &newHiFrame) { + if (m_fileMapAddress) UnmapViewOfFile(m_fileMapAddress); - newHiFrame = newLowFrame + TINT32(m_viewSize / m_chunkSize); + newLowFrame = frame; - DWORD allocGranularity = m_systemInfo.dwAllocationGranularity; - TINT64 viewOffset = (TINT64(newLowFrame * m_chunkSize) / allocGranularity) * allocGranularity; - m_mapOffset = newLowFrame * m_chunkSize - viewOffset; + newHiFrame = newLowFrame + TINT32(m_viewSize / m_chunkSize); - TINT64 fileSize = newHiFrame * m_chunkSize; + DWORD allocGranularity = m_systemInfo.dwAllocationGranularity; + TINT64 viewOffset = + (TINT64(newLowFrame * m_chunkSize) / allocGranularity) * allocGranularity; + m_mapOffset = newLowFrame * m_chunkSize - viewOffset; - if ((fileSize > m_currentFileSize) || !m_hMap) // devo riallocare! - { - CloseHandle(m_hMap); - m_hMap = 0; - CloseHandle(m_hFile); - m_hFile = 0; + TINT64 fileSize = newHiFrame * m_chunkSize; - TINT64 allocUnitCount = fileSize / m_reallocSize; - // rendo fileSize multiplo di m_reallocSize - if ((fileSize % m_reallocSize) != 0) - ++allocUnitCount; + if ((fileSize > m_currentFileSize) || !m_hMap) // devo riallocare! + { + CloseHandle(m_hMap); + m_hMap = 0; + CloseHandle(m_hFile); + m_hFile = 0; - fileSize = allocUnitCount * m_reallocSize; + TINT64 allocUnitCount = fileSize / m_reallocSize; + // rendo fileSize multiplo di m_reallocSize + if ((fileSize % m_reallocSize) != 0) ++allocUnitCount; - openFile(m_fname, fileSize); - m_currentFileSize = fileSize; - } + fileSize = allocUnitCount * m_reallocSize; - DWORD dwDesiredAccess = FILE_MAP_WRITE; - m_fileMapAddress = MapViewOfFile(m_hMap, // handle to file-mapping object - dwDesiredAccess, // access mode: Write permission - DWORDLONG_HI_DWORD(viewOffset), // high-order DWORD of offset: Max. object size. - DWORDLONG_LO_DWORD(viewOffset), // low-order DWORD of offset: Size of hFile. - m_viewSize); // number of bytes to map + openFile(m_fname, fileSize); + m_currentFileSize = fileSize; + } - if (m_fileMapAddress == NULL) { - string errMsg = getLastErrorMessage(); - CloseHandle(m_hMap); - m_hMap = 0; - CloseHandle(m_hFile); - m_hFile = 0; + DWORD dwDesiredAccess = FILE_MAP_WRITE; + m_fileMapAddress = MapViewOfFile( + m_hMap, // handle to file-mapping object + dwDesiredAccess, // access mode: Write permission + DWORDLONG_HI_DWORD( + viewOffset), // high-order DWORD of offset: Max. object size. + DWORDLONG_LO_DWORD( + viewOffset), // low-order DWORD of offset: Size of hFile. + m_viewSize); // number of bytes to map - throw TException("Unable to memory map cache file. " + errMsg); - } + if (m_fileMapAddress == NULL) { + string errMsg = getLastErrorMessage(); + CloseHandle(m_hMap); + m_hMap = 0; + CloseHandle(m_hFile); + m_hFile = 0; + + throw TException("Unable to memory map cache file. " + errMsg); + } } #else -ImpPDX::ImpPDX(const TFilePath &fp) - : ImpPD(fp), m_fd(-1) -{ - //std::cout << "cache file " << toString(m_fname.getFullPath()) << std::endl; - m_pageSize = getpagesize(); - openFile(m_fname, 0); - assert(m_fd >= 0); +ImpPDX::ImpPDX(const TFilePath &fp) : ImpPD(fp), m_fd(-1) { + // std::cout << "cache file " << toString(m_fname.getFullPath()) << std::endl; + m_pageSize = getpagesize(); + openFile(m_fname, 0); + assert(m_fd >= 0); } //------------------------------------------------------------------------------ -ImpPDX::~ImpPDX() -{ - if (m_fileMapAddress) - munmap(m_fileMapAddress, m_viewSize); - close(m_fd); - m_fd = 0; +ImpPDX::~ImpPDX() { + if (m_fileMapAddress) munmap(m_fileMapAddress, m_viewSize); + close(m_fd); + m_fd = 0; } //------------------------------------------------------------------------------ -void ImpPDX::openFile(const TFilePath &fname, TINT64 fileSize) -{ - assert(0); - /* +void ImpPDX::openFile(const TFilePath &fname, TINT64 fileSize) { + assert(0); + /* string fn(toString(fname.getWideString())); std::cout << "open " << fn << std::endl; m_fd = open(fn.c_str(), O_RDWR|O_CREAT, 00666); @@ -467,42 +439,44 @@ assert(m_fd >=0); */ } -void ImpPDX::setCurrentView(int pos, int &newLowPos, int &newHiPos) -{ - newLowPos = pos; - newHiPos = newLowPos + (m_viewSize / m_chunkSize); - - assert(m_fd >= 0); - if (m_fileMapAddress) //previous view... - if (munmap(m_fileMapAddress, m_viewSize) != 0) - throw TCachedLevelException(errno); - void *start = 0; - int flags = MAP_SHARED; - size_t viewOffset = ((newLowPos * m_chunkSize) / m_pageSize) * m_pageSize; - m_mapOffset = newLowPos * m_chunkSize - viewOffset; - - assert(!"controllare le dimensioni"); - unsigned long lastByte = (unsigned long)(((newHiPos * m_chunkSize) / (double)m_pageSize + 0.5) * m_pageSize); - - if (lastByte > m_currentFileSize) // devo riallocare! - { - unsigned long bu = (unsigned long)((lastByte / (double)m_reallocSize + 0.5) * m_reallocSize); - bu = (unsigned long)((bu / (double)m_pageSize + 0.5) * m_pageSize); - //m_maxFileSize = tmax(m_maxFileSize + m_reallocFileSize, lastByte); - m_currentFileSize += bu; - - std::cout << "new cache size " << m_currentFileSize << std::endl; - if (lseek(m_fd, m_currentFileSize, SEEK_SET) == -1) - throw TCachedLevelException(errno); - if (write(m_fd, "", 1) == -1) - throw TCachedLevelException(errno); - if (ftruncate(m_fd, m_currentFileSize) == -1) - throw TCachedLevelException(errno); - } - - m_fileMapAddress = mmap(start, m_viewSize, PROT_READ | PROT_WRITE, flags, m_fd, viewOffset); - if (m_fileMapAddress == (void *)-1) - throw TCachedLevelException(errno); +void ImpPDX::setCurrentView(int pos, int &newLowPos, int &newHiPos) { + newLowPos = pos; + newHiPos = newLowPos + (m_viewSize / m_chunkSize); + + assert(m_fd >= 0); + if (m_fileMapAddress) // previous view... + if (munmap(m_fileMapAddress, m_viewSize) != 0) + throw TCachedLevelException(errno); + void *start = 0; + int flags = MAP_SHARED; + size_t viewOffset = ((newLowPos * m_chunkSize) / m_pageSize) * m_pageSize; + m_mapOffset = newLowPos * m_chunkSize - viewOffset; + + assert(!"controllare le dimensioni"); + unsigned long lastByte = + (unsigned long)(((newHiPos * m_chunkSize) / (double)m_pageSize + 0.5) * + m_pageSize); + + if (lastByte > m_currentFileSize) // devo riallocare! + { + unsigned long bu = + (unsigned long)((lastByte / (double)m_reallocSize + 0.5) * + m_reallocSize); + bu = (unsigned long)((bu / (double)m_pageSize + 0.5) * m_pageSize); + // m_maxFileSize = tmax(m_maxFileSize + m_reallocFileSize, lastByte); + m_currentFileSize += bu; + + std::cout << "new cache size " << m_currentFileSize << std::endl; + if (lseek(m_fd, m_currentFileSize, SEEK_SET) == -1) + throw TCachedLevelException(errno); + if (write(m_fd, "", 1) == -1) throw TCachedLevelException(errno); + if (ftruncate(m_fd, m_currentFileSize) == -1) + throw TCachedLevelException(errno); + } + + m_fileMapAddress = + mmap(start, m_viewSize, PROT_READ | PROT_WRITE, flags, m_fd, viewOffset); + if (m_fileMapAddress == (void *)-1) throw TCachedLevelException(errno); } #endif @@ -511,33 +485,31 @@ void ImpPDX::setCurrentView(int pos, int &newLowPos, int &newHiPos) #ifndef WIN32 #define ULONGLONG unsigned long long #endif -bool TDiskCachePersist::Imp::put(int frame, UCHAR *data, TUINT32 dataSize) -{ - if (dataSize != m_impPD->m_chunkSize) - return false; +bool TDiskCachePersist::Imp::put(int frame, UCHAR *data, TUINT32 dataSize) { + if (dataSize != m_impPD->m_chunkSize) return false; - TThread::ScopedLock sl(m_mutex); + TThread::ScopedLock sl(m_mutex); - setCurrentView(frame); - ULONGLONG offset = (frame - m_lowFrame) * m_impPD->m_chunkSize; - UCHAR *dst = (UCHAR *)m_impPD->m_fileMapAddress + offset; - memcpy(dst + m_impPD->m_mapOffset, data, dataSize); - return true; + setCurrentView(frame); + ULONGLONG offset = (frame - m_lowFrame) * m_impPD->m_chunkSize; + UCHAR *dst = (UCHAR *)m_impPD->m_fileMapAddress + offset; + memcpy(dst + m_impPD->m_mapOffset, data, dataSize); + return true; } //------------------------------------------------------------------------------ -UCHAR *TDiskCachePersist::Imp::get(int pos, TUINT32 *size) -{ - UCHAR *ret = new UCHAR[TINT32(m_impPD->m_chunkSize)]; - - TThread::ScopedLock sl(m_mutex); - setCurrentView(pos); - ULONGLONG offset = (pos - m_lowFrame) * m_impPD->m_chunkSize; - UCHAR *src = (UCHAR *)m_impPD->m_fileMapAddress + offset + m_impPD->m_mapOffset; - memcpy(ret, src, TINT32(m_impPD->m_chunkSize)); - *size = TUINT32(m_impPD->m_chunkSize); - return ret; +UCHAR *TDiskCachePersist::Imp::get(int pos, TUINT32 *size) { + UCHAR *ret = new UCHAR[TINT32(m_impPD->m_chunkSize)]; + + TThread::ScopedLock sl(m_mutex); + setCurrentView(pos); + ULONGLONG offset = (pos - m_lowFrame) * m_impPD->m_chunkSize; + UCHAR *src = + (UCHAR *)m_impPD->m_fileMapAddress + offset + m_impPD->m_mapOffset; + memcpy(ret, src, TINT32(m_impPD->m_chunkSize)); + *size = TUINT32(m_impPD->m_chunkSize); + return ret; } //------------------------------------------------------------------------------ @@ -545,431 +517,385 @@ UCHAR *TDiskCachePersist::Imp::get(int pos, TUINT32 *size) // TRasterCache //------------------------------------------------------------------------------ -class TRasterCache::Data -{ +class TRasterCache::Data { public: - Data(TCachePersist *cp) - : m_cp(cp), m_size(0, 0), m_prefetchEnabled(false), m_prefetchedFrame(-1), m_frameToPrefetch(-1), m_preLoader(1, true) - { - } - ~Data() {} - - class FrameData - { - public: - bool m_valid; - // int m_size; // dimensione in byte del raster codificato - ~FrameData() {} - }; - - bool isFrameCached(int frame) const; - - TDimension m_size; // dimensioni dei raster in cache - int m_bpp; - - typedef map Status; - Status m_status; - TCachePersist *m_cp; - TThread::Mutex m_accessMutex; - - TThread::Executor m_preLoader; - bool m_prefetchEnabled; - int m_prefetchedFrame; - int m_frameToPrefetch; - TRasterP m_prefetchedRas; + Data(TCachePersist *cp) + : m_cp(cp) + , m_size(0, 0) + , m_prefetchEnabled(false) + , m_prefetchedFrame(-1) + , m_frameToPrefetch(-1) + , m_preLoader(1, true) {} + ~Data() {} + + class FrameData { + public: + bool m_valid; + // int m_size; // dimensione in byte del raster codificato + ~FrameData() {} + }; + + bool isFrameCached(int frame) const; + + TDimension m_size; // dimensioni dei raster in cache + int m_bpp; + + typedef map Status; + Status m_status; + TCachePersist *m_cp; + TThread::Mutex m_accessMutex; + + TThread::Executor m_preLoader; + bool m_prefetchEnabled; + int m_prefetchedFrame; + int m_frameToPrefetch; + TRasterP m_prefetchedRas; }; -bool TRasterCache::Data::isFrameCached(int frame) const -{ - // volutamente senza ScopedLock - Data::Status::const_iterator it = m_status.find(frame); - if (it == m_status.end()) - return false; - Data::FrameData fd = it->second; - return fd.m_valid; +bool TRasterCache::Data::isFrameCached(int frame) const { + // volutamente senza ScopedLock + Data::Status::const_iterator it = m_status.find(frame); + if (it == m_status.end()) return false; + Data::FrameData fd = it->second; + return fd.m_valid; } //============================================================================== -namespace -{ +namespace { -class Load : public TThread::Runnable -{ +class Load : public TThread::Runnable { public: - Load(int frameToPrefetch, TCachePersist *cp, int &prefetchedFrame, TRasterP &prefetchedRas) - : m_frame(frameToPrefetch), m_cp(cp), m_prefetchedFrame(prefetchedFrame), m_prefetchedRas(prefetchedRas) {} + Load(int frameToPrefetch, TCachePersist *cp, int &prefetchedFrame, + TRasterP &prefetchedRas) + : m_frame(frameToPrefetch) + , m_cp(cp) + , m_prefetchedFrame(prefetchedFrame) + , m_prefetchedRas(prefetchedRas) {} - void run(); + void run(); private: - int m_frame; - TCachePersist *m_cp; - int &m_prefetchedFrame; - TRasterP &m_prefetchedRas; + int m_frame; + TCachePersist *m_cp; + int &m_prefetchedFrame; + TRasterP &m_prefetchedRas; }; -void Load::run() -{ - m_prefetchedRas = m_cp->doGetRaster(m_frame); - m_prefetchedFrame = m_frame; +void Load::run() { + m_prefetchedRas = m_cp->doGetRaster(m_frame); + m_prefetchedFrame = m_frame; } }; //============================================================================== -TRasterCache::TRasterCache(TCachePersist *cp) - : m_data(new Data(cp)) -{ -} +TRasterCache::TRasterCache(TCachePersist *cp) : m_data(new Data(cp)) {} //------------------------------------------------------------------------------ -TRasterCache::~TRasterCache() -{ - delete m_data; -} +TRasterCache::~TRasterCache() { delete m_data; } //------------------------------------------------------------------------------ -void TRasterCache::setMode(const TDimension &size, int bpp) -{ - TThread::ScopedLock sl(m_data->m_accessMutex); +void TRasterCache::setMode(const TDimension &size, int bpp) { + TThread::ScopedLock sl(m_data->m_accessMutex); - m_data->m_size = size; // dimensioni dei raster in cache - m_data->m_bpp = bpp; + m_data->m_size = size; // dimensioni dei raster in cache + m_data->m_bpp = bpp; - m_data->m_cp->setFrameSize(size.lx, size.ly, bpp); - invalidate(); + m_data->m_cp->setFrameSize(size.lx, size.ly, bpp); + invalidate(); } //------------------------------------------------------------------------------ -void TRasterCache::getMode(TDimension &size, int &bpp) const -{ - size = m_data->m_size; // dimensioni dei raster in cache - bpp = m_data->m_bpp; +void TRasterCache::getMode(TDimension &size, int &bpp) const { + size = m_data->m_size; // dimensioni dei raster in cache + bpp = m_data->m_bpp; } //------------------------------------------------------------------------------ -TRasterP TRasterCache::getRaster(int frame) const -{ - TThread::ScopedLock sl(m_data->m_accessMutex); +TRasterP TRasterCache::getRaster(int frame) const { + TThread::ScopedLock sl(m_data->m_accessMutex); - if (m_data->m_prefetchEnabled) { - /* - if (frame == m_data->m_frameToPrefetch) - m_data->m_preLoader.wait(); + if (m_data->m_prefetchEnabled) { + /* +if (frame == m_data->m_frameToPrefetch) +m_data->m_preLoader.wait(); +else +*/ + { + m_data->m_preLoader.clear(); + // m_data->m_preLoader.cancel(); + } + + TRasterP ras; + if (frame == m_data->m_prefetchedFrame) + ras = m_data->m_prefetchedRas; else - */ - { - m_data->m_preLoader.clear(); - //m_data->m_preLoader.cancel(); - } - - TRasterP ras; - if (frame == m_data->m_prefetchedFrame) - ras = m_data->m_prefetchedRas; - else - ras = m_data->m_cp->doGetRaster(frame); - - if (isFrameCached(frame + 1)) { - // il frame successivo a quello richiesto e' nella cache - // -> avvia il prefetch di tale raster - m_data->m_frameToPrefetch = frame + 1; - m_data->m_preLoader.addTask( - new Load(m_data->m_frameToPrefetch, m_data->m_cp, - m_data->m_prefetchedFrame, m_data->m_prefetchedRas)); - } - - return ras; - } else { - return m_data->m_cp->doGetRaster(frame); - } + ras = m_data->m_cp->doGetRaster(frame); + + if (isFrameCached(frame + 1)) { + // il frame successivo a quello richiesto e' nella cache + // -> avvia il prefetch di tale raster + m_data->m_frameToPrefetch = frame + 1; + m_data->m_preLoader.addTask( + new Load(m_data->m_frameToPrefetch, m_data->m_cp, + m_data->m_prefetchedFrame, m_data->m_prefetchedRas)); + } + + return ras; + } else { + return m_data->m_cp->doGetRaster(frame); + } } //------------------------------------------------------------------------------ -bool TRasterCache::getRaster(int frame, TRaster32P &ras) const -{ - TThread::ScopedLock sl(m_data->m_accessMutex); - if (m_data->isFrameCached(frame)) { - bool rc = m_data->m_cp->doGetRaster(frame, ras); - assert(rc); - return true; - } else - return false; +bool TRasterCache::getRaster(int frame, TRaster32P &ras) const { + TThread::ScopedLock sl(m_data->m_accessMutex); + if (m_data->isFrameCached(frame)) { + bool rc = m_data->m_cp->doGetRaster(frame, ras); + assert(rc); + return true; + } else + return false; } //------------------------------------------------------------------------------ -void TRasterCache::putRaster(int frame, const TRasterP &ras) -{ - TThread::ScopedLock sl(m_data->m_accessMutex); - Data::Status::iterator it = m_data->m_status.find(frame); - bool cached = false; - try { - cached = m_data->m_cp->doPutRaster(frame, ras); - } catch (TException &e) { - if (it != m_data->m_status.end()) { - Data::FrameData fd; - fd.m_valid = false; - m_data->m_status[frame] = fd; - } - throw e; - } - if (cached) { - Data::FrameData fd; - fd.m_valid = true; - m_data->m_status[frame] = fd; - } +void TRasterCache::putRaster(int frame, const TRasterP &ras) { + TThread::ScopedLock sl(m_data->m_accessMutex); + Data::Status::iterator it = m_data->m_status.find(frame); + bool cached = false; + try { + cached = m_data->m_cp->doPutRaster(frame, ras); + } catch (TException &e) { + if (it != m_data->m_status.end()) { + Data::FrameData fd; + fd.m_valid = false; + m_data->m_status[frame] = fd; + } + throw e; + } + if (cached) { + Data::FrameData fd; + fd.m_valid = true; + m_data->m_status[frame] = fd; + } } //------------------------------------------------------------------------------ -UCHAR *TRasterCache::getRawData(int frame, TINT32 &size, int &lx, int &ly) const -{ - return m_data->m_cp->getRawData(frame, size, lx, ly); +UCHAR *TRasterCache::getRawData(int frame, TINT32 &size, int &lx, + int &ly) const { + return m_data->m_cp->getRawData(frame, size, lx, ly); } //------------------------------------------------------------------------------ -bool TRasterCache::isFrameCached(int frame) const -{ - TThread::ScopedLock sl(m_data->m_accessMutex); - return m_data->isFrameCached(frame); +bool TRasterCache::isFrameCached(int frame) const { + TThread::ScopedLock sl(m_data->m_accessMutex); + return m_data->isFrameCached(frame); } //------------------------------------------------------------------------------ -void TRasterCache::invalidate() -{ - TThread::ScopedLock sl(m_data->m_accessMutex); - m_data->m_status.clear(); - m_data->m_cp->onInvalidate(); +void TRasterCache::invalidate() { + TThread::ScopedLock sl(m_data->m_accessMutex); + m_data->m_status.clear(); + m_data->m_cp->onInvalidate(); } //------------------------------------------------------------------------------ -void TRasterCache::invalidate(int startFrame, int endFrame) -{ - assert(startFrame <= endFrame); - TThread::ScopedLock sl(m_data->m_accessMutex); +void TRasterCache::invalidate(int startFrame, int endFrame) { + assert(startFrame <= endFrame); + TThread::ScopedLock sl(m_data->m_accessMutex); - Data::Status::iterator low = m_data->m_status.lower_bound(startFrame); - Data::Status::iterator hi = m_data->m_status.upper_bound(endFrame); + Data::Status::iterator low = m_data->m_status.lower_bound(startFrame); + Data::Status::iterator hi = m_data->m_status.upper_bound(endFrame); #ifdef _DEBUG - int count = m_data->m_status.size(); + int count = m_data->m_status.size(); - if (low != m_data->m_status.end() && hi != m_data->m_status.end()) { - int ll = low->first; - int hh = hi->first; - assert(ll <= hh); - } + if (low != m_data->m_status.end() && hi != m_data->m_status.end()) { + int ll = low->first; + int hh = hi->first; + assert(ll <= hh); + } #endif - if (low != m_data->m_status.end()) { - m_data->m_status.erase(low, hi); - m_data->m_cp->onInvalidate(startFrame, endFrame); - } + if (low != m_data->m_status.end()) { + m_data->m_status.erase(low, hi); + m_data->m_cp->onInvalidate(startFrame, endFrame); + } } //------------------------------------------------------------------------------ -void TRasterCache::enablePrefetch(bool newState) -{ - m_data->m_prefetchEnabled = newState; +void TRasterCache::enablePrefetch(bool newState) { + m_data->m_prefetchEnabled = newState; } //------------------------------------------------------------------------------ -bool TRasterCache::isPrefetchEnabled() const -{ - return m_data->m_prefetchEnabled; +bool TRasterCache::isPrefetchEnabled() const { + return m_data->m_prefetchEnabled; } //------------------------------------------------------------------------------ -TUINT64 TRasterCache::getUsedSpace() -{ - return m_data->m_cp->getUsedSpace(); -} +TUINT64 TRasterCache::getUsedSpace() { return m_data->m_cp->getUsedSpace(); } //============================================================================== //============================================================================== //============================================================================== // TRamCachePersist //------------------------------------------------------------------------------ -class TRamCachePersist::Imp -{ - friend class TRamCachePersist; +class TRamCachePersist::Imp { + friend class TRamCachePersist; public: - Imp() - : m_cacheSize(0), m_chunks() - { - } - ~Imp() - { - for (CompressedChunks::iterator it = m_chunks.begin(); it != m_chunks.end(); ++it) { - CompressedChunk *cc = it->second; - m_cacheSize -= cc->m_size; - delete cc; - } - assert(m_cacheSize == 0); // se m_cacheSize > 0 mi sono perso qualche chunk - // se m_cacheSize < 0 ho liberato 2 volte qualche chunk - m_chunks.clear(); - } - - class CompressedChunk - { - public: - CompressedChunk(UCHAR *buffer, int size) : m_buffer(buffer), m_size(size) {} - ~CompressedChunk() - { - delete[] m_buffer; - } - UCHAR *m_buffer; - int m_size; - }; - - typedef map CompressedChunks; - CompressedChunks m_chunks; - TUINT64 m_cacheSize; + Imp() : m_cacheSize(0), m_chunks() {} + ~Imp() { + for (CompressedChunks::iterator it = m_chunks.begin(); it != m_chunks.end(); + ++it) { + CompressedChunk *cc = it->second; + m_cacheSize -= cc->m_size; + delete cc; + } + assert(m_cacheSize == 0); // se m_cacheSize > 0 mi sono perso qualche chunk + // se m_cacheSize < 0 ho liberato 2 volte qualche chunk + m_chunks.clear(); + } + + class CompressedChunk { + public: + CompressedChunk(UCHAR *buffer, int size) : m_buffer(buffer), m_size(size) {} + ~CompressedChunk() { delete[] m_buffer; } + UCHAR *m_buffer; + int m_size; + }; + + typedef map CompressedChunks; + CompressedChunks m_chunks; + TUINT64 m_cacheSize; }; TRamCachePersist::TRamCachePersist(TRasterCodec *codec) - : TCachePersist(codec), m_imp(new Imp) -{ -} + : TCachePersist(codec), m_imp(new Imp) {} //------------------------------------------------------------------------------ -TRamCachePersist::~TRamCachePersist() -{ - delete m_imp; -} +TRamCachePersist::~TRamCachePersist() { delete m_imp; } //------------------------------------------------------------------------------ TRasterP TRamCachePersist::doGetRaster(int frame) -//void TRamCachePersist::doGetRaster(int frame, const TRasterP &ras) +// void TRamCachePersist::doGetRaster(int frame, const TRasterP &ras) { - Imp::CompressedChunks::const_iterator it = m_imp->m_chunks.find(frame); - if (it == m_imp->m_chunks.end()) - return TRasterP(); - Imp::CompressedChunk *cc = it->second; - assert(cc); - TRasterP rasP; - m_codec->decompress(cc->m_buffer, cc->m_size, rasP); - return rasP; + Imp::CompressedChunks::const_iterator it = m_imp->m_chunks.find(frame); + if (it == m_imp->m_chunks.end()) return TRasterP(); + Imp::CompressedChunk *cc = it->second; + assert(cc); + TRasterP rasP; + m_codec->decompress(cc->m_buffer, cc->m_size, rasP); + return rasP; } //------------------------------------------------------------------------------ -bool TRamCachePersist::doGetRaster(int frame, TRaster32P &ras) const -{ - Imp::CompressedChunks::const_iterator it = m_imp->m_chunks.find(frame); - if (it == m_imp->m_chunks.end()) - return false; - Imp::CompressedChunk *cc = it->second; - assert(cc); - TRasterP rasP(ras); - m_codec->decompress(cc->m_buffer, cc->m_size, rasP); - return true; +bool TRamCachePersist::doGetRaster(int frame, TRaster32P &ras) const { + Imp::CompressedChunks::const_iterator it = m_imp->m_chunks.find(frame); + if (it == m_imp->m_chunks.end()) return false; + Imp::CompressedChunk *cc = it->second; + assert(cc); + TRasterP rasP(ras); + m_codec->decompress(cc->m_buffer, cc->m_size, rasP); + return true; } //------------------------------------------------------------------------------ -bool TRamCachePersist::doPutRaster(int frame, const TRasterP &ras) -{ - Imp::CompressedChunks::iterator it = m_imp->m_chunks.find(frame); - if (it != m_imp->m_chunks.end()) { - m_imp->m_cacheSize -= it->second->m_size; - delete it->second; - m_imp->m_chunks.erase(it); - } - - UCHAR *outData = 0; - TINT32 outDataSize = 0; - m_codec->compress(ras, 1, &outData, outDataSize); - m_imp->m_cacheSize += outDataSize; - Imp::CompressedChunk *cc = new Imp::CompressedChunk(outData, outDataSize); - m_imp->m_chunks.insert(Imp::CompressedChunks::value_type(frame, cc)); - return true; +bool TRamCachePersist::doPutRaster(int frame, const TRasterP &ras) { + Imp::CompressedChunks::iterator it = m_imp->m_chunks.find(frame); + if (it != m_imp->m_chunks.end()) { + m_imp->m_cacheSize -= it->second->m_size; + delete it->second; + m_imp->m_chunks.erase(it); + } + + UCHAR *outData = 0; + TINT32 outDataSize = 0; + m_codec->compress(ras, 1, &outData, outDataSize); + m_imp->m_cacheSize += outDataSize; + Imp::CompressedChunk *cc = new Imp::CompressedChunk(outData, outDataSize); + m_imp->m_chunks.insert(Imp::CompressedChunks::value_type(frame, cc)); + return true; } //------------------------------------------------------------------------------ -void TRamCachePersist::onInvalidate() -{ - for (Imp::CompressedChunks::iterator it = m_imp->m_chunks.begin(); - it != m_imp->m_chunks.end(); - ++it) { - Imp::CompressedChunk *cc = it->second; - m_imp->m_cacheSize -= cc->m_size; - delete cc; - } - - m_imp->m_chunks.clear(); +void TRamCachePersist::onInvalidate() { + for (Imp::CompressedChunks::iterator it = m_imp->m_chunks.begin(); + it != m_imp->m_chunks.end(); ++it) { + Imp::CompressedChunk *cc = it->second; + m_imp->m_cacheSize -= cc->m_size; + delete cc; + } + + m_imp->m_chunks.clear(); } //------------------------------------------------------------------------------ -void TRamCachePersist::onInvalidate(int startFrame, int endFrame) -{ // ottimizzabile - assert(startFrame <= endFrame); +void TRamCachePersist::onInvalidate(int startFrame, + int endFrame) { // ottimizzabile + assert(startFrame <= endFrame); - for (int frame = startFrame; frame <= endFrame; ++frame) { - Imp::CompressedChunks::iterator it = m_imp->m_chunks.find(frame); - if (it != m_imp->m_chunks.end()) { - m_imp->m_cacheSize -= it->second->m_size; - delete it->second; - m_imp->m_chunks.erase(it); - } - } + for (int frame = startFrame; frame <= endFrame; ++frame) { + Imp::CompressedChunks::iterator it = m_imp->m_chunks.find(frame); + if (it != m_imp->m_chunks.end()) { + m_imp->m_cacheSize -= it->second->m_size; + delete it->second; + m_imp->m_chunks.erase(it); + } + } } //------------------------------------------------------------------------------ -UCHAR *TRamCachePersist::getRawData(int frame, TINT32 &size, int &lx, int &ly) -{ - Imp::CompressedChunks::const_iterator it = m_imp->m_chunks.find(frame); - if (it == m_imp->m_chunks.end()) - return 0; - Imp::CompressedChunk *cc = it->second; - assert(cc); - return m_codec->removeHeader(cc->m_buffer, cc->m_size, size, lx, ly); +UCHAR *TRamCachePersist::getRawData(int frame, TINT32 &size, int &lx, int &ly) { + Imp::CompressedChunks::const_iterator it = m_imp->m_chunks.find(frame); + if (it == m_imp->m_chunks.end()) return 0; + Imp::CompressedChunk *cc = it->second; + assert(cc); + return m_codec->removeHeader(cc->m_buffer, cc->m_size, size, lx, ly); } //------------------------------------------------------------------------------ -TUINT64 TRamCachePersist::getUsedSpace() -{ - return m_imp->m_cacheSize; -} +TUINT64 TRamCachePersist::getUsedSpace() { return m_imp->m_cacheSize; } //------------------------------------------------------------------------------ -void TDiskCachePersist::onInvalidate() -{ - //m_imp->m_chunkSize = 0; +void TDiskCachePersist::onInvalidate() { + // m_imp->m_chunkSize = 0; } //------------------------------------------------------------------------------ -void TDiskCachePersist::onInvalidate(int startFrame, int endFrame) -{ - //m_imp->m_chunkSize = 0; +void TDiskCachePersist::onInvalidate(int startFrame, int endFrame) { + // m_imp->m_chunkSize = 0; } //------------------------------------------------------------------------------ -TUINT64 TDiskCachePersist::getUsedSpace() -{ - assert(0); - return 0; +TUINT64 TDiskCachePersist::getUsedSpace() { + assert(0); + return 0; } //============================================================================== @@ -980,694 +906,650 @@ TUINT64 TDiskCachePersist::getUsedSpace() // //------------------------------------------------------------------------------ #ifdef WIN32 -namespace -{ +namespace { -class ZFile -{ +class ZFile { public: - ZFile(const TFilePath &fp, bool directIO, bool asyncIO); - ~ZFile(); + ZFile(const TFilePath &fp, bool directIO, bool asyncIO); + ~ZFile(); - void open(); + void open(); - int read(BYTE buf[], int size, TINT64 qwOffset) const; - int write(BYTE buf[], int size, TINT64 qwOffset) const; + int read(BYTE buf[], int size, TINT64 qwOffset) const; + int write(BYTE buf[], int size, TINT64 qwOffset) const; - void waitForAsyncIOCompletion() const; + void waitForAsyncIOCompletion() const; - TFilePath getFilePath() const - { - return m_filepath; - } + TFilePath getFilePath() const { return m_filepath; } - int getBytesPerSector() const - { - return m_bytesPerSector; - } + int getBytesPerSector() const { return m_bytesPerSector; } - static void CALLBACK FileIOCompletionRoutine( - DWORD errCode, - DWORD byteTransferred, - LPOVERLAPPED overlapped); + static void CALLBACK FileIOCompletionRoutine(DWORD errCode, + DWORD byteTransferred, + LPOVERLAPPED overlapped); private: - TFilePath m_filepath; - bool m_directIO; - bool m_asyncIO; - DWORD m_bytesPerSector; + TFilePath m_filepath; + bool m_directIO; + bool m_asyncIO; + DWORD m_bytesPerSector; - HANDLE m_fileHandle; - HANDLE m_writeNotPending; + HANDLE m_fileHandle; + HANDLE m_writeNotPending; }; //----------------------------------------------------------------------------- ZFile::ZFile(const TFilePath &fp, bool directIO, bool asyncIO) - : m_filepath(fp), m_directIO(directIO), m_asyncIO(asyncIO), m_fileHandle(0), m_writeNotPending(0) -{ - DWORD sectorsPerCluster; - DWORD numberOfFreeClusters; - DWORD totalNumberOfClusters; - - TFilePathSet disks = TSystem::getDisks(); - - TFilePath disk = fp; - while (std::find(disks.begin(), disks.end(), disk) == disks.end()) - disk = disk.getParentDir(); - - BOOL ret = GetDiskFreeSpaceW( - disk.getWideString().c_str(), // root path - §orsPerCluster, // sectors per cluster - &m_bytesPerSector, // bytes per sector - &numberOfFreeClusters, // free clusters - &totalNumberOfClusters // total clusters - ); - - if (m_asyncIO) - m_writeNotPending = CreateEvent(NULL, TRUE, TRUE, NULL); + : m_filepath(fp) + , m_directIO(directIO) + , m_asyncIO(asyncIO) + , m_fileHandle(0) + , m_writeNotPending(0) { + DWORD sectorsPerCluster; + DWORD numberOfFreeClusters; + DWORD totalNumberOfClusters; + + TFilePathSet disks = TSystem::getDisks(); + + TFilePath disk = fp; + while (std::find(disks.begin(), disks.end(), disk) == disks.end()) + disk = disk.getParentDir(); + + BOOL ret = GetDiskFreeSpaceW(disk.getWideString().c_str(), // root path + §orsPerCluster, // sectors per cluster + &m_bytesPerSector, // bytes per sector + &numberOfFreeClusters, // free clusters + &totalNumberOfClusters // total clusters + ); + + if (m_asyncIO) m_writeNotPending = CreateEvent(NULL, TRUE, TRUE, NULL); } //----------------------------------------------------------------------------- -ZFile::~ZFile() -{ - if (m_fileHandle) - CloseHandle(m_fileHandle); +ZFile::~ZFile() { + if (m_fileHandle) CloseHandle(m_fileHandle); - if (m_writeNotPending) - CloseHandle(m_writeNotPending); + if (m_writeNotPending) CloseHandle(m_writeNotPending); } //----------------------------------------------------------------------------- -void ZFile::open() -{ - DWORD flagsAndAttributes = 0; - flagsAndAttributes = m_directIO ? FILE_FLAG_NO_BUFFERING : 0UL; - flagsAndAttributes |= m_asyncIO ? FILE_FLAG_OVERLAPPED : 0UL; - - // Open the file for write access. - m_fileHandle = CreateFileW(m_filepath.getWideString().c_str(), - GENERIC_READ | GENERIC_WRITE, // Read/Write access - 0, // no sharing allowed - NULL, // no security - OPEN_ALWAYS, // open it or create new if it doesn't exist - flagsAndAttributes, - NULL); // ignored - - if (m_fileHandle == INVALID_HANDLE_VALUE) { - m_fileHandle = 0; - - char errorMessage[2048]; - - DWORD error = GetLastError(); - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0UL, error, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errorMessage, 2048, NULL); - - throw TException(errorMessage); - } +void ZFile::open() { + DWORD flagsAndAttributes = 0; + flagsAndAttributes = m_directIO ? FILE_FLAG_NO_BUFFERING : 0UL; + flagsAndAttributes |= m_asyncIO ? FILE_FLAG_OVERLAPPED : 0UL; + + // Open the file for write access. + m_fileHandle = + CreateFileW(m_filepath.getWideString().c_str(), + GENERIC_READ | GENERIC_WRITE, // Read/Write access + 0, // no sharing allowed + NULL, // no security + OPEN_ALWAYS, // open it or create new if it doesn't exist + flagsAndAttributes, + NULL); // ignored + + if (m_fileHandle == INVALID_HANDLE_VALUE) { + m_fileHandle = 0; + + char errorMessage[2048]; + + DWORD error = GetLastError(); + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0UL, error, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errorMessage, 2048, + NULL); + + throw TException(errorMessage); + } } //----------------------------------------------------------------------------- -int ZFile::read(BYTE buf[], int size, TINT64 qwOffset) const -{ - assert(size % m_bytesPerSector == 0); - assert(qwOffset % m_bytesPerSector == 0); +int ZFile::read(BYTE buf[], int size, TINT64 qwOffset) const { + assert(size % m_bytesPerSector == 0); + assert(qwOffset % m_bytesPerSector == 0); - char msg[2048] = ""; - unsigned long bytesToRead; // Padded number of bytes to read. - unsigned long bytesRead; // count of bytes actually read + char msg[2048] = ""; + unsigned long bytesToRead; // Padded number of bytes to read. + unsigned long bytesRead; // count of bytes actually read - OVERLAPPED overLapped; - memset(&overLapped, 0, sizeof(overLapped)); + OVERLAPPED overLapped; + memset(&overLapped, 0, sizeof(overLapped)); #define DWORDLONG_LO_DWORD(dwl64) ((DWORD)(dwl64)) #define DWORDLONG_HI_DWORD(dwl64) ((DWORD)(dwl64 >> 32)) - // set the overlapped stucture with the offsets - overLapped.Offset = DWORDLONG_LO_DWORD(qwOffset); - overLapped.OffsetHigh = DWORDLONG_HI_DWORD(qwOffset); - - if (m_asyncIO) { - overLapped.hEvent = CreateEvent( - NULL, // SD - TRUE, // manual reset - FALSE, // initial state is not signaled - NULL); // object name - } else - overLapped.hEvent = NULL; - - bytesToRead = size; - - // Read a bunch of bytes and store in buf - int result = ReadFile( - m_fileHandle, // file handle - (void *)buf, // buffer to store data - bytesToRead, // num bytes to read - &bytesRead, // bytes read - &overLapped); // stucture for file offsets - - if (!result) { - DWORD error = GetLastError(); - if (m_asyncIO && ERROR_IO_PENDING == error) { - if (!GetOverlappedResult(m_fileHandle, &overLapped, &bytesRead, TRUE)) { - char errorMessage[2048]; - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0UL, error, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errorMessage, 2048, NULL); - - throw TException(errorMessage); - } - } else { - char errorMessage[2048]; - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0UL, error, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errorMessage, 2048, NULL); - - throw TException(errorMessage); - } - } - - return bytesRead; + // set the overlapped stucture with the offsets + overLapped.Offset = DWORDLONG_LO_DWORD(qwOffset); + overLapped.OffsetHigh = DWORDLONG_HI_DWORD(qwOffset); + + if (m_asyncIO) { + overLapped.hEvent = CreateEvent(NULL, // SD + TRUE, // manual reset + FALSE, // initial state is not signaled + NULL); // object name + } else + overLapped.hEvent = NULL; + + bytesToRead = size; + + // Read a bunch of bytes and store in buf + int result = ReadFile(m_fileHandle, // file handle + (void *)buf, // buffer to store data + bytesToRead, // num bytes to read + &bytesRead, // bytes read + &overLapped); // stucture for file offsets + + if (!result) { + DWORD error = GetLastError(); + if (m_asyncIO && ERROR_IO_PENDING == error) { + if (!GetOverlappedResult(m_fileHandle, &overLapped, &bytesRead, TRUE)) { + char errorMessage[2048]; + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0UL, error, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errorMessage, + 2048, NULL); + + throw TException(errorMessage); + } + } else { + char errorMessage[2048]; + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0UL, error, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errorMessage, + 2048, NULL); + + throw TException(errorMessage); + } + } + + return bytesRead; } //----------------------------------------------------------------------------- -int ZFile::write(BYTE buf[], int size, TINT64 qwOffset) const -{ - assert(size % m_bytesPerSector == 0); - assert(qwOffset % m_bytesPerSector == 0); - - char msg[2048] = ""; - unsigned long bytesToWrite; // Padded number of bytes to write. - unsigned long bytesWritten = 0; // count of bytes actually writtten - - int result; - - if (m_asyncIO) { - OVERLAPPED *overLapped = new OVERLAPPED; - memset(overLapped, 0, sizeof(OVERLAPPED)); - - // set the overlapped stucture with the offsets - overLapped->Offset = DWORDLONG_LO_DWORD(qwOffset); - overLapped->OffsetHigh = DWORDLONG_HI_DWORD(qwOffset); - overLapped->hEvent = NULL; - - bytesToWrite = size; - - result = WriteFileEx( - m_fileHandle, // file handle - (void *)buf, // data buffer - bytesToWrite, // num bytes to write - overLapped, // stucture for file offsets - &ZFile::FileIOCompletionRoutine); - - ResetEvent(m_writeNotPending); - } else { - OVERLAPPED overLapped; - memset(&overLapped, 0, sizeof(overLapped)); - - // set the overlapped stucture with the offsets - overLapped.Offset = DWORDLONG_LO_DWORD(qwOffset); - overLapped.OffsetHigh = DWORDLONG_HI_DWORD(qwOffset); - overLapped.hEvent = NULL; - - bytesToWrite = size; - - result = WriteFile( - m_fileHandle, // file handle - (void *)buf, // data buffer - bytesToWrite, // num bytes to read - &bytesWritten, // bytes read - &overLapped); // stucture for file offsets - } - - if (!result) { - char errorMessage[2048]; - DWORD error = GetLastError(); - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0UL, error, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errorMessage, 2048, NULL); - - throw TException(errorMessage); - } - - return bytesWritten; +int ZFile::write(BYTE buf[], int size, TINT64 qwOffset) const { + assert(size % m_bytesPerSector == 0); + assert(qwOffset % m_bytesPerSector == 0); + + char msg[2048] = ""; + unsigned long bytesToWrite; // Padded number of bytes to write. + unsigned long bytesWritten = 0; // count of bytes actually writtten + + int result; + + if (m_asyncIO) { + OVERLAPPED *overLapped = new OVERLAPPED; + memset(overLapped, 0, sizeof(OVERLAPPED)); + + // set the overlapped stucture with the offsets + overLapped->Offset = DWORDLONG_LO_DWORD(qwOffset); + overLapped->OffsetHigh = DWORDLONG_HI_DWORD(qwOffset); + overLapped->hEvent = NULL; + + bytesToWrite = size; + + result = WriteFileEx(m_fileHandle, // file handle + (void *)buf, // data buffer + bytesToWrite, // num bytes to write + overLapped, // stucture for file offsets + &ZFile::FileIOCompletionRoutine); + + ResetEvent(m_writeNotPending); + } else { + OVERLAPPED overLapped; + memset(&overLapped, 0, sizeof(overLapped)); + + // set the overlapped stucture with the offsets + overLapped.Offset = DWORDLONG_LO_DWORD(qwOffset); + overLapped.OffsetHigh = DWORDLONG_HI_DWORD(qwOffset); + overLapped.hEvent = NULL; + + bytesToWrite = size; + + result = WriteFile(m_fileHandle, // file handle + (void *)buf, // data buffer + bytesToWrite, // num bytes to read + &bytesWritten, // bytes read + &overLapped); // stucture for file offsets + } + + if (!result) { + char errorMessage[2048]; + DWORD error = GetLastError(); + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0UL, error, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errorMessage, 2048, + NULL); + + throw TException(errorMessage); + } + + return bytesWritten; } //------------------------------------------------------------------------------ -void ZFile::waitForAsyncIOCompletion() const -{ - if (m_asyncIO) { - WaitForSingleObjectEx(m_writeNotPending, INFINITE, TRUE); - SetEvent(m_writeNotPending); - } +void ZFile::waitForAsyncIOCompletion() const { + if (m_asyncIO) { + WaitForSingleObjectEx(m_writeNotPending, INFINITE, TRUE); + SetEvent(m_writeNotPending); + } } //------------------------------------------------------------------------------ -void CALLBACK ZFile::FileIOCompletionRoutine( - DWORD errCode, - DWORD byteTransferred, - LPOVERLAPPED overlapped) -{ - delete overlapped; +void CALLBACK ZFile::FileIOCompletionRoutine(DWORD errCode, + DWORD byteTransferred, + LPOVERLAPPED overlapped) { + delete overlapped; } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ -class BufferQueue -{ +class BufferQueue { public: - class Item - { - public: - Item(int frame, UCHAR *buffer, int bufferSize, int chunkSize) - : m_frame(frame), m_buffer(buffer), m_bufferSize(bufferSize), m_chunkSize(chunkSize) - { - } - - int m_frame; - UCHAR *m_buffer; - int m_bufferSize; - TINT64 m_chunkSize; - }; - - BufferQueue(int capacity, int allocUnit) - : m_capacity(capacity), m_allocUnit(allocUnit), m_notEmpty(), m_notFull(), m_mutex(), m_bufferCount(0), m_nextPutItem(0), m_nextGetItem(0) - { - for (int i = 0; i < m_capacity; ++i) - m_items.push_back(Item(-1, (UCHAR *)0, 0, 0)); - } - - ~BufferQueue() - { - for (int i = 0; i < m_capacity; ++i) - delete[] m_items[i].m_buffer; - } - - void put(int frame, UCHAR *buffer, int bufferSize, int chunkSize) - { - TThread::ScopedLock sl(m_mutex); - while (m_bufferCount == m_capacity) - m_notFull.wait(sl); - - if (m_items[m_nextPutItem].m_chunkSize != chunkSize) { - delete[] m_items[m_nextPutItem].m_buffer; - m_items[m_nextPutItem].m_buffer = new UCHAR[chunkSize]; - m_items[m_nextPutItem].m_chunkSize = chunkSize; - } - - memcpy(m_items[m_nextPutItem].m_buffer, buffer, bufferSize); - m_items[m_nextPutItem].m_frame = frame; - - m_nextPutItem = (m_nextPutItem + 1) % m_capacity; - ++m_bufferCount; - m_notEmpty.notifyOne(); - } - - BufferQueue::Item get() - { - TThread::ScopedLock sl(m_mutex); - - while (m_bufferCount == 0) - m_notEmpty.wait(sl); - - m_notFull.notifyOne(); - - BufferQueue::Item item = m_items[m_nextGetItem]; - - m_nextGetItem = (m_nextGetItem + 1) % m_capacity; - --m_bufferCount; - return item; - } - - void saveOne(ZFile *file) - { - TThread::ScopedLock sl(m_mutex); - - while (m_bufferCount == 0) - m_notEmpty.wait(sl); - - m_notFull.notifyOne(); - - BufferQueue::Item item = m_items[m_nextGetItem]; - - m_nextGetItem = (m_nextGetItem + 1) % m_capacity; - --m_bufferCount; - - TINT64 pos = item.m_frame * item.m_chunkSize; - TINT64 sectorCount = pos / m_allocUnit; - - if ((pos % m_allocUnit) != 0) - ++sectorCount; - - pos = sectorCount * m_allocUnit; - file->write(item.m_buffer, (TINT32)item.m_chunkSize, pos); - } - - int size() - { - TThread::ScopedLock sl(m_mutex); - return m_bufferCount; - } + class Item { + public: + Item(int frame, UCHAR *buffer, int bufferSize, int chunkSize) + : m_frame(frame) + , m_buffer(buffer) + , m_bufferSize(bufferSize) + , m_chunkSize(chunkSize) {} + + int m_frame; + UCHAR *m_buffer; + int m_bufferSize; + TINT64 m_chunkSize; + }; + + BufferQueue(int capacity, int allocUnit) + : m_capacity(capacity) + , m_allocUnit(allocUnit) + , m_notEmpty() + , m_notFull() + , m_mutex() + , m_bufferCount(0) + , m_nextPutItem(0) + , m_nextGetItem(0) { + for (int i = 0; i < m_capacity; ++i) + m_items.push_back(Item(-1, (UCHAR *)0, 0, 0)); + } + + ~BufferQueue() { + for (int i = 0; i < m_capacity; ++i) delete[] m_items[i].m_buffer; + } + + void put(int frame, UCHAR *buffer, int bufferSize, int chunkSize) { + TThread::ScopedLock sl(m_mutex); + while (m_bufferCount == m_capacity) m_notFull.wait(sl); + + if (m_items[m_nextPutItem].m_chunkSize != chunkSize) { + delete[] m_items[m_nextPutItem].m_buffer; + m_items[m_nextPutItem].m_buffer = new UCHAR[chunkSize]; + m_items[m_nextPutItem].m_chunkSize = chunkSize; + } + + memcpy(m_items[m_nextPutItem].m_buffer, buffer, bufferSize); + m_items[m_nextPutItem].m_frame = frame; + + m_nextPutItem = (m_nextPutItem + 1) % m_capacity; + ++m_bufferCount; + m_notEmpty.notifyOne(); + } + + BufferQueue::Item get() { + TThread::ScopedLock sl(m_mutex); + + while (m_bufferCount == 0) m_notEmpty.wait(sl); + + m_notFull.notifyOne(); + + BufferQueue::Item item = m_items[m_nextGetItem]; + + m_nextGetItem = (m_nextGetItem + 1) % m_capacity; + --m_bufferCount; + return item; + } + + void saveOne(ZFile *file) { + TThread::ScopedLock sl(m_mutex); + + while (m_bufferCount == 0) m_notEmpty.wait(sl); + + m_notFull.notifyOne(); + + BufferQueue::Item item = m_items[m_nextGetItem]; + + m_nextGetItem = (m_nextGetItem + 1) % m_capacity; + --m_bufferCount; + + TINT64 pos = item.m_frame * item.m_chunkSize; + TINT64 sectorCount = pos / m_allocUnit; + + if ((pos % m_allocUnit) != 0) ++sectorCount; + + pos = sectorCount * m_allocUnit; + file->write(item.m_buffer, (TINT32)item.m_chunkSize, pos); + } + + int size() { + TThread::ScopedLock sl(m_mutex); + return m_bufferCount; + } private: - int m_capacity; - int m_allocUnit; + int m_capacity; + int m_allocUnit; - TThread::Condition m_notEmpty; - TThread::Condition m_notFull; - TThread::Mutex m_mutex; + TThread::Condition m_notEmpty; + TThread::Condition m_notFull; + TThread::Mutex m_mutex; - vector m_items; + vector m_items; - int m_bufferCount; - int m_nextPutItem; - int m_nextGetItem; + int m_bufferCount; + int m_nextPutItem; + int m_nextGetItem; }; //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ -class WriteBufferTask : public TThread::Runnable -{ +class WriteBufferTask : public TThread::Runnable { public: - WriteBufferTask(ZFile *file, BufferQueue *bufferQueue) - : m_file(file), m_bufferQueue(bufferQueue) - { - } + WriteBufferTask(ZFile *file, BufferQueue *bufferQueue) + : m_file(file), m_bufferQueue(bufferQueue) {} - void run(); + void run(); - ZFile *m_file; - BufferQueue *m_bufferQueue; + ZFile *m_file; + BufferQueue *m_bufferQueue; }; //------------------------------------------------------------------------------ -void WriteBufferTask::run() -{ - while (true) { - TThread::milestone(); - - try { - m_bufferQueue->saveOne(m_file); - m_file->waitForAsyncIOCompletion(); - } catch (TException & /*e*/) { - } catch (...) { - } - } +void WriteBufferTask::run() { + while (true) { + TThread::milestone(); + + try { + m_bufferQueue->saveOne(m_file); + m_file->waitForAsyncIOCompletion(); + } catch (TException & /*e*/) { + } catch (...) { + } + } } -} // anonymous namespace +} // anonymous namespace //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ -class TDiskCachePersist2::Imp -{ +class TDiskCachePersist2::Imp { public: - Imp(const TFilePath &fp, bool asyncWrite) - : m_chunkSize(0), m_readBuffer(0), m_file(new ZFile(fp, true, asyncWrite)), m_asyncWrite(asyncWrite), m_executor(0), m_bufferQueue(0) - { - m_file->open(); - m_allocUnit = m_file->getBytesPerSector(); - - if (m_asyncWrite) { - m_executor = new TThread::Executor(); - m_bufferQueue = new BufferQueue(4, m_allocUnit); - m_executor->addTask(new WriteBufferTask(m_file, m_bufferQueue)); - } - } - - ~Imp() - { - delete m_file; - delete[] m_readBuffer; - - if (m_executor) { - m_executor->cancel(); - delete m_executor; - } - - delete m_bufferQueue; - } - - bool put(int frame, UCHAR *data, TUINT32 dataSize); - UCHAR *get(int pos, TUINT32 *size); - - TThread::Mutex m_mutex; - TINT64 m_chunkSize; - - ZFile *m_file; - int m_allocUnit; - UCHAR *m_readBuffer; - int m_lx; - int m_ly; - int m_bpp; - - bool m_asyncWrite; - TThread::Executor *m_executor; - BufferQueue *m_bufferQueue; + Imp(const TFilePath &fp, bool asyncWrite) + : m_chunkSize(0) + , m_readBuffer(0) + , m_file(new ZFile(fp, true, asyncWrite)) + , m_asyncWrite(asyncWrite) + , m_executor(0) + , m_bufferQueue(0) { + m_file->open(); + m_allocUnit = m_file->getBytesPerSector(); + + if (m_asyncWrite) { + m_executor = new TThread::Executor(); + m_bufferQueue = new BufferQueue(4, m_allocUnit); + m_executor->addTask(new WriteBufferTask(m_file, m_bufferQueue)); + } + } + + ~Imp() { + delete m_file; + delete[] m_readBuffer; + + if (m_executor) { + m_executor->cancel(); + delete m_executor; + } + + delete m_bufferQueue; + } + + bool put(int frame, UCHAR *data, TUINT32 dataSize); + UCHAR *get(int pos, TUINT32 *size); + + TThread::Mutex m_mutex; + TINT64 m_chunkSize; + + ZFile *m_file; + int m_allocUnit; + UCHAR *m_readBuffer; + int m_lx; + int m_ly; + int m_bpp; + + bool m_asyncWrite; + TThread::Executor *m_executor; + BufferQueue *m_bufferQueue; }; //------------------------------------------------------------------------------ -bool TDiskCachePersist2::Imp::put(int frame, UCHAR *data, TUINT32 dataSize) -{ - if (dataSize != m_chunkSize) - return false; +bool TDiskCachePersist2::Imp::put(int frame, UCHAR *data, TUINT32 dataSize) { + if (dataSize != m_chunkSize) return false; - TINT64 pos = frame * m_chunkSize; - TINT64 sectorCount = pos / m_allocUnit; + TINT64 pos = frame * m_chunkSize; + TINT64 sectorCount = pos / m_allocUnit; - if ((pos % m_allocUnit) != 0) - ++sectorCount; + if ((pos % m_allocUnit) != 0) ++sectorCount; - pos = sectorCount * m_allocUnit; + pos = sectorCount * m_allocUnit; - m_file->write(data, dataSize, pos); - return true; + m_file->write(data, dataSize, pos); + return true; } //------------------------------------------------------------------------------ -UCHAR *TDiskCachePersist2::Imp::get(int frame, TUINT32 *size) -{ - UCHAR *ret = new UCHAR[TINT32(m_chunkSize)]; +UCHAR *TDiskCachePersist2::Imp::get(int frame, TUINT32 *size) { + UCHAR *ret = new UCHAR[TINT32(m_chunkSize)]; - TThread::ScopedLock sl(m_mutex); + TThread::ScopedLock sl(m_mutex); - TINT64 pos = frame * m_chunkSize; - TINT64 sectorCount = pos / m_allocUnit; + TINT64 pos = frame * m_chunkSize; + TINT64 sectorCount = pos / m_allocUnit; - if ((pos % m_allocUnit) != 0) - ++sectorCount; + if ((pos % m_allocUnit) != 0) ++sectorCount; - pos = sectorCount * m_allocUnit; + pos = sectorCount * m_allocUnit; - m_file->read(ret, TINT32(m_chunkSize), pos); - *size = TUINT32(m_chunkSize); - return ret; + m_file->read(ret, TINT32(m_chunkSize), pos); + *size = TUINT32(m_chunkSize); + return ret; } //------------------------------------------------------------------------------ -TDiskCachePersist2::TDiskCachePersist2(TRasterCodec *codec, const TFilePath &fullpath) - : TCachePersist(codec), m_imp(new Imp(fullpath, false /*true*/)) -{ -} +TDiskCachePersist2::TDiskCachePersist2(TRasterCodec *codec, + const TFilePath &fullpath) + : TCachePersist(codec), m_imp(new Imp(fullpath, false /*true*/)) {} //------------------------------------------------------------------------------ -TDiskCachePersist2::~TDiskCachePersist2() -{ - delete m_imp; -} +TDiskCachePersist2::~TDiskCachePersist2() { delete m_imp; } //------------------------------------------------------------------------------ -void TDiskCachePersist2::setFrameSize(int lx, int ly, int bpp) -{ - m_imp->m_lx = lx; - m_imp->m_ly = ly; - m_imp->m_bpp = bpp; - - // inizializza m_imp->m_chunkSize in modo che sia un multiplo di m_imp->m_allocUnit - if (m_codec) - m_imp->m_chunkSize = m_codec->getMaxCompressionSize(lx * ly * (bpp >> 3)); - else - m_imp->m_chunkSize = lx * ly * (bpp >> 3); - - TINT64 allocUnitCount = m_imp->m_chunkSize / m_imp->m_allocUnit; - if ((m_imp->m_chunkSize % m_imp->m_allocUnit) != 0) - ++allocUnitCount; - - m_imp->m_chunkSize = allocUnitCount * m_imp->m_allocUnit; - delete[] m_imp->m_readBuffer; - m_imp->m_readBuffer = 0; +void TDiskCachePersist2::setFrameSize(int lx, int ly, int bpp) { + m_imp->m_lx = lx; + m_imp->m_ly = ly; + m_imp->m_bpp = bpp; + + // inizializza m_imp->m_chunkSize in modo che sia un multiplo di + // m_imp->m_allocUnit + if (m_codec) + m_imp->m_chunkSize = m_codec->getMaxCompressionSize(lx * ly * (bpp >> 3)); + else + m_imp->m_chunkSize = lx * ly * (bpp >> 3); + + TINT64 allocUnitCount = m_imp->m_chunkSize / m_imp->m_allocUnit; + if ((m_imp->m_chunkSize % m_imp->m_allocUnit) != 0) ++allocUnitCount; + + m_imp->m_chunkSize = allocUnitCount * m_imp->m_allocUnit; + delete[] m_imp->m_readBuffer; + m_imp->m_readBuffer = 0; } //------------------------------------------------------------------------------ -TRasterP TDiskCachePersist2::doGetRaster(int frame) -{ - TRasterP outRas; - TUINT32 size; - - if (!m_imp->m_readBuffer) - m_imp->m_readBuffer = new UCHAR[TINT32(m_imp->m_chunkSize)]; - - TINT64 pos = frame * m_imp->m_chunkSize; - TINT64 sectorCount = pos / m_imp->m_allocUnit; - - if ((pos % m_imp->m_allocUnit) != 0) - ++sectorCount; - - pos = sectorCount * m_imp->m_allocUnit; - - m_imp->m_file->read(m_imp->m_readBuffer, TINT32(m_imp->m_chunkSize), pos); - size = TUINT32(m_imp->m_chunkSize); - - if (m_codec) - m_codec->decompress(m_imp->m_readBuffer, size, outRas); - else { - switch (m_imp->m_bpp) { - case 32: { - TRaster32P ras(m_imp->m_lx, m_imp->m_ly); - outRas = ras; - } break; - case 64: { - TRaster64P ras(m_imp->m_lx, m_imp->m_ly); - outRas = ras; - } break; - default: - throw TException("unsupported pixel format"); - break; - } - - unsigned int rasSize = outRas->getRowSize() * outRas->getLy(); - assert(size >= rasSize); - outRas->lock(); - memcpy(outRas->getRawData(), m_imp->m_readBuffer, rasSize); - outRas->unlock(); - } - return outRas; +TRasterP TDiskCachePersist2::doGetRaster(int frame) { + TRasterP outRas; + TUINT32 size; + + if (!m_imp->m_readBuffer) + m_imp->m_readBuffer = new UCHAR[TINT32(m_imp->m_chunkSize)]; + + TINT64 pos = frame * m_imp->m_chunkSize; + TINT64 sectorCount = pos / m_imp->m_allocUnit; + + if ((pos % m_imp->m_allocUnit) != 0) ++sectorCount; + + pos = sectorCount * m_imp->m_allocUnit; + + m_imp->m_file->read(m_imp->m_readBuffer, TINT32(m_imp->m_chunkSize), pos); + size = TUINT32(m_imp->m_chunkSize); + + if (m_codec) + m_codec->decompress(m_imp->m_readBuffer, size, outRas); + else { + switch (m_imp->m_bpp) { + case 32: { + TRaster32P ras(m_imp->m_lx, m_imp->m_ly); + outRas = ras; + } break; + case 64: { + TRaster64P ras(m_imp->m_lx, m_imp->m_ly); + outRas = ras; + } break; + default: + throw TException("unsupported pixel format"); + break; + } + + unsigned int rasSize = outRas->getRowSize() * outRas->getLy(); + assert(size >= rasSize); + outRas->lock(); + memcpy(outRas->getRawData(), m_imp->m_readBuffer, rasSize); + outRas->unlock(); + } + return outRas; } //------------------------------------------------------------------------------ -bool TDiskCachePersist2::doGetRaster(int frame, TRaster32P &ras) const -{ - if (!m_imp->m_readBuffer) - m_imp->m_readBuffer = new UCHAR[TINT32(m_imp->m_chunkSize)]; - - TINT64 pos = frame * m_imp->m_chunkSize; - TINT64 sectorCount = pos / m_imp->m_allocUnit; - - if ((pos % m_imp->m_allocUnit) != 0) - ++sectorCount; - - pos = sectorCount * m_imp->m_allocUnit; - - TRasterP rasP = ras; - if (m_codec) { - m_imp->m_file->read(m_imp->m_readBuffer, TINT32(m_imp->m_chunkSize), pos); - m_codec->decompress(m_imp->m_readBuffer, TINT32(m_imp->m_chunkSize), rasP); - assert(rasP->getSize() == ras->getSize()); - ras->copy(rasP); - } else { - assert(ras->getLx() == ras->getWrap()); - int rasSize = ras->getRowSize() * ras->getLy(); - ras->lock(); - if (rasSize == m_imp->m_chunkSize) - m_imp->m_file->read(ras->getRawData(), TINT32(m_imp->m_chunkSize), pos); - else { - assert(rasSize < m_imp->m_chunkSize); - m_imp->m_file->read(m_imp->m_readBuffer, TINT32(m_imp->m_chunkSize), pos); - memcpy(ras->getRawData(), m_imp->m_readBuffer, rasSize); - } - ras->unlock(); - } - return true; +bool TDiskCachePersist2::doGetRaster(int frame, TRaster32P &ras) const { + if (!m_imp->m_readBuffer) + m_imp->m_readBuffer = new UCHAR[TINT32(m_imp->m_chunkSize)]; + + TINT64 pos = frame * m_imp->m_chunkSize; + TINT64 sectorCount = pos / m_imp->m_allocUnit; + + if ((pos % m_imp->m_allocUnit) != 0) ++sectorCount; + + pos = sectorCount * m_imp->m_allocUnit; + + TRasterP rasP = ras; + if (m_codec) { + m_imp->m_file->read(m_imp->m_readBuffer, TINT32(m_imp->m_chunkSize), pos); + m_codec->decompress(m_imp->m_readBuffer, TINT32(m_imp->m_chunkSize), rasP); + assert(rasP->getSize() == ras->getSize()); + ras->copy(rasP); + } else { + assert(ras->getLx() == ras->getWrap()); + int rasSize = ras->getRowSize() * ras->getLy(); + ras->lock(); + if (rasSize == m_imp->m_chunkSize) + m_imp->m_file->read(ras->getRawData(), TINT32(m_imp->m_chunkSize), pos); + else { + assert(rasSize < m_imp->m_chunkSize); + m_imp->m_file->read(m_imp->m_readBuffer, TINT32(m_imp->m_chunkSize), pos); + memcpy(ras->getRawData(), m_imp->m_readBuffer, rasSize); + } + ras->unlock(); + } + return true; } //------------------------------------------------------------------------------ -bool TDiskCachePersist2::doPutRaster(int frame, const TRasterP &inRas) -{ - UCHAR *outData = 0; - TINT32 outDataSize = 0; - int actualDataSize = 0; - - bool deleteDataBuffer = false; - if (m_codec) { - m_codec->compress(inRas, m_imp->m_allocUnit, &outData, outDataSize); - deleteDataBuffer = true; - ; - actualDataSize = outDataSize; - } else { - assert(inRas->getLx() == inRas->getWrap()); - int rasSize = inRas->getLx() * inRas->getLy() * inRas->getPixelSize(); - - outDataSize = TINT32(m_imp->m_chunkSize); - inRas->lock(); - if (rasSize == m_imp->m_chunkSize) - outData = inRas->getRawData(); - else { - if (!m_imp->m_readBuffer) - m_imp->m_readBuffer = new UCHAR[TINT32(m_imp->m_chunkSize)]; - - memcpy(m_imp->m_readBuffer, inRas->getRawData(), rasSize); - outData = m_imp->m_readBuffer; - } - inRas->unlock(); - actualDataSize = rasSize; - } - - assert((outDataSize % m_imp->m_allocUnit) == 0); - - bool cached = true; - if (m_imp->m_asyncWrite) - m_imp->m_bufferQueue->put(frame, outData, actualDataSize, outDataSize); - else - cached = m_imp->put(frame, outData, outDataSize); - - if (deleteDataBuffer) - delete[] outData; - return cached; +bool TDiskCachePersist2::doPutRaster(int frame, const TRasterP &inRas) { + UCHAR *outData = 0; + TINT32 outDataSize = 0; + int actualDataSize = 0; + + bool deleteDataBuffer = false; + if (m_codec) { + m_codec->compress(inRas, m_imp->m_allocUnit, &outData, outDataSize); + deleteDataBuffer = true; + ; + actualDataSize = outDataSize; + } else { + assert(inRas->getLx() == inRas->getWrap()); + int rasSize = inRas->getLx() * inRas->getLy() * inRas->getPixelSize(); + + outDataSize = TINT32(m_imp->m_chunkSize); + inRas->lock(); + if (rasSize == m_imp->m_chunkSize) + outData = inRas->getRawData(); + else { + if (!m_imp->m_readBuffer) + m_imp->m_readBuffer = new UCHAR[TINT32(m_imp->m_chunkSize)]; + + memcpy(m_imp->m_readBuffer, inRas->getRawData(), rasSize); + outData = m_imp->m_readBuffer; + } + inRas->unlock(); + actualDataSize = rasSize; + } + + assert((outDataSize % m_imp->m_allocUnit) == 0); + + bool cached = true; + if (m_imp->m_asyncWrite) + m_imp->m_bufferQueue->put(frame, outData, actualDataSize, outDataSize); + else + cached = m_imp->put(frame, outData, outDataSize); + + if (deleteDataBuffer) delete[] outData; + return cached; } //------------------------------------------------------------------------------ -UCHAR *TDiskCachePersist2::getRawData(int frame, TINT32 &size, int &lx, int &ly) -{ - TUINT32 inDataSize; - UCHAR *src = m_imp->get(frame, &inDataSize); - return m_codec->removeHeader(src, inDataSize, size, lx, ly); +UCHAR *TDiskCachePersist2::getRawData(int frame, TINT32 &size, int &lx, + int &ly) { + TUINT32 inDataSize; + UCHAR *src = m_imp->get(frame, &inDataSize); + return m_codec->removeHeader(src, inDataSize, size, lx, ly); } //------------------------------------------------------------------------------ -void TDiskCachePersist2::onInvalidate() -{ -} +void TDiskCachePersist2::onInvalidate() {} //------------------------------------------------------------------------------ -void TDiskCachePersist2::onInvalidate(int startFrame, int endFrame) -{ -} +void TDiskCachePersist2::onInvalidate(int startFrame, int endFrame) {} //------------------------------------------------------------------------------ -TUINT64 TDiskCachePersist2::getUsedSpace() -{ - TFileStatus fs(m_imp->m_file->getFilePath()); - return fs.getSize(); +TUINT64 TDiskCachePersist2::getUsedSpace() { + TFileStatus fs(m_imp->m_file->getFilePath()); + return fs.getSize(); } //------------------------------------------------------------------------------ -#endif //WIN32 +#endif // WIN32 diff --git a/toonz/sources/common/trasterimage/tcodec.cpp b/toonz/sources/common/trasterimage/tcodec.cpp index 49fc220..224b73b 100644 --- a/toonz/sources/common/trasterimage/tcodec.cpp +++ b/toonz/sources/common/trasterimage/tcodec.cpp @@ -22,122 +22,117 @@ using namespace std; -namespace -{ -class Header -{ - enum RasType { - Raster32RGBM, - Raster64RGBM, - Raster32CM, - RasterGR8, - RasterGR16, - RasterUnknown - }; +namespace { +class Header { + enum RasType { + Raster32RGBM, + Raster64RGBM, + Raster32CM, + RasterGR8, + RasterGR16, + RasterUnknown + }; public: - Header(const TRasterP &ras); - ~Header() {} - TRasterP createRaster() const; - int getRasterSize() const; - int m_lx; - int m_ly; - RasType m_rasType; - Header(void *mem) { memcpy(this, mem, sizeof(Header)); } + Header(const TRasterP &ras); + ~Header() {} + TRasterP createRaster() const; + int getRasterSize() const; + int m_lx; + int m_ly; + RasType m_rasType; + Header(void *mem) { memcpy(this, mem, sizeof(Header)); } private: - Header(); // not implemented + Header(); // not implemented }; //------------------------------------------------------------------------------ -Header::Header(const TRasterP &ras) -{ - assert(ras); - m_lx = ras->getLx(); - m_ly = ras->getLy(); - TRaster32P ras32(ras); - if (ras32) - m_rasType = Raster32RGBM; - else { - TRasterCM32P rasCM32(ras); - if (rasCM32) - m_rasType = Raster32CM; - else { - TRaster64P ras64(ras); - if (ras64) - m_rasType = Raster64RGBM; - else { - TRasterGR8P rasGR8(ras); - if (rasGR8) - m_rasType = RasterGR8; - else { - TRasterGR16P rasGR16(ras); - if (rasGR16) - m_rasType = RasterGR16; - else { - assert(!"Unknown RasterType"); - m_rasType = RasterUnknown; - } - } - } - } - } +Header::Header(const TRasterP &ras) { + assert(ras); + m_lx = ras->getLx(); + m_ly = ras->getLy(); + TRaster32P ras32(ras); + if (ras32) + m_rasType = Raster32RGBM; + else { + TRasterCM32P rasCM32(ras); + if (rasCM32) + m_rasType = Raster32CM; + else { + TRaster64P ras64(ras); + if (ras64) + m_rasType = Raster64RGBM; + else { + TRasterGR8P rasGR8(ras); + if (rasGR8) + m_rasType = RasterGR8; + else { + TRasterGR16P rasGR16(ras); + if (rasGR16) + m_rasType = RasterGR16; + else { + assert(!"Unknown RasterType"); + m_rasType = RasterUnknown; + } + } + } + } + } } //------------------------------------------------------------------------------ -TRasterP Header::createRaster() const -{ - switch (m_rasType) { - case Raster32RGBM: - return TRaster32P(m_lx, m_ly); - break; - case Raster32CM: - return TRasterCM32P(m_lx, m_ly); - break; - case Raster64RGBM: - return TRaster64P(m_lx, m_ly); - break; - case RasterGR8: - return TRasterGR8P(m_lx, m_ly); - break; - case RasterGR16: - return TRasterGR16P(m_lx, m_ly); - break; - default: - assert(0); - return TRasterP(); - break; - } - return TRasterP(); +TRasterP Header::createRaster() const { + switch (m_rasType) { + case Raster32RGBM: + return TRaster32P(m_lx, m_ly); + break; + case Raster32CM: + return TRasterCM32P(m_lx, m_ly); + break; + case Raster64RGBM: + return TRaster64P(m_lx, m_ly); + break; + case RasterGR8: + return TRasterGR8P(m_lx, m_ly); + break; + case RasterGR16: + return TRasterGR16P(m_lx, m_ly); + break; + default: + assert(0); + return TRasterP(); + break; + } + return TRasterP(); } //------------------------------------------------------------------------------ -int Header::getRasterSize() const -{ - switch (m_rasType) { - case Raster32RGBM: - return 4 * m_lx * m_ly; - break; - case Raster32CM: - return 4 * m_lx * m_ly; - break; - case Raster64RGBM: - return 8 * m_lx * m_ly; - break; - case RasterGR8: - return m_lx * m_ly; - break; - default: - assert(0); - return 0; - break; - } +int Header::getRasterSize() const { + switch (m_rasType) { + case Raster32RGBM: + return 4 * m_lx * m_ly; + break; + case Raster32CM: + return 4 * m_lx * m_ly; + break; + case Raster64RGBM: + return 8 * m_lx * m_ly; + break; + case RasterGR8: + return m_lx * m_ly; + break; + default: + assert(0); + return 0; + break; + } } //------------------------------------------------------------------------------ -} //anonymous namespace +} // anonymous namespace //------------------------------------------------------------------------------ // TRasterCodecSnappy @@ -163,7 +158,8 @@ TRasterCodecSnappy::~TRasterCodecSnappy() //------------------------------------------------------------------------------ -UINT TRasterCodecSnappy::doCompress(const TRasterP &inRas, int allocUnit, TRasterGR8P& outRas) +UINT TRasterCodecSnappy::doCompress(const TRasterP &inRas, int allocUnit, +TRasterGR8P& outRas) { assert(inRas); @@ -178,7 +174,8 @@ UINT TRasterCodecSnappy::doCompress(const TRasterP &inRas, int allocUnit, TRaste if (m_cacheId=="") m_cacheId = TImageCache::instance()->getUniqueId(); else - outRas = ((TRasterImageP)TImageCache::instance()->get(m_cacheId, true))->getRaster(); + outRas = ((TRasterImageP)TImageCache::instance()->get(m_cacheId, +true))->getRaster(); } else outRas = m_raster; @@ -218,18 +215,20 @@ UINT TRasterCodecSnappy::doCompress(const TRasterP &inRas, int allocUnit, TRaste //------------------------------------------------------------------------------ -TRasterP TRasterCodecSnappy::compress(const TRasterP &inRas, int allocUnit, TINT32 &outDataSize) +TRasterP TRasterCodecSnappy::compress(const TRasterP &inRas, int allocUnit, +TINT32 &outDataSize) { TRasterGR8P rasOut; UINT outSize = doCompress(inRas, allocUnit, rasOut); if (outSize==0) return TRasterP(); - + UINT headerSize = sizeof(Header); - if (TBigMemoryManager::instance()->isActive() && - TBigMemoryManager::instance()->getAvailableMemoryinKb()<((outSize + headerSize)>>10)) - return TRasterP(); - + if (TBigMemoryManager::instance()->isActive() && + TBigMemoryManager::instance()->getAvailableMemoryinKb()<((outSize + +headerSize)>>10)) + return TRasterP(); + TRasterGR8P r8(outSize + headerSize, 1); r8->lock(); UCHAR *memoryChunk = r8->getRawData(); @@ -249,7 +248,8 @@ TRasterP TRasterCodecSnappy::compress(const TRasterP &inRas, int allocUnit, TINT //------------------------------------------------------------------------------ -bool TRasterCodecSnappy::decompress(const UCHAR* inData, TINT32 inDataSize, TRasterP &outRas, bool safeMode) +bool TRasterCodecSnappy::decompress(const UCHAR* inData, TINT32 inDataSize, +TRasterP &outRas, bool safeMode) { int headerSize = sizeof(Header); @@ -275,7 +275,8 @@ bool TRasterCodecSnappy::decompress(const UCHAR* inData, TINT32 inDataSize, TRas snappy_uncompressed_length(mc, ds, &outSize); outRas->lock(); - snappy_status rc = snappy_uncompress(mc, ds, (char*) outRas->getRawData(), &outSize); + snappy_status rc = snappy_uncompress(mc, ds, (char*) outRas->getRawData(), +&outSize); outRas->unlock(); if (rc != SNAPPY_OK) @@ -284,7 +285,7 @@ bool TRasterCodecSnappy::decompress(const UCHAR* inData, TINT32 inDataSize, TRas return false; else { - throw TException("decompress... something goes bad"); + throw TException("decompress... something goes bad"); return false; } } @@ -295,7 +296,8 @@ bool TRasterCodecSnappy::decompress(const UCHAR* inData, TINT32 inDataSize, TRas //------------------------------------------------------------------------------ -void TRasterCodecSnappy::decompress(const TRasterP & compressedRas, TRasterP &outRas) +void TRasterCodecSnappy::decompress(const TRasterP & compressedRas, TRasterP +&outRas) { int headerSize = sizeof(Header); @@ -346,470 +348,445 @@ void TRasterCodecSnappy::decompress(const TRasterP & compressedRas, TRasterP &ou // TRasterCodecLz4 //------------------------------------------------------------------------------ -namespace -{ -bool lz4decompress(LZ4F_decompressionContext_t lz4dctx, - char *out, size_t *out_len_res, - const char *in, size_t in_len) -{ - size_t out_len = *out_len_res, - in_read, out_written; +namespace { +bool lz4decompress(LZ4F_decompressionContext_t lz4dctx, char *out, + size_t *out_len_res, const char *in, size_t in_len) { + size_t out_len = *out_len_res, in_read, out_written; - *out_len_res = 0; + *out_len_res = 0; - while (in_len) { - out_written = out_len; - in_read = in_len; + while (in_len) { + out_written = out_len; + in_read = in_len; - size_t res = LZ4F_decompress( - lz4dctx, (void *)out, &out_written, (const void *)in, &in_read, NULL); + size_t res = LZ4F_decompress(lz4dctx, (void *)out, &out_written, + (const void *)in, &in_read, NULL); - if (LZ4F_isError(res)) - return false; + if (LZ4F_isError(res)) return false; - *out_len_res += out_written; + *out_len_res += out_written; - out += out_written; - out_len -= out_written; + out += out_written; + out_len -= out_written; - in += in_read; - in_len -= in_read; - } + in += in_read; + in_len -= in_read; + } - return true; + return true; } -} // namespace +} // namespace TRasterCodecLz4::TRasterCodecLz4(const std::string &name, bool useCache) - : TRasterCodec(name), m_raster(), m_useCache(useCache), m_cacheId("") -{ -} + : TRasterCodec(name), m_raster(), m_useCache(useCache), m_cacheId("") {} //------------------------------------------------------------------------------ -TRasterCodecLz4::~TRasterCodecLz4() -{ - if (m_useCache) - TImageCache::instance()->remove(m_cacheId); - else - m_raster = TRasterGR8P(); +TRasterCodecLz4::~TRasterCodecLz4() { + if (m_useCache) + TImageCache::instance()->remove(m_cacheId); + else + m_raster = TRasterGR8P(); } //------------------------------------------------------------------------------ -UINT TRasterCodecLz4::doCompress(const TRasterP &inRas, int allocUnit, TRasterGR8P &outRas) -{ - assert(inRas); - - assert(inRas->getLx() == inRas->getWrap()); - - size_t inDataSize = inRas->getLx() * inRas->getLy() * inRas->getPixelSize(); - size_t maxReqSize = LZ4F_compressFrameBound(inDataSize, NULL); - - if (m_useCache) { - if (m_cacheId == "") - m_cacheId = TImageCache::instance()->getUniqueId(); - else - outRas = ((TRasterImageP)TImageCache::instance()->get(m_cacheId, true))->getRaster(); - } else - outRas = m_raster; - - if (!outRas || outRas->getLx() < (int)maxReqSize) { - outRas = TRasterGR8P(); - m_raster = TRasterGR8P(); - if (m_useCache) - TImageCache::instance()->remove(m_cacheId); - outRas = TRasterGR8P(maxReqSize, 1); - if (m_useCache) - TImageCache::instance()->add(m_cacheId, TRasterImageP(outRas), true); - else - m_raster = outRas; - } - - outRas->lock(); - void *buffer = (void *)outRas->getRawData(); - if (!buffer) - return 0; - - inRas->lock(); - const void *inData = (const void *)inRas->getRawData(); - - size_t outSize = LZ4F_compressFrame(buffer, maxReqSize, inData, inDataSize, NULL); - outRas->unlock(); - inRas->unlock(); - - if (LZ4F_isError(outSize)) - throw TException("compress... something goes bad"); - - return outSize; +UINT TRasterCodecLz4::doCompress(const TRasterP &inRas, int allocUnit, + TRasterGR8P &outRas) { + assert(inRas); + + assert(inRas->getLx() == inRas->getWrap()); + + size_t inDataSize = inRas->getLx() * inRas->getLy() * inRas->getPixelSize(); + size_t maxReqSize = LZ4F_compressFrameBound(inDataSize, NULL); + + if (m_useCache) { + if (m_cacheId == "") + m_cacheId = TImageCache::instance()->getUniqueId(); + else + outRas = ((TRasterImageP)TImageCache::instance()->get(m_cacheId, true)) + ->getRaster(); + } else + outRas = m_raster; + + if (!outRas || outRas->getLx() < (int)maxReqSize) { + outRas = TRasterGR8P(); + m_raster = TRasterGR8P(); + if (m_useCache) TImageCache::instance()->remove(m_cacheId); + outRas = TRasterGR8P(maxReqSize, 1); + if (m_useCache) + TImageCache::instance()->add(m_cacheId, TRasterImageP(outRas), true); + else + m_raster = outRas; + } + + outRas->lock(); + void *buffer = (void *)outRas->getRawData(); + if (!buffer) return 0; + + inRas->lock(); + const void *inData = (const void *)inRas->getRawData(); + + size_t outSize = + LZ4F_compressFrame(buffer, maxReqSize, inData, inDataSize, NULL); + outRas->unlock(); + inRas->unlock(); + + if (LZ4F_isError(outSize)) throw TException("compress... something goes bad"); + + return outSize; } //------------------------------------------------------------------------------ -TRasterP TRasterCodecLz4::compress(const TRasterP &inRas, int allocUnit, TINT32 &outDataSize) -{ - TRasterGR8P rasOut; - UINT outSize = doCompress(inRas, allocUnit, rasOut); - if (outSize == 0) - return TRasterP(); - - UINT headerSize = sizeof(Header); - if (TBigMemoryManager::instance()->isActive() && - TBigMemoryManager::instance()->getAvailableMemoryinKb() < ((outSize + headerSize) >> 10)) - return TRasterP(); - - TRasterGR8P r8(outSize + headerSize, 1); - r8->lock(); - UCHAR *memoryChunk = r8->getRawData(); - if (!memoryChunk) - return TRasterP(); - Header head(inRas); - - memcpy(memoryChunk, &head, headerSize); - UCHAR *tmp = memoryChunk + headerSize; - rasOut->lock(); - memcpy(tmp, rasOut->getRawData(), outSize); - r8->unlock(); - rasOut->unlock(); - outDataSize = outSize + headerSize; - return r8; +TRasterP TRasterCodecLz4::compress(const TRasterP &inRas, int allocUnit, + TINT32 &outDataSize) { + TRasterGR8P rasOut; + UINT outSize = doCompress(inRas, allocUnit, rasOut); + if (outSize == 0) return TRasterP(); + + UINT headerSize = sizeof(Header); + if (TBigMemoryManager::instance()->isActive() && + TBigMemoryManager::instance()->getAvailableMemoryinKb() < + ((outSize + headerSize) >> 10)) + return TRasterP(); + + TRasterGR8P r8(outSize + headerSize, 1); + r8->lock(); + UCHAR *memoryChunk = r8->getRawData(); + if (!memoryChunk) return TRasterP(); + Header head(inRas); + + memcpy(memoryChunk, &head, headerSize); + UCHAR *tmp = memoryChunk + headerSize; + rasOut->lock(); + memcpy(tmp, rasOut->getRawData(), outSize); + r8->unlock(); + rasOut->unlock(); + outDataSize = outSize + headerSize; + return r8; } //------------------------------------------------------------------------------ -bool TRasterCodecLz4::decompress(const UCHAR *inData, TINT32 inDataSize, TRasterP &outRas, bool safeMode) -{ - int headerSize = sizeof(Header); - - Header *header = (Header *)inData; - if (!outRas) { - outRas = header->createRaster(); - if (!outRas) - throw TException(); - } else { - if (outRas->getLx() != outRas->getWrap()) - throw TException(); - } - - LZ4F_decompressionContext_t lz4dctx; - - LZ4F_errorCode_t err = LZ4F_createDecompressionContext(&lz4dctx, LZ4F_VERSION); - if (LZ4F_isError(err)) - throw TException("compress... something goes bad"); - - int outDataSize = header->getRasterSize(); - - const char *mc = (const char *)(inData + headerSize); - size_t ds = inDataSize - headerSize; - - size_t outSize = outDataSize; - char *outData = (char *)outRas->getRawData(); - - outRas->lock(); - //err = LZ4F_decompress(lz4dctx, outData, &outSize, mc, &ds, NULL); - bool ok = lz4decompress(lz4dctx, outData, &outSize, mc, ds); - LZ4F_freeDecompressionContext(lz4dctx); - outRas->unlock(); - - if (!ok) { - if (safeMode) - return false; - else { - throw TException("decompress... something goes bad"); - return false; - } - } - - assert(outSize == (size_t)outDataSize); - return true; +bool TRasterCodecLz4::decompress(const UCHAR *inData, TINT32 inDataSize, + TRasterP &outRas, bool safeMode) { + int headerSize = sizeof(Header); + + Header *header = (Header *)inData; + if (!outRas) { + outRas = header->createRaster(); + if (!outRas) throw TException(); + } else { + if (outRas->getLx() != outRas->getWrap()) throw TException(); + } + + LZ4F_decompressionContext_t lz4dctx; + + LZ4F_errorCode_t err = + LZ4F_createDecompressionContext(&lz4dctx, LZ4F_VERSION); + if (LZ4F_isError(err)) throw TException("compress... something goes bad"); + + int outDataSize = header->getRasterSize(); + + const char *mc = (const char *)(inData + headerSize); + size_t ds = inDataSize - headerSize; + + size_t outSize = outDataSize; + char *outData = (char *)outRas->getRawData(); + + outRas->lock(); + // err = LZ4F_decompress(lz4dctx, outData, &outSize, mc, &ds, NULL); + bool ok = lz4decompress(lz4dctx, outData, &outSize, mc, ds); + LZ4F_freeDecompressionContext(lz4dctx); + outRas->unlock(); + + if (!ok) { + if (safeMode) + return false; + else { + throw TException("decompress... something goes bad"); + return false; + } + } + + assert(outSize == (size_t)outDataSize); + return true; } //------------------------------------------------------------------------------ -void TRasterCodecLz4::decompress(const TRasterP &compressedRas, TRasterP &outRas) -{ - int headerSize = sizeof(Header); +void TRasterCodecLz4::decompress(const TRasterP &compressedRas, + TRasterP &outRas) { + int headerSize = sizeof(Header); - assert(compressedRas->getLy() == 1 && compressedRas->getPixelSize() == 1); - UINT inDataSize = compressedRas->getLx(); + assert(compressedRas->getLy() == 1 && compressedRas->getPixelSize() == 1); + UINT inDataSize = compressedRas->getLx(); - compressedRas->lock(); + compressedRas->lock(); - UCHAR *inData = compressedRas->getRawData(); - Header header(inData); + UCHAR *inData = compressedRas->getRawData(); + Header header(inData); - if (!outRas) { - outRas = header.createRaster(); - if (!outRas) - throw TException(); - } else { - if (outRas->getLx() != outRas->getWrap()) - throw TException(); - } + if (!outRas) { + outRas = header.createRaster(); + if (!outRas) throw TException(); + } else { + if (outRas->getLx() != outRas->getWrap()) throw TException(); + } - LZ4F_decompressionContext_t lz4dctx; + LZ4F_decompressionContext_t lz4dctx; - LZ4F_errorCode_t err = LZ4F_createDecompressionContext(&lz4dctx, LZ4F_VERSION); - if (LZ4F_isError(err)) - throw TException("compress... something goes bad"); + LZ4F_errorCode_t err = + LZ4F_createDecompressionContext(&lz4dctx, LZ4F_VERSION); + if (LZ4F_isError(err)) throw TException("compress... something goes bad"); - int outDataSize = header.getRasterSize(); + int outDataSize = header.getRasterSize(); - const char *mc = (const char *)(inData + headerSize); - size_t ds = inDataSize - headerSize; + const char *mc = (const char *)(inData + headerSize); + size_t ds = inDataSize - headerSize; - size_t outSize = outDataSize; - char *outData = (char *)outRas->getRawData(); + size_t outSize = outDataSize; + char *outData = (char *)outRas->getRawData(); - outRas->lock(); + outRas->lock(); - //err = LZ4F_decompress(lz4dctx, outData, &outSize, mc, &ds, NULL); - bool ok = lz4decompress(lz4dctx, outData, &outSize, mc, ds); - LZ4F_freeDecompressionContext(lz4dctx); + // err = LZ4F_decompress(lz4dctx, outData, &outSize, mc, &ds, NULL); + bool ok = lz4decompress(lz4dctx, outData, &outSize, mc, ds); + LZ4F_freeDecompressionContext(lz4dctx); - outRas->unlock(); - compressedRas->unlock(); + outRas->unlock(); + compressedRas->unlock(); - if (!ok) - throw TException("decompress... something goes bad"); + if (!ok) throw TException("decompress... something goes bad"); - assert(outSize == (size_t)outDataSize); + assert(outSize == (size_t)outDataSize); } //------------------------------------------------------------------------------ // TRasterCodecLZO //------------------------------------------------------------------------------ -namespace -{ - -bool lzoCompress(const QByteArray src, QByteArray &dst) -{ - QDir exeDir(QCoreApplication::applicationDirPath()); - QString compressExe = exeDir.filePath("lzocompress"); - QProcess process; - process.start(compressExe, QStringList() << QString::number(src.size())); - if (!process.waitForStarted()) - return false; - process.write(src); - if (!process.waitForFinished()) - return false; - dst = process.readAll(); - return process.exitCode() == 0; +namespace { + +bool lzoCompress(const QByteArray src, QByteArray &dst) { + QDir exeDir(QCoreApplication::applicationDirPath()); + QString compressExe = exeDir.filePath("lzocompress"); + QProcess process; + process.start(compressExe, QStringList() << QString::number(src.size())); + if (!process.waitForStarted()) return false; + process.write(src); + if (!process.waitForFinished()) return false; + dst = process.readAll(); + return process.exitCode() == 0; } -bool lzoDecompress(const QByteArray src, int dstSize, QByteArray &dst) -{ - QDir exeDir(QCoreApplication::applicationDirPath()); - QString decompressExe = exeDir.filePath("lzodecompress"); - QProcess process; - process.start(decompressExe, QStringList() << QString::number(dstSize) << QString::number(src.size())); - if (!process.waitForStarted()) - return false; - process.write(src); - if (!process.waitForFinished()) - return false; - dst = process.readAll(); - return process.exitCode() == 0 && dst.size() == dstSize; +bool lzoDecompress(const QByteArray src, int dstSize, QByteArray &dst) { + QDir exeDir(QCoreApplication::applicationDirPath()); + QString decompressExe = exeDir.filePath("lzodecompress"); + QProcess process; + process.start(decompressExe, QStringList() << QString::number(dstSize) + << QString::number(src.size())); + if (!process.waitForStarted()) return false; + process.write(src); + if (!process.waitForFinished()) return false; + dst = process.readAll(); + return process.exitCode() == 0 && dst.size() == dstSize; } } //------------------------------------------------------------------------------ TRasterCodecLZO::TRasterCodecLZO(const std::string &name, bool useCache) - : TRasterCodec(name), m_raster(), m_useCache(useCache), m_cacheId("") -{ -} + : TRasterCodec(name), m_raster(), m_useCache(useCache), m_cacheId("") {} //------------------------------------------------------------------------------ -TRasterCodecLZO::~TRasterCodecLZO() -{ - if (m_useCache) - TImageCache::instance()->remove(m_cacheId); - else - m_raster = TRasterGR8P(); +TRasterCodecLZO::~TRasterCodecLZO() { + if (m_useCache) + TImageCache::instance()->remove(m_cacheId); + else + m_raster = TRasterGR8P(); } //------------------------------------------------------------------------------ -UINT TRasterCodecLZO::doCompress(const TRasterP &inRas, int allocUnit, TRasterGR8P &outRas) -{ - assert(inRas); - - assert(inRas->getLx() == inRas->getWrap()); - - size_t inDataSize = inRas->getLx() * inRas->getLy() * inRas->getPixelSize(); - - // compress data - inRas->lock(); - char *inData = (char *)inRas->getRawData(); - QByteArray compressedBuffer; - if (!lzoCompress(QByteArray(inData, inDataSize), compressedBuffer)) - throw TException("LZO compression failed"); - - inRas->unlock(); - - size_t maxReqSize = compressedBuffer.size(); // we have just done the compression: we know the actual size - - if (m_useCache) { - if (m_cacheId == "") - m_cacheId = TImageCache::instance()->getUniqueId(); - else - outRas = ((TRasterImageP)TImageCache::instance()->get(m_cacheId, true))->getRaster(); - } else - outRas = m_raster; - - if (!outRas || outRas->getLx() < (int)maxReqSize) { - outRas = TRasterGR8P(); - m_raster = TRasterGR8P(); - if (m_useCache) - TImageCache::instance()->remove(m_cacheId); - outRas = TRasterGR8P(maxReqSize, 1); - if (m_useCache) - TImageCache::instance()->add(m_cacheId, TRasterImageP(outRas), true); - else - m_raster = outRas; - } - - size_t outSize = maxReqSize; - outRas->lock(); - char *buffer = (char *)outRas->getRawData(); // Change cast types, if needed - if (!buffer) { - outRas->unlock(); - return 0; - } - memcpy(buffer, compressedBuffer.data(), outSize); - outRas->unlock(); - - return outSize; +UINT TRasterCodecLZO::doCompress(const TRasterP &inRas, int allocUnit, + TRasterGR8P &outRas) { + assert(inRas); + + assert(inRas->getLx() == inRas->getWrap()); + + size_t inDataSize = inRas->getLx() * inRas->getLy() * inRas->getPixelSize(); + + // compress data + inRas->lock(); + char *inData = (char *)inRas->getRawData(); + QByteArray compressedBuffer; + if (!lzoCompress(QByteArray(inData, inDataSize), compressedBuffer)) + throw TException("LZO compression failed"); + + inRas->unlock(); + + size_t maxReqSize = compressedBuffer.size(); // we have just done the + // compression: we know the + // actual size + + if (m_useCache) { + if (m_cacheId == "") + m_cacheId = TImageCache::instance()->getUniqueId(); + else + outRas = ((TRasterImageP)TImageCache::instance()->get(m_cacheId, true)) + ->getRaster(); + } else + outRas = m_raster; + + if (!outRas || outRas->getLx() < (int)maxReqSize) { + outRas = TRasterGR8P(); + m_raster = TRasterGR8P(); + if (m_useCache) TImageCache::instance()->remove(m_cacheId); + outRas = TRasterGR8P(maxReqSize, 1); + if (m_useCache) + TImageCache::instance()->add(m_cacheId, TRasterImageP(outRas), true); + else + m_raster = outRas; + } + + size_t outSize = maxReqSize; + outRas->lock(); + char *buffer = (char *)outRas->getRawData(); // Change cast types, if needed + if (!buffer) { + outRas->unlock(); + return 0; + } + memcpy(buffer, compressedBuffer.data(), outSize); + outRas->unlock(); + + return outSize; } //------------------------------------------------------------------------------ -TRasterP TRasterCodecLZO::compress(const TRasterP &inRas, int allocUnit, TINT32 &outDataSize) -{ - TRasterGR8P rasOut; - UINT outSize = doCompress(inRas, allocUnit, rasOut); - if (outSize == 0) - return TRasterP(); - - UINT headerSize = sizeof(Header); - if (TBigMemoryManager::instance()->isActive() && - TBigMemoryManager::instance()->getAvailableMemoryinKb() < ((outSize + headerSize) >> 10)) - return TRasterP(); - - TRasterGR8P r8(outSize + headerSize, 1); - r8->lock(); - UCHAR *memoryChunk = r8->getRawData(); - if (!memoryChunk) - return TRasterP(); - Header head(inRas); - - memcpy(memoryChunk, &head, headerSize); - UCHAR *tmp = memoryChunk + headerSize; - rasOut->lock(); - memcpy(tmp, rasOut->getRawData(), outSize); - r8->unlock(); - rasOut->unlock(); - outDataSize = outSize + headerSize; - return r8; +TRasterP TRasterCodecLZO::compress(const TRasterP &inRas, int allocUnit, + TINT32 &outDataSize) { + TRasterGR8P rasOut; + UINT outSize = doCompress(inRas, allocUnit, rasOut); + if (outSize == 0) return TRasterP(); + + UINT headerSize = sizeof(Header); + if (TBigMemoryManager::instance()->isActive() && + TBigMemoryManager::instance()->getAvailableMemoryinKb() < + ((outSize + headerSize) >> 10)) + return TRasterP(); + + TRasterGR8P r8(outSize + headerSize, 1); + r8->lock(); + UCHAR *memoryChunk = r8->getRawData(); + if (!memoryChunk) return TRasterP(); + Header head(inRas); + + memcpy(memoryChunk, &head, headerSize); + UCHAR *tmp = memoryChunk + headerSize; + rasOut->lock(); + memcpy(tmp, rasOut->getRawData(), outSize); + r8->unlock(); + rasOut->unlock(); + outDataSize = outSize + headerSize; + return r8; } //------------------------------------------------------------------------------ -bool TRasterCodecLZO::decompress(const UCHAR *inData, TINT32 inDataSize, TRasterP &outRas, bool safeMode) -{ - int headerSize = sizeof(Header); +bool TRasterCodecLZO::decompress(const UCHAR *inData, TINT32 inDataSize, + TRasterP &outRas, bool safeMode) { + int headerSize = sizeof(Header); - Header *header = (Header *)inData; - if (!outRas) { - outRas = header->createRaster(); - if (!outRas) - throw TException(); - } else { - if (outRas->getLx() != outRas->getWrap()) - throw TException(); - } + Header *header = (Header *)inData; + if (!outRas) { + outRas = header->createRaster(); + if (!outRas) throw TException(); + } else { + if (outRas->getLx() != outRas->getWrap()) throw TException(); + } - int outDataSize = header->getRasterSize(); + int outDataSize = header->getRasterSize(); - char *mc = (char *)inData + headerSize; - int ds = inDataSize - headerSize; + char *mc = (char *)inData + headerSize; + int ds = inDataSize - headerSize; - size_t outSize = outDataSize; // Calculate output buffer size + size_t outSize = outDataSize; // Calculate output buffer size - QByteArray decompressedBuffer; - if (!lzoDecompress(QByteArray(mc, ds), outSize, decompressedBuffer)) - throw TException("LZO decompression failed"); + QByteArray decompressedBuffer; + if (!lzoDecompress(QByteArray(mc, ds), outSize, decompressedBuffer)) + throw TException("LZO decompression failed"); - outRas->lock(); - memcpy(outRas->getRawData(), decompressedBuffer.data(), decompressedBuffer.size()); - bool rc = true; + outRas->lock(); + memcpy(outRas->getRawData(), decompressedBuffer.data(), + decompressedBuffer.size()); + bool rc = true; - outRas->unlock(); + outRas->unlock(); - /* - if (rc != true) // Check success code here - { - if (safeMode) - return false; - else - { - throw TException("decompress... something goes bad"); - return false; - } - } - */ + /* +if (rc != true) // Check success code here +{ +if (safeMode) +return false; +else +{ +throw TException("decompress... something goes bad"); +return false; +} +} + */ - assert(outSize == (size_t)outDataSize); - return true; + assert(outSize == (size_t)outDataSize); + return true; } //------------------------------------------------------------------------------ -void TRasterCodecLZO::decompress(const TRasterP &compressedRas, TRasterP &outRas) -{ - int headerSize = sizeof(Header); +void TRasterCodecLZO::decompress(const TRasterP &compressedRas, + TRasterP &outRas) { + int headerSize = sizeof(Header); - assert(compressedRas->getLy() == 1 && compressedRas->getPixelSize() == 1); - UINT inDataSize = compressedRas->getLx(); + assert(compressedRas->getLy() == 1 && compressedRas->getPixelSize() == 1); + UINT inDataSize = compressedRas->getLx(); - compressedRas->lock(); + compressedRas->lock(); - UCHAR *inData = compressedRas->getRawData(); - Header header(inData); + UCHAR *inData = compressedRas->getRawData(); + Header header(inData); - if (!outRas) { - outRas = header.createRaster(); - if (!outRas) - throw TException(); - } else { - if (outRas->getLx() != outRas->getWrap()) - throw TException(); - } + if (!outRas) { + outRas = header.createRaster(); + if (!outRas) throw TException(); + } else { + if (outRas->getLx() != outRas->getWrap()) throw TException(); + } - int outDataSize = header.getRasterSize(); + int outDataSize = header.getRasterSize(); - char *mc = (char *)inData + headerSize; - int ds = inDataSize - headerSize; + char *mc = (char *)inData + headerSize; + int ds = inDataSize - headerSize; - size_t outSize = outDataSize; // Calculate output buffer size + size_t outSize = outDataSize; // Calculate output buffer size - char *outData = (char *)outRas->getRawData(); + char *outData = (char *)outRas->getRawData(); - QByteArray decompressedBuffer; - if (!lzoDecompress(QByteArray(mc, ds), outSize, decompressedBuffer)) - throw TException("LZO decompression failed"); - outRas->lock(); - memcpy(outRas->getRawData(), decompressedBuffer.data(), decompressedBuffer.size()); - bool rc = true; + QByteArray decompressedBuffer; + if (!lzoDecompress(QByteArray(mc, ds), outSize, decompressedBuffer)) + throw TException("LZO decompression failed"); + outRas->lock(); + memcpy(outRas->getRawData(), decompressedBuffer.data(), + decompressedBuffer.size()); + bool rc = true; - outRas->unlock(); - compressedRas->unlock(); + outRas->unlock(); + compressedRas->unlock(); - if (rc != true) // Check success code here - throw TException("decompress... something goes bad"); + if (rc != true) // Check success code here + throw TException("decompress... something goes bad"); - assert(outSize == (size_t)outDataSize); + assert(outSize == (size_t)outDataSize); } diff --git a/toonz/sources/common/trasterimage/trasterimage.cpp b/toonz/sources/common/trasterimage/trasterimage.cpp index b503aa9..887e82b 100644 --- a/toonz/sources/common/trasterimage/trasterimage.cpp +++ b/toonz/sources/common/trasterimage/trasterimage.cpp @@ -6,89 +6,93 @@ //--------------------------------------------------------- TRasterImage::TRasterImage() - : m_mainRaster(), m_patchRaster(), m_iconRaster(), m_dpix(0), m_dpiy(0), m_name(""), m_savebox() - //, m_hPos(0.0) - , - m_isOpaque(false), m_isScanBW(false), m_offset(0, 0), m_subsampling(1) -{ -} + : m_mainRaster() + , m_patchRaster() + , m_iconRaster() + , m_dpix(0) + , m_dpiy(0) + , m_name("") + , m_savebox() + //, m_hPos(0.0) + , m_isOpaque(false) + , m_isScanBW(false) + , m_offset(0, 0) + , m_subsampling(1) {} //--------------------------------------------------------- TRasterImage::TRasterImage(const TRasterP &ras) - : m_mainRaster(ras), m_patchRaster(), m_iconRaster(), m_dpix(0), m_dpiy(0), m_name(""), m_savebox(0, 0, ras->getLx() - 1, ras->getLy() - 1) - //, m_hPos(0.0) - , - m_isOpaque(false), m_isScanBW(false), m_offset(0, 0), m_subsampling(1) -{ -} - -void TRasterImage::setRaster(const TRasterP &raster) -{ - m_mainRaster = raster; - m_savebox = TRect(0, 0, raster->getLx() - 1, raster->getLy() - 1); + : m_mainRaster(ras) + , m_patchRaster() + , m_iconRaster() + , m_dpix(0) + , m_dpiy(0) + , m_name("") + , m_savebox(0, 0, ras->getLx() - 1, ras->getLy() - 1) + //, m_hPos(0.0) + , m_isOpaque(false) + , m_isScanBW(false) + , m_offset(0, 0) + , m_subsampling(1) {} + +void TRasterImage::setRaster(const TRasterP &raster) { + m_mainRaster = raster; + m_savebox = TRect(0, 0, raster->getLx() - 1, raster->getLy() - 1); } //--------------------------------------------------------- TRasterImage::TRasterImage(const TRasterImage &src) - : m_mainRaster(src.m_mainRaster), m_patchRaster(src.m_patchRaster), m_iconRaster(src.m_iconRaster), m_dpix(src.m_dpix), m_dpiy(src.m_dpiy), m_name(src.m_name), m_savebox(src.m_savebox) - //, m_hPos(src.m_hPos) - , - m_isOpaque(src.m_isOpaque), m_isScanBW(src.m_isScanBW), m_offset(src.m_offset), m_subsampling(src.m_subsampling) -{ - if (m_mainRaster) - m_mainRaster = m_mainRaster->clone(); - if (m_patchRaster) - m_patchRaster = m_patchRaster->clone(); - if (m_iconRaster) - m_iconRaster = m_iconRaster->clone(); + : m_mainRaster(src.m_mainRaster) + , m_patchRaster(src.m_patchRaster) + , m_iconRaster(src.m_iconRaster) + , m_dpix(src.m_dpix) + , m_dpiy(src.m_dpiy) + , m_name(src.m_name) + , m_savebox(src.m_savebox) + //, m_hPos(src.m_hPos) + , m_isOpaque(src.m_isOpaque) + , m_isScanBW(src.m_isScanBW) + , m_offset(src.m_offset) + , m_subsampling(src.m_subsampling) { + if (m_mainRaster) m_mainRaster = m_mainRaster->clone(); + if (m_patchRaster) m_patchRaster = m_patchRaster->clone(); + if (m_iconRaster) m_iconRaster = m_iconRaster->clone(); } //--------------------------------------------------------- -TRasterImage::~TRasterImage() -{ -} +TRasterImage::~TRasterImage() {} //--------------------------------------------------------- -TImage *TRasterImage::cloneImage() const -{ - return new TRasterImage(*this); -} +TImage *TRasterImage::cloneImage() const { return new TRasterImage(*this); } //--------------------------------------------------------- -void TRasterImage::setSubsampling(int s) -{ - m_subsampling = s; -} +void TRasterImage::setSubsampling(int s) { m_subsampling = s; } //--------------------------------------------------------- -void TRasterImage::makeIcon(const TRaster32P &dstRas) -{ +void TRasterImage::makeIcon(const TRaster32P &dstRas) { #ifndef TNZCORE_LIGHT - assert(dstRas && dstRas->getLx() > 0 && dstRas->getLy() > 0); - - TRasterP &srcRas = m_mainRaster; - if (!srcRas || srcRas->getLx() <= 0 || srcRas->getLy() <= 0) { - dstRas->clear(); - return; - } - - double dpix = m_dpix, dpiy = m_dpiy; - if (dpix == 0) - dpix = 1; - if (dpiy == 0) - dpiy = 1; - double sx = (double)dstRas->getLx() * dpix / (double)srcRas->getLx(); - double sy = (double)dstRas->getLy() * dpiy / (double)srcRas->getLy(); - double sc = std::max(sx, sy); - TAffine aff = TScale(sc / dpix, sc / dpiy) - .place(srcRas->getCenterD(), dstRas->getCenterD()); - - TRop::resample(dstRas, srcRas, aff); + assert(dstRas && dstRas->getLx() > 0 && dstRas->getLy() > 0); + + TRasterP &srcRas = m_mainRaster; + if (!srcRas || srcRas->getLx() <= 0 || srcRas->getLy() <= 0) { + dstRas->clear(); + return; + } + + double dpix = m_dpix, dpiy = m_dpiy; + if (dpix == 0) dpix = 1; + if (dpiy == 0) dpiy = 1; + double sx = (double)dstRas->getLx() * dpix / (double)srcRas->getLx(); + double sy = (double)dstRas->getLy() * dpiy / (double)srcRas->getLy(); + double sc = std::max(sx, sy); + TAffine aff = TScale(sc / dpix, sc / dpiy) + .place(srcRas->getCenterD(), dstRas->getCenterD()); + + TRop::resample(dstRas, srcRas, aff); #endif } diff --git a/toonz/sources/common/trop/bbox.cpp b/toonz/sources/common/trop/bbox.cpp index c18dcdd..fa05672 100644 --- a/toonz/sources/common/trop/bbox.cpp +++ b/toonz/sources/common/trop/bbox.cpp @@ -2,227 +2,214 @@ #include "trop.h" -namespace -{ +namespace { //------------------------------------------------------------------- template -void computeBBox(TRasterPT ras, TRect &bbox) -{ - bbox = ras->getBounds(); - int lx = ras->getLx(); - int ly = ras->getLy(); - - // se c'e' un pixel opaco in alto a sin e in basso a destra allora bbox = bounds - if (ras->pixels(0)[0].m != 0 && - ras->pixels(ly - 1)[lx - 1].m != 0) - return; - - int y; - ras->lock(); - for (y = 0; y < ly; y++) { - CHANNEL_TYPE *pix = &(ras->pixels(y)->m); - CHANNEL_TYPE *endPix = pix + 4 * lx; - while (pix < endPix && *pix == 0) - pix += 4; - if (pix < endPix) - break; - } - if (y == ly) { - // tutta trasparente - bbox = TRect(); - ras->unlock(); - return; - } - bbox.y0 = y; - for (y = ly - 1; y > bbox.y0; y--) { - CHANNEL_TYPE *pix = &(ras->pixels(y)->m); - CHANNEL_TYPE *endPix = pix + 4 * lx; - while (pix < endPix && *pix == 0) - pix += 4; - if (pix < endPix) - break; - } - bbox.y1 = y; - assert(bbox.y0 <= bbox.y1); - bbox.x0 = lx; - bbox.x1 = -1; - for (y = bbox.y0; y <= bbox.y1; y++) { - CHANNEL_TYPE *row = &(ras->pixels(y)->m); - int x = 0; - for (x = 0; x < bbox.x0 && row[x * 4] == 0; x++) { - } - bbox.x0 = x; - for (x = lx - 1; x > bbox.x1 && row[x * 4] == 0; x--) { - } - bbox.x1 = x; - } - assert(bbox.x0 <= bbox.x1); - - ras->unlock(); - /* - - UCHAR *row_m = &(ras->pixels()->m); - // se c'e' un pixel opaco in alto a sin e in basso a destra allora bbox = bounds - if(row_m[0] && row_m[(ly-1)*wrap4 + (lx-1)*4]) - return; +void computeBBox(TRasterPT ras, TRect &bbox) { + bbox = ras->getBounds(); + int lx = ras->getLx(); + int ly = ras->getLy(); + + // se c'e' un pixel opaco in alto a sin e in basso a destra allora bbox = + // bounds + if (ras->pixels(0)[0].m != 0 && ras->pixels(ly - 1)[lx - 1].m != 0) return; int y; - UCHAR *m, *max_m, *min_m; - - for(y=0;y=ly) - { - // tutta trasparente - return; - } - - bbox.y0 = bbox.y1 = y; - bbox.x0 = (m - row_m)/4; - assert(0<=bbox.x0 && bbox.x0pixels(bbox.y0)[bbox.x0].m>0); - assert(bbox.x0 == 0 || ras->pixels(bbox.y0)[bbox.x0-1].m==0); - - min_m = m; - for(m = max_m - 4;m>min_m && *m==0;m-=4) {} - bbox.x1 = (m - row_m)/4; - assert(0<=bbox.x1 && bbox.x1pixels(bbox.y0)[bbox.x1].m>0); - assert(bbox.x1 == lx-1 || ras->pixels(bbox.y0)[bbox.x1+1].m==0); - - row_m += wrap4; - - for(y++;ypixels(y)[bbox.x0].m>0); - assert(bbox.x0 == 0 || ras->pixels(y)[bbox.x0-1].m==0); + ras->lock(); + for (y = 0; y < ly; y++) { + CHANNEL_TYPE *pix = &(ras->pixels(y)->m); + CHANNEL_TYPE *endPix = pix + 4 * lx; + while (pix < endPix && *pix == 0) pix += 4; + if (pix < endPix) break; + } + if (y == ly) { + // tutta trasparente + bbox = TRect(); + ras->unlock(); + return; + } + bbox.y0 = y; + for (y = ly - 1; y > bbox.y0; y--) { + CHANNEL_TYPE *pix = &(ras->pixels(y)->m); + CHANNEL_TYPE *endPix = pix + 4 * lx; + while (pix < endPix && *pix == 0) pix += 4; + if (pix < endPix) break; + } + bbox.y1 = y; + assert(bbox.y0 <= bbox.y1); + bbox.x0 = lx; + bbox.x1 = -1; + for (y = bbox.y0; y <= bbox.y1; y++) { + CHANNEL_TYPE *row = &(ras->pixels(y)->m); + int x = 0; + for (x = 0; x < bbox.x0 && row[x * 4] == 0; x++) { + } + bbox.x0 = x; + for (x = lx - 1; x > bbox.x1 && row[x * 4] == 0; x--) { + } + bbox.x1 = x; + } + assert(bbox.x0 <= bbox.x1); + + ras->unlock(); + /* + + UCHAR *row_m = &(ras->pixels()->m); +// se c'e' un pixel opaco in alto a sin e in basso a destra allora bbox = bounds +if(row_m[0] && row_m[(ly-1)*wrap4 + (lx-1)*4]) + return; + +int y; +UCHAR *m, *max_m, *min_m; + +for(y=0;y=ly) + { + // tutta trasparente + return; + } + + bbox.y0 = bbox.y1 = y; +bbox.x0 = (m - row_m)/4; +assert(0<=bbox.x0 && bbox.x0pixels(bbox.y0)[bbox.x0].m>0); +assert(bbox.x0 == 0 || ras->pixels(bbox.y0)[bbox.x0-1].m==0); + +min_m = m; +for(m = max_m - 4;m>min_m && *m==0;m-=4) {} +bbox.x1 = (m - row_m)/4; +assert(0<=bbox.x1 && bbox.x1pixels(bbox.y0)[bbox.x1].m>0); +assert(bbox.x1 == lx-1 || ras->pixels(bbox.y0)[bbox.x1+1].m==0); + + row_m += wrap4; + +for(y++;ypixels(y)[bbox.x0].m>0); + assert(bbox.x0 == 0 || ras->pixels(y)[bbox.x0-1].m==0); + } + min_m = row_m + bbox.x1*4; + for(m = max_m - 4;m>min_m && *m==0;m-=4) {} + if(m>min_m) + { + x = (m - row_m)/4; + assert(x>bbox.x1); + bbox.x1 = x; + } + bbox.y1 = y; + } + row_m += wrap4; } - min_m = row_m + bbox.x1*4; - for(m = max_m - 4;m>min_m && *m==0;m-=4) {} - if(m>min_m) - { - x = (m - row_m)/4; - assert(x>bbox.x1); - bbox.x1 = x; - } - bbox.y1 = y; - } - row_m += wrap4; - } */ } //------------------------------------------------------------------- -inline bool isTransparent(TPixelCM32 *pix) -{ - return (!pix->isPureInk() && - // (pix->getPaint()==BackgroundStyle - (pix->getPaint() == 0 && pix->isPurePaint())); +inline bool isTransparent(TPixelCM32 *pix) { + return (!pix->isPureInk() && + // (pix->getPaint()==BackgroundStyle + (pix->getPaint() == 0 && pix->isPurePaint())); } //------------------------------------------------------------------- -void computeBBoxCM32(TRasterCM32P ras, TRect &bbox) -{ - bbox = ras->getBounds(); - int lx = ras->getLx(); - int ly = ras->getLy(); - - // se c'e' un pixel opaco in alto a sin e in basso a destra allora bbox = bounds - if (!isTransparent(&(ras->pixels(0)[0])) && - !isTransparent(&(ras->pixels(ly - 1)[lx - 1]))) - return; - - int y; - ras->lock(); - for (y = 0; y < ly; y++) { - TPixelCM32 *pix = ras->pixels(y); - TPixelCM32 *endPix = pix + lx; - while (pix < endPix && isTransparent(pix)) - ++pix; - if (pix < endPix) - break; - } - if (y == ly) { - // tutta trasparente - bbox = TRect(); - ras->unlock(); - return; - } - bbox.y0 = y; - for (y = ly - 1; y > bbox.y0; y--) { - TPixelCM32 *pix = ras->pixels(y); - TPixelCM32 *endPix = pix + lx; - while (pix < endPix && isTransparent(pix)) - ++pix; - if (pix < endPix) - break; - } - bbox.y1 = y; - assert(bbox.y0 <= bbox.y1); - bbox.x0 = lx; - bbox.x1 = -1; - for (y = bbox.y0; y <= bbox.y1; y++) { - TPixelCM32 *row = ras->pixels(y); - int x = 0; - for (x = 0; x < bbox.x0 && isTransparent(&row[x]); x++) { - } - bbox.x0 = x; - for (x = lx - 1; x > bbox.x1 && isTransparent(&row[x]); x--) { - } - bbox.x1 = x; - } - assert(bbox.x0 <= bbox.x1); - ras->unlock(); +void computeBBoxCM32(TRasterCM32P ras, TRect &bbox) { + bbox = ras->getBounds(); + int lx = ras->getLx(); + int ly = ras->getLy(); + + // se c'e' un pixel opaco in alto a sin e in basso a destra allora bbox = + // bounds + if (!isTransparent(&(ras->pixels(0)[0])) && + !isTransparent(&(ras->pixels(ly - 1)[lx - 1]))) + return; + + int y; + ras->lock(); + for (y = 0; y < ly; y++) { + TPixelCM32 *pix = ras->pixels(y); + TPixelCM32 *endPix = pix + lx; + while (pix < endPix && isTransparent(pix)) ++pix; + if (pix < endPix) break; + } + if (y == ly) { + // tutta trasparente + bbox = TRect(); + ras->unlock(); + return; + } + bbox.y0 = y; + for (y = ly - 1; y > bbox.y0; y--) { + TPixelCM32 *pix = ras->pixels(y); + TPixelCM32 *endPix = pix + lx; + while (pix < endPix && isTransparent(pix)) ++pix; + if (pix < endPix) break; + } + bbox.y1 = y; + assert(bbox.y0 <= bbox.y1); + bbox.x0 = lx; + bbox.x1 = -1; + for (y = bbox.y0; y <= bbox.y1; y++) { + TPixelCM32 *row = ras->pixels(y); + int x = 0; + for (x = 0; x < bbox.x0 && isTransparent(&row[x]); x++) { + } + bbox.x0 = x; + for (x = lx - 1; x > bbox.x1 && isTransparent(&row[x]); x--) { + } + bbox.x1 = x; + } + assert(bbox.x0 <= bbox.x1); + ras->unlock(); } //------------------------------------------------------------------- -} //namespace +} // namespace //------------------------------------------------------------------- -void TRop::computeBBox(TRasterP ras, TRect &bbox) -{ - TRaster32P ras32 = ras; - if (ras32) { - ::computeBBox(ras32, bbox); - return; - } - - TRaster64P ras64 = ras; - if (ras64) { - ::computeBBox(ras64, bbox); - return; - } - - TRasterCM32P rasCM32 = ras; - if (rasCM32) { - computeBBoxCM32(rasCM32, bbox); - return; - } - - TRasterGR8P ras8 = ras; - if (ras8) { - bbox = ras->getBounds(); - return; - } - assert(0); +void TRop::computeBBox(TRasterP ras, TRect &bbox) { + TRaster32P ras32 = ras; + if (ras32) { + ::computeBBox(ras32, bbox); + return; + } + + TRaster64P ras64 = ras; + if (ras64) { + ::computeBBox(ras64, bbox); + return; + } + + TRasterCM32P rasCM32 = ras; + if (rasCM32) { + computeBBoxCM32(rasCM32, bbox); + return; + } + + TRasterGR8P ras8 = ras; + if (ras8) { + bbox = ras->getBounds(); + return; + } + assert(0); } diff --git a/toonz/sources/common/trop/borders_extractor.h b/toonz/sources/common/trop/borders_extractor.h index ba2dead..87d64b5 100644 --- a/toonz/sources/common/trop/borders_extractor.h +++ b/toonz/sources/common/trop/borders_extractor.h @@ -8,10 +8,8 @@ #include "raster_edge_iterator.h" -namespace TRop -{ -namespace borders -{ +namespace TRop { +namespace borders { //******************************************************************* // Pixel Selector model @@ -37,61 +35,67 @@ namespace borders completely transparent (virtual pixels outside the raster boundaries are). */ template -class pixel_selector -{ +class pixel_selector { public: - typedef Pix pixel_type; //!< The pixel type naming the selector - typedef Val value_type; //!< A value type representing pixel contents. - //!< Typically the pixel itself. + typedef Pix pixel_type; //!< The pixel type naming the selector + typedef Val value_type; //!< A value type representing pixel contents. + //!< Typically the pixel itself. public: - value_type value(const pixel_type &pix) const; - bool equal(const pixel_type &a, const pixel_type &b) const - { - return value(a) == value(b); - } - - value_type transparent() const; - bool transparent(const pixel_type &pix) const - { - return value(pix) == transparent(); - } - - //! Returns whether a border point must be read or not (corners are always read). - bool skip(const value_type &prevLeftValue, const value_type &leftValue) const { return true; } + value_type value(const pixel_type &pix) const; + bool equal(const pixel_type &a, const pixel_type &b) const { + return value(a) == value(b); + } + + value_type transparent() const; + bool transparent(const pixel_type &pix) const { + return value(pix) == transparent(); + } + + //! Returns whether a border point must be read or not (corners are always + //! read). + bool skip(const value_type &prevLeftValue, + const value_type &leftValue) const { + return true; + } }; //---------------------------------------------------------------------------------- -enum RunType { _BORDER_LEFT = 0x20, - _BORDER_RIGHT = 0x10, - _HIERARCHY_INCREASE = 0x8, - _HIERARCHY_DECREASE = 0x4 }; +enum RunType { + _BORDER_LEFT = 0x20, + _BORDER_RIGHT = 0x10, + _HIERARCHY_INCREASE = 0x8, + _HIERARCHY_DECREASE = 0x4 +}; //---------------------------------------------------------------------------------- /*! Reads the borders of the input raster, according to the specified selector. - Outputs the borders by supplying a container reader with the raster edge iterators + Outputs the borders by supplying a container reader with the raster edge + iterators corresponding to border vertices. The runsmap used in the process can be returned in output. */ template void readBorders(const TRasterPT &raster, const PixelSelector &selector, - ContainerReader &reader, RunsMapP *rasterRunsMap = 0); + ContainerReader &reader, RunsMapP *rasterRunsMap = 0); //===================================================================================== template -void readMeshes(const TRasterPT &raster, const PixelSelector &selector, - ContainersReader &meshesDataReader, RunsMapP *rasterRunsMap = 0); +void readMeshes(const TRasterPT &raster, + const PixelSelector &selector, + ContainersReader &meshesDataReader, + RunsMapP *rasterRunsMap = 0); } -} //namespace TRop::borders +} // namespace TRop::borders -#endif //BORDERS_EXTRACTOR_H +#endif // BORDERS_EXTRACTOR_H //===================================================================================== #ifdef INCLUDE_HPP #include "borders_extractor.hpp" -#endif //INCLUDE_HPP +#endif // INCLUDE_HPP diff --git a/toonz/sources/common/trop/borders_extractor.hpp b/toonz/sources/common/trop/borders_extractor.hpp index d258b62..74549bc 100644 --- a/toonz/sources/common/trop/borders_extractor.hpp +++ b/toonz/sources/common/trop/borders_extractor.hpp @@ -3,10 +3,10 @@ #ifndef BORDERS_EXTRACTOR_HPP #define BORDERS_EXTRACTOR_HPP -//Toonz includes +// Toonz includes #include "raster_edge_iterator.h" -//tcg includes +// tcg includes #include "tcg/tcg_traits.h" #include "tcg/tcg_containers_reader.h" #include "tcg/tcg_hash.h" @@ -14,184 +14,188 @@ #include "borders_extractor.h" -namespace TRop -{ -namespace borders -{ +namespace TRop { +namespace borders { //********************************************************************************************************* // Private stuff //********************************************************************************************************* template -class _DummyReader -{ +class _DummyReader { public: - void openContainer(const RasterEdgeIterator &) {} - void addElement(const RasterEdgeIterator &) {} - void closeContainer() {} + void openContainer(const RasterEdgeIterator &) {} + void addElement(const RasterEdgeIterator &) {} + void closeContainer() {} }; //********************************************************************************************************* // Borders Extraction procedure //********************************************************************************************************* -inline void _signEdge(RunsMapP &runsMap, int x, int y0, int y1, UCHAR increasingSign, UCHAR decreasingSign) -{ - for (; y0 < y1; ++y0) - runsMap->runHeader(x, y0) |= increasingSign; - - if (y0 > y1) { - --x; - do { - --y0; - runsMap->runHeader(x, y0) |= decreasingSign; - } while (y0 > y1); - } +inline void _signEdge(RunsMapP &runsMap, int x, int y0, int y1, + UCHAR increasingSign, UCHAR decreasingSign) { + for (; y0 < y1; ++y0) runsMap->runHeader(x, y0) |= increasingSign; + + if (y0 > y1) { + --x; + do { + --y0; + runsMap->runHeader(x, y0) |= decreasingSign; + } while (y0 > y1); + } } //--------------------------------------------------------------------------------------------- template void _readBorder(const TRasterPT &rin, const PixelSelector &selector, - RunsMapP &runsMap, int x, int y, bool counter, ContainerReader &reader) -{ - typedef typename PixelSelector::value_type value_type; + RunsMapP &runsMap, int x, int y, bool counter, + ContainerReader &reader) { + typedef typename PixelSelector::value_type value_type; - UCHAR increasingSign = _BORDER_LEFT, decreasingSign = _BORDER_RIGHT; - if (!counter) - increasingSign |= _HIERARCHY_INCREASE, decreasingSign |= _HIERARCHY_DECREASE; + UCHAR increasingSign = _BORDER_LEFT, decreasingSign = _BORDER_RIGHT; + if (!counter) + increasingSign |= _HIERARCHY_INCREASE, + decreasingSign |= _HIERARCHY_DECREASE; - //First, read the border entirely, while erasing the border from - //the runsMap. - RasterEdgeIterator it(rin, selector, TPoint(x, y), counter ? TPoint(1, 0) : TPoint(0, 1)); - //++it; //As we could be in the middle of a straight edge, increment to get a corner + // First, read the border entirely, while erasing the border from + // the runsMap. + RasterEdgeIterator it(rin, selector, TPoint(x, y), + counter ? TPoint(1, 0) : TPoint(0, 1)); + //++it; //As we could be in the middle of a straight edge, increment to get + //a corner - TPoint start(it.pos()), startDir(it.dir()); - reader.openContainer(it); + TPoint start(it.pos()), startDir(it.dir()); + reader.openContainer(it); - TPoint oldPos(start); - for (++it; it.pos() != start || it.dir() != startDir; ++it) { - const TPoint &currPos(it.pos()); - reader.addElement(it); + TPoint oldPos(start); + for (++it; it.pos() != start || it.dir() != startDir; ++it) { + const TPoint &currPos(it.pos()); + reader.addElement(it); - //Sign the corresponding (vertical) edge - _signEdge(runsMap, oldPos.x, oldPos.y, currPos.y, increasingSign, decreasingSign); + // Sign the corresponding (vertical) edge + _signEdge(runsMap, oldPos.x, oldPos.y, currPos.y, increasingSign, + decreasingSign); - oldPos = currPos; - } + oldPos = currPos; + } - _signEdge(runsMap, oldPos.x, oldPos.y, it.pos().y, increasingSign, decreasingSign); + _signEdge(runsMap, oldPos.x, oldPos.y, it.pos().y, increasingSign, + decreasingSign); - reader.closeContainer(); + reader.closeContainer(); } //--------------------------------------------------------------------------------------------- template void readBorders(const TRasterPT &rin, const PixelSelector &selector, - ContainerReader &reader, RunsMapP *rasterRunsMap) -{ - typedef TRasterPT RasterTypeP; - typedef _DummyReader DummyReader; - - //First, extract the run-length representation for rin - RunsMapP runsMap; - if (rasterRunsMap && *rasterRunsMap) { - //If it was supplied, use it - runsMap = *rasterRunsMap; - runsMap->lock(); - } else { - //In case, build it anew - runsMap = RunsMapP(rin->getLx(), rin->getLy()); - - runsMap->lock(); - buildRunsMap(runsMap, rin, selector); - } - - if (rasterRunsMap) - //Return the runsMap if requested - *rasterRunsMap = runsMap; - - //Build a fake reader for internal borders - DummyReader dummyReader; - - //Now, use it to extract borders - iterate through runs and, whenever - //one is found with opaque color (ie not transparent), extract its - //associated border. The border is erased internally after the read. - int lx = rin->getLx(), ly = rin->getLy(); - - int hierarchyLevel = 0; - - int x, y; - for (y = 0; y < ly; ++y) { - Pixel *lineStart = rin->pixels(y), *pix; - TPixelGR8 *runsStart = runsMap->pixels(y), *run; - - UCHAR nextHeader, prevHeader = 0; - for (x = 0, pix = lineStart, run = runsStart; x < lx;) { - nextHeader = run->value; - - if (hierarchyLevel) { - if (prevHeader & _BORDER_RIGHT) { - if (prevHeader & _HIERARCHY_DECREASE) - --hierarchyLevel; - } else //Every right border in a region should be signed. Do so now. - _readBorder(rin, selector, runsMap, x, y, true, dummyReader); - } - - if (hierarchyLevel) { - if (nextHeader & _BORDER_LEFT) { - if (nextHeader & _HIERARCHY_INCREASE) - ++hierarchyLevel; - } else { - ++hierarchyLevel; - _readBorder(rin, selector, runsMap, x, y, false, reader); - } - } else { - if (!(selector.transparent(*pix))) //External transparent region - do not extract - { - ++hierarchyLevel; - if (!(nextHeader & _BORDER_LEFT)) - _readBorder(rin, selector, runsMap, x, y, false, reader); - } - } - - //Increment variables - x += runsMap->runLength(x, y), pix = lineStart + x, run = runsStart + x; - prevHeader = (run - 1)->value; - } - - assert(x == lx); - - if (hierarchyLevel) { - assert((prevHeader & _BORDER_RIGHT) && (prevHeader & _HIERARCHY_DECREASE)); - --hierarchyLevel; - } - - assert(!hierarchyLevel); - } - - runsMap->unlock(); + ContainerReader &reader, RunsMapP *rasterRunsMap) { + typedef TRasterPT RasterTypeP; + typedef _DummyReader DummyReader; + + // First, extract the run-length representation for rin + RunsMapP runsMap; + if (rasterRunsMap && *rasterRunsMap) { + // If it was supplied, use it + runsMap = *rasterRunsMap; + runsMap->lock(); + } else { + // In case, build it anew + runsMap = RunsMapP(rin->getLx(), rin->getLy()); + + runsMap->lock(); + buildRunsMap(runsMap, rin, selector); + } + + if (rasterRunsMap) + // Return the runsMap if requested + *rasterRunsMap = runsMap; + + // Build a fake reader for internal borders + DummyReader dummyReader; + + // Now, use it to extract borders - iterate through runs and, whenever + // one is found with opaque color (ie not transparent), extract its + // associated border. The border is erased internally after the read. + int lx = rin->getLx(), ly = rin->getLy(); + + int hierarchyLevel = 0; + + int x, y; + for (y = 0; y < ly; ++y) { + Pixel *lineStart = rin->pixels(y), *pix; + TPixelGR8 *runsStart = runsMap->pixels(y), *run; + + UCHAR nextHeader, prevHeader = 0; + for (x = 0, pix = lineStart, run = runsStart; x < lx;) { + nextHeader = run->value; + + if (hierarchyLevel) { + if (prevHeader & _BORDER_RIGHT) { + if (prevHeader & _HIERARCHY_DECREASE) --hierarchyLevel; + } else // Every right border in a region should be signed. Do so now. + _readBorder(rin, selector, runsMap, x, y, true, dummyReader); + } + + if (hierarchyLevel) { + if (nextHeader & _BORDER_LEFT) { + if (nextHeader & _HIERARCHY_INCREASE) ++hierarchyLevel; + } else { + ++hierarchyLevel; + _readBorder(rin, selector, runsMap, x, y, false, reader); + } + } else { + if (!(selector.transparent( + *pix))) // External transparent region - do not extract + { + ++hierarchyLevel; + if (!(nextHeader & _BORDER_LEFT)) + _readBorder(rin, selector, runsMap, x, y, false, reader); + } + } + + // Increment variables + x += runsMap->runLength(x, y), pix = lineStart + x, run = runsStart + x; + prevHeader = (run - 1)->value; + } + + assert(x == lx); + + if (hierarchyLevel) { + assert((prevHeader & _BORDER_RIGHT) && + (prevHeader & _HIERARCHY_DECREASE)); + --hierarchyLevel; + } + + assert(!hierarchyLevel); + } + + runsMap->unlock(); } //********************************************************************************************************* // New Mesh Extraction procedure //********************************************************************************************************* -enum { _PROCESSED = 0x1, - _HIERARCHY_UP = 0x2, - _HIERARCHY_DN = 0x4, - _PROCESSED_AND_HIERARCHY_UP = (_PROCESSED | _HIERARCHY_UP) }; +enum { + _PROCESSED = 0x1, + _HIERARCHY_UP = 0x2, + _HIERARCHY_DN = 0x4, + _PROCESSED_AND_HIERARCHY_UP = (_PROCESSED | _HIERARCHY_UP) +}; //------------------------------------------------------------------- template -inline bool _isVertex(const RasterEdgeIter &it, const typename RasterEdgeIter::value_type &oldOtherColor) -{ - return (it.otherColor() != oldOtherColor) || - (it.turn() == it.adherence() && (!(it.turn() & RasterEdgeIter::AMBIGUOUS)) && - it.elbowColor() != oldOtherColor); +inline bool _isVertex( + const RasterEdgeIter &it, + const typename RasterEdgeIter::value_type &oldOtherColor) { + return (it.otherColor() != oldOtherColor) || + (it.turn() == it.adherence() && + (!(it.turn() & RasterEdgeIter::AMBIGUOUS)) && + it.elbowColor() != oldOtherColor); } //------------------------------------------------------------------- @@ -202,341 +206,365 @@ inline size_t _pointHash(const TPoint &point) { return point.x ^ point.y; } template struct _ExternalEdgeSigner { - static inline void signAndIncrement(RunsMapP &runsMap, RasterEdgeIter &it) - { - if (it.dir().y > 0) { - TPoint pos = it.pos(); - int newY = (++it).pos().y; - - for (; pos.y != newY; ++pos.y) - runsMap->runHeader(pos.x, pos.y) |= _PROCESSED_AND_HIERARCHY_UP; - } else if (it.dir().y < 0) { - TPoint pos = it.pos(); - int newY = (++it).pos().y; - - TPixelGR8 *pix = runsMap->pixels(pos.y - 1) + pos.x; - - for (; pos.y != newY; --pos.y, --pix) { - pix->value |= _PROCESSED; - (--pix)->value |= _HIERARCHY_DN; - } - } else - ++it; - } + static inline void signAndIncrement(RunsMapP &runsMap, RasterEdgeIter &it) { + if (it.dir().y > 0) { + TPoint pos = it.pos(); + int newY = (++it).pos().y; + + for (; pos.y != newY; ++pos.y) + runsMap->runHeader(pos.x, pos.y) |= _PROCESSED_AND_HIERARCHY_UP; + } else if (it.dir().y < 0) { + TPoint pos = it.pos(); + int newY = (++it).pos().y; + + TPixelGR8 *pix = runsMap->pixels(pos.y - 1) + pos.x; + + for (; pos.y != newY; --pos.y, --pix) { + pix->value |= _PROCESSED; + (--pix)->value |= _HIERARCHY_DN; + } + } else + ++it; + } }; //------------------------------------------------------------------- template struct _InternalEdgeSigner { - static inline void signAndIncrement(RunsMapP &runsMap, RasterEdgeIter &it) - { - if (it.dir().y) { - TPoint pos = it.pos(); - int newY = (++it).pos().y; - int dir = it.dir().y; - - TPixelGR8 *pix = runsMap->pixels((it.dir().y > 0) ? pos.y : pos.y - 1) + pos.x; - - for (; pos.y != newY; pos.y += dir, pix += dir) { - pix->value |= _PROCESSED_AND_HIERARCHY_UP; - (--pix)->value |= _HIERARCHY_DN; - } - } else - ++it; - } + static inline void signAndIncrement(RunsMapP &runsMap, RasterEdgeIter &it) { + if (it.dir().y) { + TPoint pos = it.pos(); + int newY = (++it).pos().y; + int dir = it.dir().y; + + TPixelGR8 *pix = + runsMap->pixels((it.dir().y > 0) ? pos.y : pos.y - 1) + pos.x; + + for (; pos.y != newY; pos.y += dir, pix += dir) { + pix->value |= _PROCESSED_AND_HIERARCHY_UP; + (--pix)->value |= _HIERARCHY_DN; + } + } else + ++it; + } }; //------------------------------------------------------------------- -template +template int _readEdge(RasterEdgeIter &it, const RasterEdgeIter &end, RunsMapP runsMap, - int &vIdx, Mesh &mesh, tcg::hash &pointsHash, ContainersReader &reader) -{ - typedef tcg::container_reader_traits edge_output; + int &vIdx, Mesh &mesh, tcg::hash &pointsHash, + ContainersReader &reader) { + typedef tcg::container_reader_traits + edge_output; - typename Mesh::edge_type ed; + typename Mesh::edge_type ed; - ed.addVertex(vIdx); - ed.direction(0) = it.dir(); + ed.addVertex(vIdx); + ed.direction(0) = it.dir(); - edge_output::openContainer(reader, it); + edge_output::openContainer(reader, it); - typename RasterEdgeIter::value_type oldOtherColor = it.otherColor(); - do { - EdgeSigner::signAndIncrement(runsMap, it); - edge_output::addElement(reader, it); + typename RasterEdgeIter::value_type oldOtherColor = it.otherColor(); + do { + EdgeSigner::signAndIncrement(runsMap, it); + edge_output::addElement(reader, it); - } while ((it != end) && !_isVertex(it, oldOtherColor)); + } while ((it != end) && !_isVertex(it, oldOtherColor)); - // Identify the newly found vertex. If it's a brand new one, add it - tcg::hash::iterator ht = pointsHash.find(it.pos()); - vIdx = (ht == pointsHash.end()) ? pointsHash[it.pos()] = mesh.addVertex(typename Mesh::vertex_type(it.pos())) : ht.m_idx; + // Identify the newly found vertex. If it's a brand new one, add it + tcg::hash::iterator ht = pointsHash.find(it.pos()); + vIdx = (ht == pointsHash.end()) + ? pointsHash[it.pos()] = + mesh.addVertex(typename Mesh::vertex_type(it.pos())) + : ht.m_idx; - ed.addVertex(vIdx); - ed.direction(1) = (it.turn() == RasterEdgeIter::STRAIGHT) ? -it.dir() : (it.turn() == RasterEdgeIter::LEFT) ? tcg::point_ops::ortLeft(it.dir()) : tcg::point_ops::ortRight(it.dir()); + ed.addVertex(vIdx); + ed.direction(1) = (it.turn() == RasterEdgeIter::STRAIGHT) + ? -it.dir() + : (it.turn() == RasterEdgeIter::LEFT) + ? tcg::point_ops::ortLeft(it.dir()) + : tcg::point_ops::ortRight(it.dir()); - int eIdx = mesh.addEdge(ed); - edge_output::closeContainer(reader, &mesh, eIdx); + int eIdx = mesh.addEdge(ed); + edge_output::closeContainer(reader, &mesh, eIdx); - return eIdx; + return eIdx; } //--------------------------------------------------------------------------------------------- template -void _readMeshes(const RasterEdgeIter &begin, RunsMapP &runsMap, ContainersReader &reader) -{ - typedef tcg::container_reader_traits face_output; +void _readMeshes(const RasterEdgeIter &begin, RunsMapP &runsMap, + ContainersReader &reader) { + typedef tcg::container_reader_traits + face_output; - // Iterate it clockwise. Process lines with vertical displacement. In each line, search - // for unprocessed raster edges. + // Iterate it clockwise. Process lines with vertical displacement. In each + // line, search + // for unprocessed raster edges. - // Use hierarchy signs in the runsMap to understand the search scope in this sub-region. - int hierarchyLevel = 0; + // Use hierarchy signs in the runsMap to understand the search scope in this + // sub-region. + int hierarchyLevel = 0; - RasterEdgeIter it(begin); - do { - if (it.dir().y > 0) { - // Process line - TPoint pos = it.pos(); - const TPixelGR8 *pix = runsMap->pixels(pos.y) + pos.x; + RasterEdgeIter it(begin); + do { + if (it.dir().y > 0) { + // Process line + TPoint pos = it.pos(); + const TPixelGR8 *pix = runsMap->pixels(pos.y) + pos.x; - hierarchyLevel = 0; - assert((pix->value & _PROCESSED) && (pix->value & _HIERARCHY_UP)); + hierarchyLevel = 0; + assert((pix->value & _PROCESSED) && (pix->value & _HIERARCHY_UP)); - do { - // Iterate through the line. Extract a mesh each time an unprocessed raster edge is found. - if (!(pix->value & _PROCESSED)) { - assert(hierarchyLevel == 1); + do { + // Iterate through the line. Extract a mesh each time an unprocessed + // raster edge is found. + if (!(pix->value & _PROCESSED)) { + assert(hierarchyLevel == 1); - Mesh *meshPtr = new Mesh; - _readMesh(it.raster(), it.selector(), runsMap, pos.x, pos.y, *meshPtr, reader); + Mesh *meshPtr = new Mesh; + _readMesh(it.raster(), it.selector(), runsMap, pos.x, pos.y, *meshPtr, + reader); - face_output::addElement(reader, meshPtr); - } + face_output::addElement(reader, meshPtr); + } - if (pix->value & _HIERARCHY_UP) - ++hierarchyLevel; + if (pix->value & _HIERARCHY_UP) ++hierarchyLevel; - TUINT32 l = runsMap->runLength(pos.x, pos.y); - pos.x += l; - pix += l; + TUINT32 l = runsMap->runLength(pos.x, pos.y); + pos.x += l; + pix += l; - if ((pix - 1)->value & _HIERARCHY_DN) - --hierarchyLevel; + if ((pix - 1)->value & _HIERARCHY_DN) --hierarchyLevel; - } while (hierarchyLevel > 0); - } + } while (hierarchyLevel > 0); + } - ++it; + ++it; - } while (it != begin); + } while (it != begin); } //------------------------------------------------------------------- template -void _readBorder(const RasterEdgeIter &begin, RunsMapP runsMap, - int vIdx, Mesh &mesh, tcg::hash &pointsHash, - ContainersReader &reader) -{ - typedef typename Mesh::face_type face_type; - typedef typename Mesh::edge_type edge_type; - typedef tcg::container_reader_traits face_output; - - // As long as we don't get back to the initial iterator, extract edges - RasterEdgeIter it(begin); - - // Create the face to be extracted at the right of processed border, and add it to - // the mesh. Observe that insertion is made manually in the mesh's faces list. - // This prevents the mesh from automatically link edges to the face. - face_type fc; - - do { - // Retrieve current vertex - typename Mesh::vertex_type &vx = mesh.vertex(vIdx); - - // Search in it the edge corresponding to current iterating direction - int e, edgesCount = vx.edgesCount(), eIdx = -1, side = -1; - for (e = 0; e < edgesCount; ++e) { - edge_type &ed = mesh.edge(vx.edge(e)); - side = ed.vertex(0) == vIdx ? 0 : 1; - - if (ed.direction(side) == it.dir()) { - eIdx = ed.getIndex(); - break; - } - } - - if (e == edgesCount) { - // In case the edge was not found, it needs to be extracted now. - eIdx = _readEdge>( - it, begin, runsMap, vIdx, mesh, pointsHash, reader); - } else { - // The edge was already extracted. We just need to update the iterator then. - const edge_type &ed = mesh.edge(eIdx); - - vIdx = ed.vertex(1 - side); - const TPoint &oppositePos = mesh.vertex(vIdx).P(); - const TPoint &oppositeDir = ed.direction(1 - side); - - // We need to perform the last ++it in the already extracted edge since we need - // to give it the incoming direction. - it.setEdge(oppositePos + oppositeDir, -oppositeDir), ++it; - } - - fc.addEdge(eIdx); - - } while (it != begin); - - // The face has now been described (from the mesh viewpoint). Add it to the mesh. - int fIdx = mesh.addFace(fc); - - // We still need to extract its sub-meshes content now. - face_output::openContainer(reader, &mesh, fIdx, begin.rightColor()); - - _readMeshes(begin, runsMap, reader); - - face_output::closeContainer(reader); +void _readBorder(const RasterEdgeIter &begin, RunsMapP runsMap, int vIdx, + Mesh &mesh, tcg::hash &pointsHash, + ContainersReader &reader) { + typedef typename Mesh::face_type face_type; + typedef typename Mesh::edge_type edge_type; + typedef tcg::container_reader_traits + face_output; + + // As long as we don't get back to the initial iterator, extract edges + RasterEdgeIter it(begin); + + // Create the face to be extracted at the right of processed border, and add + // it to + // the mesh. Observe that insertion is made manually in the mesh's faces list. + // This prevents the mesh from automatically link edges to the face. + face_type fc; + + do { + // Retrieve current vertex + typename Mesh::vertex_type &vx = mesh.vertex(vIdx); + + // Search in it the edge corresponding to current iterating direction + int e, edgesCount = vx.edgesCount(), eIdx = -1, side = -1; + for (e = 0; e < edgesCount; ++e) { + edge_type &ed = mesh.edge(vx.edge(e)); + side = ed.vertex(0) == vIdx ? 0 : 1; + + if (ed.direction(side) == it.dir()) { + eIdx = ed.getIndex(); + break; + } + } + + if (e == edgesCount) { + // In case the edge was not found, it needs to be extracted now. + eIdx = _readEdge>( + it, begin, runsMap, vIdx, mesh, pointsHash, reader); + } else { + // The edge was already extracted. We just need to update the iterator + // then. + const edge_type &ed = mesh.edge(eIdx); + + vIdx = ed.vertex(1 - side); + const TPoint &oppositePos = mesh.vertex(vIdx).P(); + const TPoint &oppositeDir = ed.direction(1 - side); + + // We need to perform the last ++it in the already extracted edge since we + // need + // to give it the incoming direction. + it.setEdge(oppositePos + oppositeDir, -oppositeDir), ++it; + } + + fc.addEdge(eIdx); + + } while (it != begin); + + // The face has now been described (from the mesh viewpoint). Add it to the + // mesh. + int fIdx = mesh.addFace(fc); + + // We still need to extract its sub-meshes content now. + face_output::openContainer(reader, &mesh, fIdx, begin.rightColor()); + + _readMeshes(begin, runsMap, reader); + + face_output::closeContainer(reader); } //------------------------------------------------------------------- template void _readMesh(const TRasterPT &rin, - const PixelSelector &selector, RunsMapP &runsMap, int x, int y, - Mesh &mesh, ContainersReader &reader) -{ - typedef typename Mesh::vertex_type vertex_type; - typedef typename Mesh::edge_type edge_type; - typedef tcg::container_reader_traits edge_output; - typedef typename PixelSelector::value_type value_type; - typedef RasterEdgeIterator raster_edge_iterator; - - // Iterate silently until a vertex is encountered (or until the initial point is found) - raster_edge_iterator it(rin, selector, TPoint(x, y), TPoint(0, 1)), begin(it); - it.setAdherence(raster_edge_iterator::LEFT); - - value_type beginColor = begin.rightColor(); - for (++it; it != begin && !_isVertex(it, beginColor); ++it) - ; - - // Use a hash to keep track of found vertices - tcg::hash pointsHash(&_pointHash); - - int vIdx = pointsHash[it.pos()] = mesh.addVertex(it.pos()); - - // The outer edges are extracted first in clockwise orientation. - begin = it; - do { - _readEdge>( - it, begin, runsMap, vIdx, mesh, pointsHash, reader); - - } while (it != begin); - - // Then, their associated faces are extracted. - it.setAdherence(raster_edge_iterator::RIGHT); - - int e, outerEdgesCount = mesh.edgesCount(); - for (e = 0; e < outerEdgesCount; ++e) { - const edge_type &ed = mesh.edge(e); - if (ed.face(0) < 0) { - vIdx = ed.vertex(0); - const vertex_type &vx = mesh.vertex(vIdx); - - it.setEdge(vx.P(), ed.direction(0)); - _readBorder(it, runsMap, vIdx, mesh, pointsHash, reader); - } - } - - // Edges following those must have either side associated with a face. - // Which must be extracted too. - for (e = outerEdgesCount; e < mesh.edgesCount(); ++e) { - const edge_type &ed = mesh.edge(e); - if (ed.face(1) < 0) { - vIdx = ed.vertex(1); - const vertex_type &vx = mesh.vertex(vIdx); - - it.setEdge(vx.P(), ed.direction(1)); - _readBorder(it, runsMap, vIdx, mesh, pointsHash, reader); - } - } + const PixelSelector &selector, RunsMapP &runsMap, int x, int y, + Mesh &mesh, ContainersReader &reader) { + typedef typename Mesh::vertex_type vertex_type; + typedef typename Mesh::edge_type edge_type; + typedef tcg::container_reader_traits edge_output; + typedef typename PixelSelector::value_type value_type; + typedef RasterEdgeIterator raster_edge_iterator; + + // Iterate silently until a vertex is encountered (or until the initial point + // is found) + raster_edge_iterator it(rin, selector, TPoint(x, y), TPoint(0, 1)), begin(it); + it.setAdherence(raster_edge_iterator::LEFT); + + value_type beginColor = begin.rightColor(); + for (++it; it != begin && !_isVertex(it, beginColor); ++it) + ; + + // Use a hash to keep track of found vertices + tcg::hash pointsHash(&_pointHash); + + int vIdx = pointsHash[it.pos()] = mesh.addVertex(it.pos()); + + // The outer edges are extracted first in clockwise orientation. + begin = it; + do { + _readEdge>( + it, begin, runsMap, vIdx, mesh, pointsHash, reader); + + } while (it != begin); + + // Then, their associated faces are extracted. + it.setAdherence(raster_edge_iterator::RIGHT); + + int e, outerEdgesCount = mesh.edgesCount(); + for (e = 0; e < outerEdgesCount; ++e) { + const edge_type &ed = mesh.edge(e); + if (ed.face(0) < 0) { + vIdx = ed.vertex(0); + const vertex_type &vx = mesh.vertex(vIdx); + + it.setEdge(vx.P(), ed.direction(0)); + _readBorder(it, runsMap, vIdx, mesh, pointsHash, reader); + } + } + + // Edges following those must have either side associated with a face. + // Which must be extracted too. + for (e = outerEdgesCount; e < mesh.edgesCount(); ++e) { + const edge_type &ed = mesh.edge(e); + if (ed.face(1) < 0) { + vIdx = ed.vertex(1); + const vertex_type &vx = mesh.vertex(vIdx); + + it.setEdge(vx.P(), ed.direction(1)); + _readBorder(it, runsMap, vIdx, mesh, pointsHash, reader); + } + } } //--------------------------------------------------------------------------------------------- template -void readMeshes(const TRasterPT &rin, const PixelSelector &selector, - ContainersReader &reader, RunsMapP *rasterRunsMap) -{ - typedef typename PixelSelector::pixel_type pixel_type; - typedef TRasterPT RasterTypeP; - typedef Mesh mesh_type; - typedef tcg::container_reader_traits face_output; - - // First, extract the run-length representation for rin - RunsMapP runsMap; - if (rasterRunsMap && *rasterRunsMap) { - // If a runsmap was supplied, use it - runsMap = *rasterRunsMap; - runsMap->lock(); - - assert((runsMap->getLx() == rin->getLx() + 1) && (runsMap->getLy() == rin->getLy())); - } else { - // In case, build it anew - runsMap = RunsMapP(rin->getLx() + 1, rin->getLy()); - - // Observe the +1 on the x-axis. One additional pixel is currently required on the right - // side of the runsmap - for ease of use in the algorithm. - - runsMap->lock(); - buildRunsMap(runsMap, rin, selector); - } - - if (rasterRunsMap) - // Return the runsMap if requested - *rasterRunsMap = runsMap; - - face_output::openContainer(reader, 0, -1, selector.transparent()); - - // Now, use it to extract borders - iterate through runs and, whenever - // one is found with opaque color (ie not transparent), extract its - // associated border. The border is erased internally after the read. - int lx = rin->getLx(), ly = rin->getLy(); - - int x, y; - for (y = 0; y < ly; ++y) { - // Process each row - - pixel_type *lineStart = rin->pixels(y), *pix; - TPixelGR8 *runsStart = runsMap->pixels(y), *run; - - UCHAR nextHeader, prevHeader = 0; - for (x = 0, pix = lineStart, run = runsStart; x < lx;) { - nextHeader = run->value; - - if (!(selector.transparent(*pix) || nextHeader & _PROCESSED)) { - mesh_type *meshPtr = new mesh_type; - - // Read the mesh. All its internal sub-meshes are read as well. - _readMesh(rin, selector, runsMap, x, y, *meshPtr, reader); - face_output::addElement(reader, meshPtr); - } - - //Increment variables - x += runsMap->runLength(x, y), pix = lineStart + x, run = runsStart + x; - prevHeader = (run - 1)->value; - } - - assert(x == lx); - } - - face_output::closeContainer(reader); - - runsMap->unlock(); +void readMeshes(const TRasterPT &rin, + const PixelSelector &selector, ContainersReader &reader, + RunsMapP *rasterRunsMap) { + typedef typename PixelSelector::pixel_type pixel_type; + typedef TRasterPT RasterTypeP; + typedef Mesh mesh_type; + typedef tcg::container_reader_traits + face_output; + + // First, extract the run-length representation for rin + RunsMapP runsMap; + if (rasterRunsMap && *rasterRunsMap) { + // If a runsmap was supplied, use it + runsMap = *rasterRunsMap; + runsMap->lock(); + + assert((runsMap->getLx() == rin->getLx() + 1) && + (runsMap->getLy() == rin->getLy())); + } else { + // In case, build it anew + runsMap = RunsMapP(rin->getLx() + 1, rin->getLy()); + + // Observe the +1 on the x-axis. One additional pixel is currently required + // on the right + // side of the runsmap - for ease of use in the algorithm. + + runsMap->lock(); + buildRunsMap(runsMap, rin, selector); + } + + if (rasterRunsMap) + // Return the runsMap if requested + *rasterRunsMap = runsMap; + + face_output::openContainer(reader, 0, -1, selector.transparent()); + + // Now, use it to extract borders - iterate through runs and, whenever + // one is found with opaque color (ie not transparent), extract its + // associated border. The border is erased internally after the read. + int lx = rin->getLx(), ly = rin->getLy(); + + int x, y; + for (y = 0; y < ly; ++y) { + // Process each row + + pixel_type *lineStart = rin->pixels(y), *pix; + TPixelGR8 *runsStart = runsMap->pixels(y), *run; + + UCHAR nextHeader, prevHeader = 0; + for (x = 0, pix = lineStart, run = runsStart; x < lx;) { + nextHeader = run->value; + + if (!(selector.transparent(*pix) || nextHeader & _PROCESSED)) { + mesh_type *meshPtr = new mesh_type; + + // Read the mesh. All its internal sub-meshes are read as well. + _readMesh(rin, selector, runsMap, x, y, *meshPtr, reader); + face_output::addElement(reader, meshPtr); + } + + // Increment variables + x += runsMap->runLength(x, y), pix = lineStart + x, run = runsStart + x; + prevHeader = (run - 1)->value; + } + + assert(x == lx); + } + + face_output::closeContainer(reader); + + runsMap->unlock(); } } -} //namespace TRop::borders +} // namespace TRop::borders -#endif //BORDERS_EXTRACTOR_HPP +#endif // BORDERS_EXTRACTOR_HPP diff --git a/toonz/sources/common/trop/brush.cpp b/toonz/sources/common/trop/brush.cpp index c142fc4..f9b561c 100644 --- a/toonz/sources/common/trop/brush.cpp +++ b/toonz/sources/common/trop/brush.cpp @@ -5,616 +5,645 @@ //======================================================================= -class HalfCord -{ - std::unique_ptr m_array; - int m_radius; +class HalfCord { + std::unique_ptr m_array; + int m_radius; public: - HalfCord(int radius) - : m_radius(radius) - , m_array(new int[radius + 1]) - { - assert(radius >= 0); - memset(m_array.get(), 0, (m_radius + 1) * sizeof(int)); - - float dCircle = 1.25f - m_radius; // inizializza decision variable - int y = m_radius; // inizializzazione indice scanline - int x = 0; // inizializzazione indice colonna - do { - m_array[y] = std::max(x, m_array[y]); - m_array[x] = y; - if (dCircle <= 0) { - dCircle = dCircle + 2 * x + 3; - } else { - y--; - dCircle = dCircle + 2 * (x - y) + 5; - } - x++; - - } while (y >= x); - } - - inline int getCord(int x) - { - assert(0 <= x && x <= m_radius); - return m_array[x]; - }; + HalfCord(int radius) : m_radius(radius), m_array(new int[radius + 1]) { + assert(radius >= 0); + memset(m_array.get(), 0, (m_radius + 1) * sizeof(int)); + + float dCircle = 1.25f - m_radius; // inizializza decision variable + int y = m_radius; // inizializzazione indice scanline + int x = 0; // inizializzazione indice colonna + do { + m_array[y] = std::max(x, m_array[y]); + m_array[x] = y; + if (dCircle <= 0) { + dCircle = dCircle + 2 * x + 3; + } else { + y--; + dCircle = dCircle + 2 * (x - y) + 5; + } + x++; + + } while (y >= x); + } + + inline int getCord(int x) { + assert(0 <= x && x <= m_radius); + return m_array[x]; + }; private: - // not implemented - HalfCord(const HalfCord &); - HalfCord &operator=(const HalfCord &); + // not implemented + HalfCord(const HalfCord &); + HalfCord &operator=(const HalfCord &); }; //======================================================================= -void TRop::brush( - TRaster32P ras, - const TPoint &aa, - const TPoint &bb, - int radius, - const TPixel32 &col) -{ - - TPoint a = aa; - TPoint b = bb; - if (a.y > b.y) - tswap(a, b); // a e' piu' in basso di b - - int lx = ras->getLx(); - int ly = ras->getLy(); - ras->lock(); - - // ----- radius = 0 - if (radius == 0) { - // k = +1/-1 se il rettangolo e' inclinato positivamente (0<=m)/negativamente (m<0) - // (se k<0 viene fatta una riflessione sulle ascisse prima di tornare alle - // coordinate "di schermo") - int k = 1; - int dy = b.y - a.y; - int dx = b.x - a.x; - if (dx < 0) { - dx = -dx; - k = -1; - } - - assert(dx >= 0); - assert(dy >= 0); - - double m; // m sara' definita solo per dx!=0) - if (dx > 0) { - m = dy / (double)dx; - } - //double length = sqrt(dx*dx + dy*dy); - const int alpha = dy, beta = -dx; - const int incE = alpha; - const int incNE = alpha + beta; - const int incN = beta; - - // N.B. le coordinate sono relative ad un sist. di rif. con l'origine in a - // l'eq. della retta e' alpha * x + beta * y = 0 - - int yMin = std::max(a.y, 0) - a.y; // clipping y + cambio riferimento - int yMax = std::min(b.y, ly - 1) - a.y; // (trasporto dell'origine in a) - if (dx > 0 && m <= 1) { - // midpoint algorithm - TPoint segm; - if (dy == 0) // segmento orizzontale: inizializza segm - { - segm.x = 0; - segm.y = yMin; - } else // 0 0) { - xMin = std::max({a.x + segm.x - count, a.x, 0}); // clipping x + ritorno alle - xMax = std::min({a.x + segm.x, b.x, lx - 1}); // coordinate "di schermo" - - } else { - xMin = std::max({a.x - segm.x, a.x - dx, 0}); // clipping x + riflessione + ritorno - xMax = std::min({a.x - segm.x + count, a.x, lx - 1}); // alle coordinate "di schermo" - } - - TPixel32 *p = ras->pixels(segm.y + a.y) + xMin; - TPixel32 *q = p + (xMax - xMin); - - while (p <= q) - *p++ = col; - - dSegm = dSegm + incNE; - segm.x++; - segm.y++; - } - } else // m>1 oppure segmento verticale - { - // midpoint algorithm - TPoint segm; - if (dx == 0) // segmento verticale: inizializza segm - { - segm.x = 0; - segm.y = yMin; - } else // m>1 : inizializza segm - { - segm.x = tround(yMin / m); - segm.y = yMin; - } - - int dSegm = tfloor(alpha * (segm.x + 0.5) + beta * (segm.y + 1)); - while (segm.y <= yMax) { - int xMin, xMax; - if (k > 0) { - xMin = std::max(a.x + segm.x, 0); // clipping x + ritorno alle - xMax = std::min(a.x + segm.x, lx - 1); // coordinate "di schermo" - - } else { - xMin = std::max(a.x - segm.x, 0); // clipping x + riflessione + ritorno - xMax = std::min(a.x - segm.x, lx - 1); // alle coordinate "di schermo" - } - - TPixel32 *p = ras->pixels(segm.y + a.y) + xMin; - TPixel32 *q = p + (xMax - xMin); - - while (p <= q) - *p++ = col; - - if (dSegm <= 0) // NordEst - { - dSegm = dSegm + incNE; - segm.x++; - } else // Nord - { - dSegm = dSegm + incN; - } - segm.y++; - } - } - ras->unlock(); - return; - } - - HalfCord halfCord(radius); - - int x, y; - - // ----- punti iniziali coincidenti: disegna un cerchio - if (a == b) { - int yMin = std::max(a.y - radius, 0); // clipping y - int yMax = std::min(a.y + radius, ly - 1); // clipping y - for (y = yMin; y <= yMax; y++) { - int deltay = abs(y - a.y); - int xMin = std::max(a.x - halfCord.getCord(deltay), 0); // clipping x - int xMax = std::min(a.x + halfCord.getCord(deltay), lx - 1); // clipping x - TPixel32 *p = ras->pixels(y) + xMin; - TPixel32 *q = p + (xMax - xMin); - while (p <= q) - *p++ = col; - } - ras->unlock(); - return; - } - - // ----- rettangolo orizzontale (a.y = b.y, a.x != b.x) - if (a.y == b.y) { - int yMin = std::max((a.y - radius), 0); // clipping y - int yMax = std::min((a.y + radius), ly - 1); // clipping y - int xLeft = std::min(a.x, b.x); - int xRight = std::max(a.x, b.x); - for (y = yMin; y <= yMax; y++) { - int deltay = abs(y - a.y); - int xMin = std::max(xLeft - halfCord.getCord(deltay), 0); // clipping x - int xMax = std::min(xRight + halfCord.getCord(deltay), lx - 1); // clipping x - TPixel32 *p = ras->pixels(y) + xMin; - TPixel32 *q = p + (xMax - xMin); - while (p <= q) - *p++ = col; - } - ras->unlock(); - return; - } - - // ----- rettangolo verticale (a.x = b.x, a.y != b.y) - if (a.x == b.x) { - - int xMin = std::max(a.x - radius, 0); // clipping x - int xMax = std::min(a.x + radius, lx - 1); // clipping x - for (x = xMin; x <= xMax; x++) { - int deltax = abs(x - a.x); - int yMin = std::max(a.y - halfCord.getCord(deltax), 0); // clipping y - int yMax = std::min(b.y + halfCord.getCord(deltax), ly - 1); // clipping y - if (yMin <= yMax) { - TPixel32 *p = ras->pixels(yMin) + x; - TPixel32 *q = ras->pixels(yMax) + x; - int wrap = ras->getWrap(); - while (p <= q) { - *p = col; - p += wrap; - } - } - } - ras->unlock(); - return; - } - - // ----- rettangolo inclinato - // k = +1/-1 se il rettangolo e' inclinato positivamente/negativamente - int k = 1; - int dx = b.x - a.x; - if (dx < 0) { - dx = -dx; - k = -1; - } - int dy = b.y - a.y; - - assert(dx > 0); - assert(dy > 0); - - double length = sqrt((double)(dx * dx + dy * dy)); - const double m = dy / (double)dx; - - //punto di tangenza superiore nel sistema di riferimento del cerchio - TPointD up(-radius * dy / length, radius * dx / length); - - //semi-ampiezza orizzontale delle "calotte" circolari - int halfAmplCap = tfloor(-up.x); - - // A meno di intersezioni relative tra le diverse zone: - - // le scanline della "calotta" circolare superiore sono (b.y+cutExt,b.y+radius] - // le scanline del trapezoide circolare superiore sono [b.y-cutIn,b.y+cutExt] - // le scanline del parallelogramma sono (a.y+cutIn,b.y-cutIn) - // le scanline del trapezoide circolare inferiore sono [a.y-cutExt,a.y+cutIn] - // le scanline della "calotta" circolare inferiore sono [a.y-radius,a.y-cutExt) - int cutExt, cutIn; - - // vertici del parallelogramma - TPointD rightUp; - TPointD rightDown; - TPointD leftUp; - TPointD leftDown; - double mParall; //coeff. angolare parallelogramma - - // NOTA BENE: halfAmplCap=0 <=> (radius=0 (caso a parte) , 1) - if (radius > 1) { - for (cutExt = radius; cutExt >= 0 && halfCord.getCord(cutExt) <= halfAmplCap; cutExt--) - ; - cutIn = cutExt; // vedi else successivo - rightUp.x = dx + halfCord.getCord(cutIn); - rightUp.y = dy - cutIn; - rightDown.x = halfCord.getCord(cutIn); - rightDown.y = -cutIn; - leftUp.x = dx - halfCord.getCord(cutIn); - leftUp.y = dy + cutIn; - leftDown.x = -halfCord.getCord(cutIn); - leftDown.y = cutIn; - mParall = dy / (double)dx; - } else // N.B. cutExt != cutIn solo quando radius=1 - { - cutExt = radius; // radius=1 => halfAmplCap=0 (non ci sono mai le "calotte" circolari) - cutIn = 0; // anche per radius=1 il limite "interno" dei trapezoidi circolari e' < radius - rightUp.x = dx - up.x; - rightUp.y = dy - up.y; - rightDown.x = -up.x; - rightDown.y = -up.y; - leftUp.x = dx + up.x; - leftUp.y = dy + up.y; - leftDown.x = up.x; - leftDown.y = up.y; - mParall = m; - } - // ----- riempie "calotte" circolari - - // ----- riempie "calotta" circolare inferiore - int yMin = std::max(a.y - radius, 0); // clipping y - int yMax = std::min(a.y - cutExt - 1, ly - 1); // clipping y - for (y = yMin; y <= yMax; y++) { - int r = halfCord.getCord(a.y - y); - int xMin = std::max(a.x - r, 0); // clipping x - int xMax = std::min(a.x + r, lx - 1); // clipping x - TPixel32 *p = ras->pixels(y) + xMin; - TPixel32 *q = p + (xMax - xMin); - while (p <= q) - *p++ = col; - } - // ----- riempie "calotta" circolare superiore - yMin = std::max(b.y + cutExt + 1, 0); // clipping y - yMax = std::min(b.y + radius, ly - 1); // clipping y - for (y = yMin; y <= yMax; y++) { - int r = halfCord.getCord(y - b.y); - int xMin = std::max(b.x - r, 0); // clipping x - int xMax = std::min(b.x + r, lx - 1); // clipping x - TPixel32 *p = ras->pixels(y) + xMin; - TPixel32 *q = p + (xMax - xMin); - while (p <= q) - *p++ = col; - } - // ----- riempie trapezoidi - - // (se k<0 viene fatta una riflessione sulle ascisse prima di tornare alle - // coordinate "di schermo") - - // limite destro assoluto delle scanline trapezoide: - int xSegmMax = tround(dx - up.x); // coordinata x del punto di tangenza inferiore sul cerchio superiore - - // limite sinistro assoluto delle scanline: - int xSegmMin = tround(up.x); // coordinata x del punto di tangenza superiore sul cerchio inferiore - - // ----- riempie trapezoide inferiore - - // N.B. le coordinate sono relative ad un sist. di rif. con l'origine sul centro - // del cerchio inferiore - - yMin = std::max(a.y - cutExt, 0) - a.y; // clipping y - yMax = std::min({a.y + cutIn, b.y - cutIn - 1, ly - 1}) - a.y; // clipping y - - // l'eq. della retta e' alpha * x + beta * y + gammaRight = 0 - const int alpha = dy, beta = -dx; - const double gammaRight = rightDown.y * dx - rightDown.x * dy; - const int incE = alpha; - const int incNE = alpha + beta; - const int incN = beta; - - if (m <= 1) { - // midpoint algorithm; le scanline vengono disegnate solo - // sul NordEst. L'ultima scanline non viene disegnata - TPoint segmRight(tceil((yMin + 0.5 - rightDown.y) / mParall + rightDown.x) - 1, yMin); - int dSegmRight = tfloor(alpha * (segmRight.x + 1) + beta * (segmRight.y + 0.5) + gammaRight); - while (segmRight.y <= yMax) { - if (dSegmRight < 0) // Est - { - dSegmRight = dSegmRight + incE; - segmRight.x++; - } else // NordEst - { - int xMin, xMax; - if (k > 0) { - xMin = std::max(a.x - halfCord.getCord(abs(segmRight.y)), 0); // clipping x - xMax = std::min(a.x + std::min(segmRight.x, xSegmMax), lx - 1); // clipping x - } else { - xMin = std::max(a.x - std::min(segmRight.x, xSegmMax), 0); // clipping x + ritorno alle - xMax = std::min(a.x + halfCord.getCord(abs(segmRight.y)), lx - 1); // coordinate "di schermo" - } - TPixel32 *p = ras->pixels(segmRight.y + a.y) + xMin; - TPixel32 *q = p + (xMax - xMin); - while (p <= q) - *p++ = col; - - dSegmRight = dSegmRight + incNE; - segmRight.x++; - segmRight.y++; - } - } - } else // m>1 - { - // midpoint algorithm; le scanline vengono disegnate sempre - TPoint segmRight(tround((yMin - rightDown.y) / mParall + rightDown.x), yMin); - int dSegmRight = tfloor(alpha * (segmRight.x + 0.5) + beta * (segmRight.y + 1) + gammaRight); - while (segmRight.y <= yMax) { - int xMin, xMax; - if (k > 0) { - xMin = std::max(a.x - halfCord.getCord(abs(segmRight.y)), 0); // clipping x - xMax = std::min(a.x + segmRight.x, lx - 1); // clipping x - } else { - xMin = std::max(a.x - segmRight.x, 0); // clipping x + ritorno alle coordinate - xMax = std::min(a.x + halfCord.getCord(abs(segmRight.y)), lx - 1); // "di schermo" - } - TPixel32 *p = ras->pixels(segmRight.y + a.y) + xMin; - TPixel32 *q = p + (xMax - xMin); - while (p <= q) - *p++ = col; - - if (dSegmRight <= 0) // NordEst - { - dSegmRight = dSegmRight + incNE; - segmRight.x++; - } else // Nord - { - dSegmRight = dSegmRight + incN; - } - segmRight.y++; - } - } - - // ----- riempie trapezoide superiore - - // N.B. le coordinate sono relative ad un sist. di rif. con l'origine sul centro - // del cerchio superiore - yMin = std::max({b.y - cutIn, a.y + cutIn + 1, 0}) - b.y; // clipping y - yMax = std::min(b.y + cutExt, ly - 1) - b.y; // clipping y - - // l'eq. della retta e' alpha * x + beta * y + gammaLeft = 0 - const double gammaLeft = leftDown.y * dx - leftDown.x * dy; - - if (m <= 1) { - // midpoint algorithm; le scanline vengono disegnate solo - // sul NordEst. L'ultima scanline non viene disegnata - TPoint segmLeft(tceil((yMin - 0.5 - leftDown.y) / mParall + leftDown.x), yMin); - int dSegmLeft = tfloor(alpha * (segmLeft.x + 1) + beta * (segmLeft.y + 0.5) + gammaLeft); - while (segmLeft.y <= yMax) { - int xMin, xMax; - if (k > 0) { - xMin = std::max(b.x + std::max(segmLeft.x, xSegmMin - dx), 0); // clipping x - xMax = std::min(b.x + halfCord.getCord(abs(segmLeft.y)), lx - 1); // clipping x - } else { - xMin = std::max(b.x - halfCord.getCord(abs(segmLeft.y)), 0); // clipping x + ritorno alle - xMax = std::min(b.x - std::max(segmLeft.x, xSegmMin - dx), lx - 1); // coordinate "di schermo" - } - TPixel32 *p = ras->pixels(segmLeft.y + b.y) + xMin; - TPixel32 *q = p + (xMax - xMin); - - while (p <= q) - *p++ = col; - while (dSegmLeft < 0) { - dSegmLeft = dSegmLeft + incE; - segmLeft.x++; - } - dSegmLeft = dSegmLeft + incNE; - segmLeft.x++; - segmLeft.y++; - } - } else // m>1 - { - // midpoint algorithm; le scanline vengono disegnate sempre - TPoint segmLeft(tround((yMin - leftDown.y) / mParall + leftDown.x), yMin); - int dSegmLeft = tfloor(alpha * (segmLeft.x + 0.5) + beta * (segmLeft.y + 1) + gammaLeft); - while (segmLeft.y <= yMax) { - int xMin, xMax; - if (k > 0) { - xMin = std::max(b.x + segmLeft.x, 0); // clipping x - xMax = std::min(b.x + halfCord.getCord(abs(segmLeft.y)), lx - 1); // clipping x - } else { - xMin = std::max(b.x - halfCord.getCord(abs(segmLeft.y)), 0); // clipping x + ritorno alle - xMax = std::min(b.x - segmLeft.x, lx - 1); // coordinate "di schermo" - } - TPixel32 *p = ras->pixels(segmLeft.y + b.y) + xMin; - TPixel32 *q = p + (xMax - xMin); - - while (p <= q) - *p++ = col; - - if (dSegmLeft <= 0) // NordEst - { - dSegmLeft = dSegmLeft + incNE; - segmLeft.x++; - } else // Nord - { - dSegmLeft = dSegmLeft + incN; - } - segmLeft.y++; - } - } - - // ----- parallelogramma (in alternativa a "parallelogrammoide circolare") - - // N.B. le coordinate sono relative ad un sist. di rif. con l'origine sul centro - // del cerchio inferiore - - // retta destra di equaz. alpha * x + beta * y + gammaRight = 0 - // retta sinistra di equaz. alpha * x + beta * y + gammaLeft = 0 - - yMin = std::max(a.y + cutIn + 1, 0) - a.y; //clipping y - yMax = std::min(b.y - cutIn - 1, ly - 1) - a.y; //clipping y - if (m <= 1) { - // midpoint algorithm; le scanline vengono disegnate solo - // sul NordEst. L'ultima scanline non viene disegnata - TPoint segmRight(tceil((yMin + 0.5 - rightDown.y) / mParall + rightDown.x) - 1, yMin); - TPoint segmLeft = TPoint(tceil((yMin - 0.5 - leftDown.y) / mParall + leftDown.x), yMin); - int dSegmRight = tfloor(alpha * (segmRight.x + 1) + beta * (segmRight.y + 0.5) + gammaRight); - int dSegmLeft = tfloor(alpha * (segmLeft.x + 1) + beta * (segmLeft.y + 0.5) + gammaLeft); - while (segmRight.y <= yMax) { - if (dSegmRight < 0) // segmRight a Est - { - dSegmRight = dSegmRight + incE; - segmRight.x++; - } else // segmRight a NordEst - { - int xMin, xMax; - if (k > 0) { - xMin = std::max(a.x + std::max(segmLeft.x, xSegmMin), 0); // clipping x - xMax = std::min(a.x + std::min(segmRight.x, xSegmMax), lx - 1); // clipping x - } else { - xMin = std::max(a.x - std::min(segmRight.x, xSegmMax), 0); // clipping x + ritorno alle - xMax = std::min(a.x - std::max(segmLeft.x, xSegmMin), lx - 1); // coordinate "di schermo" - } - - TPixel32 *p = ras->pixels(segmRight.y + a.y) + xMin; - TPixel32 *q = p + (xMax - xMin); - - while (p <= q) - *p++ = col; - - dSegmRight = dSegmRight + incNE; - segmRight.x++; - segmRight.y++; - - while (dSegmLeft < 0) // segmLeft a Est - { - dSegmLeft = dSegmLeft + incE; - segmLeft.x++; - } - // segmLeft a NordEst - dSegmLeft = dSegmLeft + incNE; - segmLeft.x++; - segmLeft.y++; - } - } - } else // m>1 - { - // midpoint algorithm; le scanline vengono disegnate sempre - TPoint segmRight(tround((yMin - rightDown.y) / mParall + rightDown.x), yMin); - TPoint segmLeft(tround((yMin - leftDown.y) / mParall + leftDown.x), yMin); - int dSegmRight = tfloor(alpha * (segmRight.x + 0.5) + beta * (segmRight.y + 1) + gammaRight); - int dSegmLeft = tfloor(alpha * (segmLeft.x + 0.5) + beta * (segmLeft.y + 1) + gammaLeft); - while (segmRight.y <= yMax) { - int xMin, xMax; - if (k > 0) { - xMin = std::max(a.x + segmLeft.x, 0); // clipping x - xMax = std::min(a.x + segmRight.x, lx - 1); // clipping x - } else { - xMin = std::max(a.x - segmRight.x, 0); // clipping x + ritorno alle - xMax = std::min(a.x - segmLeft.x, lx - 1); // coordinate "di schermo" - } - - TPixel32 *p = ras->pixels(segmRight.y + a.y) + xMin; - TPixel32 *q = p + (xMax - xMin); - - while (p <= q) - *p++ = col; - - if (dSegmRight <= 0) // segmRight a NordEst - { - dSegmRight = dSegmRight + incNE; - segmRight.x++; - } else // segmRight a Nord - { - dSegmRight = dSegmRight + incN; - } - segmRight.y++; - - if (dSegmLeft <= 0) // segmLeft a NordEst - { - dSegmLeft = dSegmLeft + incNE; - segmLeft.x++; - } else // segmLeft a Nord - { - dSegmLeft = dSegmLeft + incN; - } - } - } - - // ---- parallelogrammoide circolare (in alternativa a parallelogramma) - - // N.B. coordinate di schermo (riflessione per k<0 ) - - yMin = std::max(b.y - cutIn, 0); - yMax = std::min(a.y + cutIn, ly - 1); - for (y = yMin; y <= yMax; y++) { - int xMin, xMax; - if (k > 0) { - xMin = std::max(a.x - halfCord.getCord(abs(y - a.y)), 0); // clipping x - xMax = std::min(b.x + halfCord.getCord(abs(b.y - y)), lx - 1); // clipping x - } else { - xMin = std::max(b.x - halfCord.getCord(abs(b.y - y)), 0); // clipping x + ritorno alle - xMax = std::min(a.x + halfCord.getCord(abs(y - a.y)), lx - 1); // coordinate "di schermo" - } - TPixel32 *p = ras->pixels(y) + xMin; - TPixel32 *q = p + (xMax - xMin); - while (p <= q) - *p++ = col; - } - ras->unlock(); +void TRop::brush(TRaster32P ras, const TPoint &aa, const TPoint &bb, int radius, + const TPixel32 &col) { + TPoint a = aa; + TPoint b = bb; + if (a.y > b.y) tswap(a, b); // a e' piu' in basso di b + + int lx = ras->getLx(); + int ly = ras->getLy(); + ras->lock(); + + // ----- radius = 0 + if (radius == 0) { + // k = +1/-1 se il rettangolo e' inclinato positivamente + // (0<=m)/negativamente (m<0) + // (se k<0 viene fatta una riflessione sulle ascisse prima di tornare alle + // coordinate "di schermo") + int k = 1; + int dy = b.y - a.y; + int dx = b.x - a.x; + if (dx < 0) { + dx = -dx; + k = -1; + } + + assert(dx >= 0); + assert(dy >= 0); + + double m; // m sara' definita solo per dx!=0) + if (dx > 0) { + m = dy / (double)dx; + } + // double length = sqrt(dx*dx + dy*dy); + const int alpha = dy, beta = -dx; + const int incE = alpha; + const int incNE = alpha + beta; + const int incN = beta; + + // N.B. le coordinate sono relative ad un sist. di rif. con l'origine in a + // l'eq. della retta e' alpha * x + beta * y = 0 + + int yMin = std::max(a.y, 0) - a.y; // clipping y + cambio riferimento + int yMax = std::min(b.y, ly - 1) - a.y; // (trasporto dell'origine in a) + if (dx > 0 && m <= 1) { + // midpoint algorithm + TPoint segm; + if (dy == 0) // segmento orizzontale: inizializza segm + { + segm.x = 0; + segm.y = yMin; + } else // 0 0) { + xMin = std::max( + {a.x + segm.x - count, a.x, 0}); // clipping x + ritorno alle + xMax = std::min( + {a.x + segm.x, b.x, lx - 1}); // coordinate "di schermo" + + } else { + xMin = std::max({a.x - segm.x, a.x - dx, + 0}); // clipping x + riflessione + ritorno + xMax = std::min({a.x - segm.x + count, a.x, + lx - 1}); // alle coordinate "di schermo" + } + + TPixel32 *p = ras->pixels(segm.y + a.y) + xMin; + TPixel32 *q = p + (xMax - xMin); + + while (p <= q) *p++ = col; + + dSegm = dSegm + incNE; + segm.x++; + segm.y++; + } + } else // m>1 oppure segmento verticale + { + // midpoint algorithm + TPoint segm; + if (dx == 0) // segmento verticale: inizializza segm + { + segm.x = 0; + segm.y = yMin; + } else // m>1 : inizializza segm + { + segm.x = tround(yMin / m); + segm.y = yMin; + } + + int dSegm = tfloor(alpha * (segm.x + 0.5) + beta * (segm.y + 1)); + while (segm.y <= yMax) { + int xMin, xMax; + if (k > 0) { + xMin = std::max(a.x + segm.x, 0); // clipping x + ritorno alle + xMax = std::min(a.x + segm.x, lx - 1); // coordinate "di schermo" + + } else { + xMin = + std::max(a.x - segm.x, 0); // clipping x + riflessione + ritorno + xMax = + std::min(a.x - segm.x, lx - 1); // alle coordinate "di schermo" + } + + TPixel32 *p = ras->pixels(segm.y + a.y) + xMin; + TPixel32 *q = p + (xMax - xMin); + + while (p <= q) *p++ = col; + + if (dSegm <= 0) // NordEst + { + dSegm = dSegm + incNE; + segm.x++; + } else // Nord + { + dSegm = dSegm + incN; + } + segm.y++; + } + } + ras->unlock(); + return; + } + + HalfCord halfCord(radius); + + int x, y; + + // ----- punti iniziali coincidenti: disegna un cerchio + if (a == b) { + int yMin = std::max(a.y - radius, 0); // clipping y + int yMax = std::min(a.y + radius, ly - 1); // clipping y + for (y = yMin; y <= yMax; y++) { + int deltay = abs(y - a.y); + int xMin = std::max(a.x - halfCord.getCord(deltay), 0); // clipping x + int xMax = + std::min(a.x + halfCord.getCord(deltay), lx - 1); // clipping x + TPixel32 *p = ras->pixels(y) + xMin; + TPixel32 *q = p + (xMax - xMin); + while (p <= q) *p++ = col; + } + ras->unlock(); + return; + } + + // ----- rettangolo orizzontale (a.y = b.y, a.x != b.x) + if (a.y == b.y) { + int yMin = std::max((a.y - radius), 0); // clipping y + int yMax = std::min((a.y + radius), ly - 1); // clipping y + int xLeft = std::min(a.x, b.x); + int xRight = std::max(a.x, b.x); + for (y = yMin; y <= yMax; y++) { + int deltay = abs(y - a.y); + int xMin = std::max(xLeft - halfCord.getCord(deltay), 0); // clipping x + int xMax = + std::min(xRight + halfCord.getCord(deltay), lx - 1); // clipping x + TPixel32 *p = ras->pixels(y) + xMin; + TPixel32 *q = p + (xMax - xMin); + while (p <= q) *p++ = col; + } + ras->unlock(); + return; + } + + // ----- rettangolo verticale (a.x = b.x, a.y != b.y) + if (a.x == b.x) { + int xMin = std::max(a.x - radius, 0); // clipping x + int xMax = std::min(a.x + radius, lx - 1); // clipping x + for (x = xMin; x <= xMax; x++) { + int deltax = abs(x - a.x); + int yMin = std::max(a.y - halfCord.getCord(deltax), 0); // clipping y + int yMax = + std::min(b.y + halfCord.getCord(deltax), ly - 1); // clipping y + if (yMin <= yMax) { + TPixel32 *p = ras->pixels(yMin) + x; + TPixel32 *q = ras->pixels(yMax) + x; + int wrap = ras->getWrap(); + while (p <= q) { + *p = col; + p += wrap; + } + } + } + ras->unlock(); + return; + } + + // ----- rettangolo inclinato + // k = +1/-1 se il rettangolo e' inclinato positivamente/negativamente + int k = 1; + int dx = b.x - a.x; + if (dx < 0) { + dx = -dx; + k = -1; + } + int dy = b.y - a.y; + + assert(dx > 0); + assert(dy > 0); + + double length = sqrt((double)(dx * dx + dy * dy)); + const double m = dy / (double)dx; + + // punto di tangenza superiore nel sistema di riferimento del cerchio + TPointD up(-radius * dy / length, radius * dx / length); + + // semi-ampiezza orizzontale delle "calotte" circolari + int halfAmplCap = tfloor(-up.x); + + // A meno di intersezioni relative tra le diverse zone: + + // le scanline della "calotta" circolare superiore sono + // (b.y+cutExt,b.y+radius] + // le scanline del trapezoide circolare superiore sono [b.y-cutIn,b.y+cutExt] + // le scanline del parallelogramma sono (a.y+cutIn,b.y-cutIn) + // le scanline del trapezoide circolare inferiore sono [a.y-cutExt,a.y+cutIn] + // le scanline della "calotta" circolare inferiore sono + // [a.y-radius,a.y-cutExt) + int cutExt, cutIn; + + // vertici del parallelogramma + TPointD rightUp; + TPointD rightDown; + TPointD leftUp; + TPointD leftDown; + double mParall; // coeff. angolare parallelogramma + + // NOTA BENE: halfAmplCap=0 <=> (radius=0 (caso a parte) , 1) + if (radius > 1) { + for (cutExt = radius; + cutExt >= 0 && halfCord.getCord(cutExt) <= halfAmplCap; cutExt--) + ; + cutIn = cutExt; // vedi else successivo + rightUp.x = dx + halfCord.getCord(cutIn); + rightUp.y = dy - cutIn; + rightDown.x = halfCord.getCord(cutIn); + rightDown.y = -cutIn; + leftUp.x = dx - halfCord.getCord(cutIn); + leftUp.y = dy + cutIn; + leftDown.x = -halfCord.getCord(cutIn); + leftDown.y = cutIn; + mParall = dy / (double)dx; + } else // N.B. cutExt != cutIn solo quando radius=1 + { + cutExt = radius; // radius=1 => halfAmplCap=0 (non ci sono mai le + // "calotte" circolari) + cutIn = 0; // anche per radius=1 il limite "interno" dei trapezoidi + // circolari e' < radius + rightUp.x = dx - up.x; + rightUp.y = dy - up.y; + rightDown.x = -up.x; + rightDown.y = -up.y; + leftUp.x = dx + up.x; + leftUp.y = dy + up.y; + leftDown.x = up.x; + leftDown.y = up.y; + mParall = m; + } + // ----- riempie "calotte" circolari + + // ----- riempie "calotta" circolare inferiore + int yMin = std::max(a.y - radius, 0); // clipping y + int yMax = std::min(a.y - cutExt - 1, ly - 1); // clipping y + for (y = yMin; y <= yMax; y++) { + int r = halfCord.getCord(a.y - y); + int xMin = std::max(a.x - r, 0); // clipping x + int xMax = std::min(a.x + r, lx - 1); // clipping x + TPixel32 *p = ras->pixels(y) + xMin; + TPixel32 *q = p + (xMax - xMin); + while (p <= q) *p++ = col; + } + // ----- riempie "calotta" circolare superiore + yMin = std::max(b.y + cutExt + 1, 0); // clipping y + yMax = std::min(b.y + radius, ly - 1); // clipping y + for (y = yMin; y <= yMax; y++) { + int r = halfCord.getCord(y - b.y); + int xMin = std::max(b.x - r, 0); // clipping x + int xMax = std::min(b.x + r, lx - 1); // clipping x + TPixel32 *p = ras->pixels(y) + xMin; + TPixel32 *q = p + (xMax - xMin); + while (p <= q) *p++ = col; + } + // ----- riempie trapezoidi + + // (se k<0 viene fatta una riflessione sulle ascisse prima di tornare alle + // coordinate "di schermo") + + // limite destro assoluto delle scanline trapezoide: + int xSegmMax = tround(dx - up.x); // coordinata x del punto di tangenza + // inferiore sul cerchio superiore + + // limite sinistro assoluto delle scanline: + int xSegmMin = tround(up.x); // coordinata x del punto di tangenza superiore + // sul cerchio inferiore + + // ----- riempie trapezoide inferiore + + // N.B. le coordinate sono relative ad un sist. di rif. con l'origine sul + // centro + // del cerchio inferiore + + yMin = std::max(a.y - cutExt, 0) - a.y; // clipping y + yMax = std::min({a.y + cutIn, b.y - cutIn - 1, ly - 1}) - a.y; // clipping y + + // l'eq. della retta e' alpha * x + beta * y + gammaRight = 0 + const int alpha = dy, beta = -dx; + const double gammaRight = rightDown.y * dx - rightDown.x * dy; + const int incE = alpha; + const int incNE = alpha + beta; + const int incN = beta; + + if (m <= 1) { + // midpoint algorithm; le scanline vengono disegnate solo + // sul NordEst. L'ultima scanline non viene disegnata + TPoint segmRight( + tceil((yMin + 0.5 - rightDown.y) / mParall + rightDown.x) - 1, yMin); + int dSegmRight = tfloor(alpha * (segmRight.x + 1) + + beta * (segmRight.y + 0.5) + gammaRight); + while (segmRight.y <= yMax) { + if (dSegmRight < 0) // Est + { + dSegmRight = dSegmRight + incE; + segmRight.x++; + } else // NordEst + { + int xMin, xMax; + if (k > 0) { + xMin = std::max(a.x - halfCord.getCord(abs(segmRight.y)), + 0); // clipping x + xMax = std::min(a.x + std::min(segmRight.x, xSegmMax), + lx - 1); // clipping x + } else { + xMin = std::max(a.x - std::min(segmRight.x, xSegmMax), + 0); // clipping x + ritorno alle + xMax = std::min(a.x + halfCord.getCord(abs(segmRight.y)), + lx - 1); // coordinate "di schermo" + } + TPixel32 *p = ras->pixels(segmRight.y + a.y) + xMin; + TPixel32 *q = p + (xMax - xMin); + while (p <= q) *p++ = col; + + dSegmRight = dSegmRight + incNE; + segmRight.x++; + segmRight.y++; + } + } + } else // m>1 + { + // midpoint algorithm; le scanline vengono disegnate sempre + TPoint segmRight(tround((yMin - rightDown.y) / mParall + rightDown.x), + yMin); + int dSegmRight = tfloor(alpha * (segmRight.x + 0.5) + + beta * (segmRight.y + 1) + gammaRight); + while (segmRight.y <= yMax) { + int xMin, xMax; + if (k > 0) { + xMin = std::max(a.x - halfCord.getCord(abs(segmRight.y)), + 0); // clipping x + xMax = std::min(a.x + segmRight.x, lx - 1); // clipping x + } else { + xMin = std::max(a.x - segmRight.x, + 0); // clipping x + ritorno alle coordinate + xMax = std::min(a.x + halfCord.getCord(abs(segmRight.y)), + lx - 1); // "di schermo" + } + TPixel32 *p = ras->pixels(segmRight.y + a.y) + xMin; + TPixel32 *q = p + (xMax - xMin); + while (p <= q) *p++ = col; + + if (dSegmRight <= 0) // NordEst + { + dSegmRight = dSegmRight + incNE; + segmRight.x++; + } else // Nord + { + dSegmRight = dSegmRight + incN; + } + segmRight.y++; + } + } + + // ----- riempie trapezoide superiore + + // N.B. le coordinate sono relative ad un sist. di rif. con l'origine sul + // centro + // del cerchio superiore + yMin = std::max({b.y - cutIn, a.y + cutIn + 1, 0}) - b.y; // clipping y + yMax = std::min(b.y + cutExt, ly - 1) - b.y; // clipping y + + // l'eq. della retta e' alpha * x + beta * y + gammaLeft = 0 + const double gammaLeft = leftDown.y * dx - leftDown.x * dy; + + if (m <= 1) { + // midpoint algorithm; le scanline vengono disegnate solo + // sul NordEst. L'ultima scanline non viene disegnata + TPoint segmLeft(tceil((yMin - 0.5 - leftDown.y) / mParall + leftDown.x), + yMin); + int dSegmLeft = tfloor(alpha * (segmLeft.x + 1) + + beta * (segmLeft.y + 0.5) + gammaLeft); + while (segmLeft.y <= yMax) { + int xMin, xMax; + if (k > 0) { + xMin = std::max(b.x + std::max(segmLeft.x, xSegmMin - dx), + 0); // clipping x + xMax = std::min(b.x + halfCord.getCord(abs(segmLeft.y)), + lx - 1); // clipping x + } else { + xMin = std::max(b.x - halfCord.getCord(abs(segmLeft.y)), + 0); // clipping x + ritorno alle + xMax = std::min(b.x - std::max(segmLeft.x, xSegmMin - dx), + lx - 1); // coordinate "di schermo" + } + TPixel32 *p = ras->pixels(segmLeft.y + b.y) + xMin; + TPixel32 *q = p + (xMax - xMin); + + while (p <= q) *p++ = col; + while (dSegmLeft < 0) { + dSegmLeft = dSegmLeft + incE; + segmLeft.x++; + } + dSegmLeft = dSegmLeft + incNE; + segmLeft.x++; + segmLeft.y++; + } + } else // m>1 + { + // midpoint algorithm; le scanline vengono disegnate sempre + TPoint segmLeft(tround((yMin - leftDown.y) / mParall + leftDown.x), yMin); + int dSegmLeft = tfloor(alpha * (segmLeft.x + 0.5) + + beta * (segmLeft.y + 1) + gammaLeft); + while (segmLeft.y <= yMax) { + int xMin, xMax; + if (k > 0) { + xMin = std::max(b.x + segmLeft.x, 0); // clipping x + xMax = std::min(b.x + halfCord.getCord(abs(segmLeft.y)), + lx - 1); // clipping x + } else { + xMin = std::max(b.x - halfCord.getCord(abs(segmLeft.y)), + 0); // clipping x + ritorno alle + xMax = std::min(b.x - segmLeft.x, lx - 1); // coordinate "di schermo" + } + TPixel32 *p = ras->pixels(segmLeft.y + b.y) + xMin; + TPixel32 *q = p + (xMax - xMin); + + while (p <= q) *p++ = col; + + if (dSegmLeft <= 0) // NordEst + { + dSegmLeft = dSegmLeft + incNE; + segmLeft.x++; + } else // Nord + { + dSegmLeft = dSegmLeft + incN; + } + segmLeft.y++; + } + } + + // ----- parallelogramma (in alternativa a "parallelogrammoide circolare") + + // N.B. le coordinate sono relative ad un sist. di rif. con l'origine sul + // centro + // del cerchio inferiore + + // retta destra di equaz. alpha * x + beta * y + gammaRight = 0 + // retta sinistra di equaz. alpha * x + beta * y + gammaLeft = 0 + + yMin = std::max(a.y + cutIn + 1, 0) - a.y; // clipping y + yMax = std::min(b.y - cutIn - 1, ly - 1) - a.y; // clipping y + if (m <= 1) { + // midpoint algorithm; le scanline vengono disegnate solo + // sul NordEst. L'ultima scanline non viene disegnata + TPoint segmRight( + tceil((yMin + 0.5 - rightDown.y) / mParall + rightDown.x) - 1, yMin); + TPoint segmLeft = + TPoint(tceil((yMin - 0.5 - leftDown.y) / mParall + leftDown.x), yMin); + int dSegmRight = tfloor(alpha * (segmRight.x + 1) + + beta * (segmRight.y + 0.5) + gammaRight); + int dSegmLeft = tfloor(alpha * (segmLeft.x + 1) + + beta * (segmLeft.y + 0.5) + gammaLeft); + while (segmRight.y <= yMax) { + if (dSegmRight < 0) // segmRight a Est + { + dSegmRight = dSegmRight + incE; + segmRight.x++; + } else // segmRight a NordEst + { + int xMin, xMax; + if (k > 0) { + xMin = + std::max(a.x + std::max(segmLeft.x, xSegmMin), 0); // clipping x + xMax = std::min(a.x + std::min(segmRight.x, xSegmMax), + lx - 1); // clipping x + } else { + xMin = std::max(a.x - std::min(segmRight.x, xSegmMax), + 0); // clipping x + ritorno alle + xMax = std::min(a.x - std::max(segmLeft.x, xSegmMin), + lx - 1); // coordinate "di schermo" + } + + TPixel32 *p = ras->pixels(segmRight.y + a.y) + xMin; + TPixel32 *q = p + (xMax - xMin); + + while (p <= q) *p++ = col; + + dSegmRight = dSegmRight + incNE; + segmRight.x++; + segmRight.y++; + + while (dSegmLeft < 0) // segmLeft a Est + { + dSegmLeft = dSegmLeft + incE; + segmLeft.x++; + } + // segmLeft a NordEst + dSegmLeft = dSegmLeft + incNE; + segmLeft.x++; + segmLeft.y++; + } + } + } else // m>1 + { + // midpoint algorithm; le scanline vengono disegnate sempre + TPoint segmRight(tround((yMin - rightDown.y) / mParall + rightDown.x), + yMin); + TPoint segmLeft(tround((yMin - leftDown.y) / mParall + leftDown.x), yMin); + int dSegmRight = tfloor(alpha * (segmRight.x + 0.5) + + beta * (segmRight.y + 1) + gammaRight); + int dSegmLeft = tfloor(alpha * (segmLeft.x + 0.5) + + beta * (segmLeft.y + 1) + gammaLeft); + while (segmRight.y <= yMax) { + int xMin, xMax; + if (k > 0) { + xMin = std::max(a.x + segmLeft.x, 0); // clipping x + xMax = std::min(a.x + segmRight.x, lx - 1); // clipping x + } else { + xMin = std::max(a.x - segmRight.x, 0); // clipping x + ritorno alle + xMax = std::min(a.x - segmLeft.x, lx - 1); // coordinate "di schermo" + } + + TPixel32 *p = ras->pixels(segmRight.y + a.y) + xMin; + TPixel32 *q = p + (xMax - xMin); + + while (p <= q) *p++ = col; + + if (dSegmRight <= 0) // segmRight a NordEst + { + dSegmRight = dSegmRight + incNE; + segmRight.x++; + } else // segmRight a Nord + { + dSegmRight = dSegmRight + incN; + } + segmRight.y++; + + if (dSegmLeft <= 0) // segmLeft a NordEst + { + dSegmLeft = dSegmLeft + incNE; + segmLeft.x++; + } else // segmLeft a Nord + { + dSegmLeft = dSegmLeft + incN; + } + } + } + + // ---- parallelogrammoide circolare (in alternativa a parallelogramma) + + // N.B. coordinate di schermo (riflessione per k<0 ) + + yMin = std::max(b.y - cutIn, 0); + yMax = std::min(a.y + cutIn, ly - 1); + for (y = yMin; y <= yMax; y++) { + int xMin, xMax; + if (k > 0) { + xMin = std::max(a.x - halfCord.getCord(abs(y - a.y)), 0); // clipping x + xMax = std::min(b.x + halfCord.getCord(abs(b.y - y)), + lx - 1); // clipping x + } else { + xMin = std::max(b.x - halfCord.getCord(abs(b.y - y)), + 0); // clipping x + ritorno alle + xMax = std::min(a.x + halfCord.getCord(abs(y - a.y)), + lx - 1); // coordinate "di schermo" + } + TPixel32 *p = ras->pixels(y) + xMin; + TPixel32 *q = p + (xMax - xMin); + while (p <= q) *p++ = col; + } + ras->unlock(); } diff --git a/toonz/sources/common/trop/loop_macros.h b/toonz/sources/common/trop/loop_macros.h index f5d20c7..d13846f 100644 --- a/toonz/sources/common/trop/loop_macros.h +++ b/toonz/sources/common/trop/loop_macros.h @@ -4,333 +4,327 @@ #define LOOP_MACROS_INCLUDED /* - assert ((0 <= xI) && (xI <= up->getLx() - 1) && \ - (0 <= yI) && (yI <= up->getLy() - 1) ); \ + assert ((0 <= xI) && (xI <= up->getLx() - 1) && \ + (0 <= yI) && (yI <= up->getLy() - 1) ); \ */ -#define INTERNAL_LOOP_THE_FIRST \ - xL += deltaXL; \ - yL += deltaYL; \ - xI = xL >> PADN; \ - yI = yL >> PADN; \ - upPix00 = upBasePix + (yI * upWrap + xI); \ - upPix10 = upPix00 + 1; \ - upPix01 = upPix00 + upWrap; \ - upPix11 = upPix00 + upWrap + 1; \ - xWeight1 = (xL & MASKN); \ - xWeight0 = (1 << PADN) - xWeight1; \ - yWeight1 = (yL & MASKN); \ - yWeight0 = (1 << PADN) - yWeight1; \ - c1 = MULT_2_X_16BIT(upPix00->r, upPix00->g, xWeight0); \ - c3 = MULT_2_X_16BIT(upPix00->b, upPix01->r, xWeight0); \ - c5 = MULT_2_X_16BIT(upPix01->g, upPix01->b, xWeight0); \ - c2 = MULT_2_X_16BIT(upPix10->r, upPix10->g, xWeight1); \ - c4 = MULT_2_X_16BIT(upPix10->b, upPix11->r, xWeight1); \ - c6 = MULT_2_X_16BIT(upPix11->g, upPix11->b, xWeight1); \ - s_gb = (c5 + c6) >> 16; \ - gColUpTmp = s_gb >> 32; \ - bColUpTmp = s_gb & 0x1FF; \ - s_br = (c3 + c4) >> 16; \ - bColDownTmp = s_br >> 32; \ - rColUpTmp = s_br & 0x1FF; \ - s_rg = (c1 + c2) >> 16; \ - rColDownTmp = s_rg >> 32; \ - gColDownTmp = s_rg & 0x1FF; \ - rCol = \ - (unsigned char)((yWeight0 * rColDownTmp + yWeight1 * rColUpTmp) >> PADN); \ - gCol = \ - (unsigned char)((yWeight0 * gColDownTmp + yWeight1 * gColUpTmp) >> PADN); \ - bCol = \ - (unsigned char)((yWeight0 * bColDownTmp + yWeight1 * bColUpTmp) >> PADN); \ - *dnPix = TPixel32(rCol, gCol, bCol, upPix00->m); +#define INTERNAL_LOOP_THE_FIRST \ + xL += deltaXL; \ + yL += deltaYL; \ + xI = xL >> PADN; \ + yI = yL >> PADN; \ + upPix00 = upBasePix + (yI * upWrap + xI); \ + upPix10 = upPix00 + 1; \ + upPix01 = upPix00 + upWrap; \ + upPix11 = upPix00 + upWrap + 1; \ + xWeight1 = (xL & MASKN); \ + xWeight0 = (1 << PADN) - xWeight1; \ + yWeight1 = (yL & MASKN); \ + yWeight0 = (1 << PADN) - yWeight1; \ + c1 = MULT_2_X_16BIT(upPix00->r, upPix00->g, xWeight0); \ + c3 = MULT_2_X_16BIT(upPix00->b, upPix01->r, xWeight0); \ + c5 = MULT_2_X_16BIT(upPix01->g, upPix01->b, xWeight0); \ + c2 = MULT_2_X_16BIT(upPix10->r, upPix10->g, xWeight1); \ + c4 = MULT_2_X_16BIT(upPix10->b, upPix11->r, xWeight1); \ + c6 = MULT_2_X_16BIT(upPix11->g, upPix11->b, xWeight1); \ + s_gb = (c5 + c6) >> 16; \ + gColUpTmp = s_gb >> 32; \ + bColUpTmp = s_gb & 0x1FF; \ + s_br = (c3 + c4) >> 16; \ + bColDownTmp = s_br >> 32; \ + rColUpTmp = s_br & 0x1FF; \ + s_rg = (c1 + c2) >> 16; \ + rColDownTmp = s_rg >> 32; \ + gColDownTmp = s_rg & 0x1FF; \ + rCol = (unsigned char)((yWeight0 * rColDownTmp + yWeight1 * rColUpTmp) >> \ + PADN); \ + gCol = (unsigned char)((yWeight0 * gColDownTmp + yWeight1 * gColUpTmp) >> \ + PADN); \ + bCol = (unsigned char)((yWeight0 * bColDownTmp + yWeight1 * bColUpTmp) >> \ + PADN); \ + *dnPix = TPixel32(rCol, gCol, bCol, upPix00->m); // ------------------------------------------------------------------------------------------------- -#define INTERNAL_LOOP_THE_FIRST_X_2 \ - INTERNAL_LOOP_THE_FIRST \ - ++dnPix; \ - INTERNAL_LOOP_THE_FIRST +#define INTERNAL_LOOP_THE_FIRST_X_2 \ + INTERNAL_LOOP_THE_FIRST \ + ++dnPix; \ + INTERNAL_LOOP_THE_FIRST // ------------------------------------------------------------------------------------------------- -#define INTERNAL_LOOP_THE_FIRST_X_4 \ - INTERNAL_LOOP_THE_FIRST_X_2 \ - ++dnPix; \ - INTERNAL_LOOP_THE_FIRST_X_2 +#define INTERNAL_LOOP_THE_FIRST_X_4 \ + INTERNAL_LOOP_THE_FIRST_X_2 \ + ++dnPix; \ + INTERNAL_LOOP_THE_FIRST_X_2 // ------------------------------------------------------------------------------------------------- -#define INTERNAL_LOOP_THE_FIRST_X_8 \ - INTERNAL_LOOP_THE_FIRST_X_4 \ - ++dnPix; \ - INTERNAL_LOOP_THE_FIRST_X_4 +#define INTERNAL_LOOP_THE_FIRST_X_8 \ + INTERNAL_LOOP_THE_FIRST_X_4 \ + ++dnPix; \ + INTERNAL_LOOP_THE_FIRST_X_4 // ------------------------------------------------------------------------------------------------- -#define INTERNAL_LOOP_THE_FIRST_X_16 \ - INTERNAL_LOOP_THE_FIRST_X_8 \ - ++dnPix; \ - INTERNAL_LOOP_THE_FIRST_X_8 +#define INTERNAL_LOOP_THE_FIRST_X_16 \ + INTERNAL_LOOP_THE_FIRST_X_8 \ + ++dnPix; \ + INTERNAL_LOOP_THE_FIRST_X_8 // ------------------------------------------------------------------------------------------------- -#define INTERNAL_LOOP_THE_FIRST_X_32 \ - INTERNAL_LOOP_THE_FIRST_X_16 \ - ++dnPix; \ - INTERNAL_LOOP_THE_FIRST_X_16 +#define INTERNAL_LOOP_THE_FIRST_X_32 \ + INTERNAL_LOOP_THE_FIRST_X_16 \ + ++dnPix; \ + INTERNAL_LOOP_THE_FIRST_X_16 // ------------------------------------------------------------------------------------------------- -#define EXTERNAL_LOOP_THE_FIRST \ - a = invAff * TPointD(xMin, y); \ - xL0 = tround(a.x * (1 << PADN)); \ - yL0 = tround(a.y * (1 << PADN)); \ - kMinX = 0; \ - kMaxX = xMax - xMin; \ - kMinY = 0; \ - kMaxY = xMax - xMin; \ - if (deltaXL == 0) { \ - if ((xL0 < 0) || (lxPred < xL0)) \ - continue; \ - } else if (deltaXL > 0) { \ - if (lxPred < xL0) \ - continue; \ - kMaxX = (lxPred - xL0) / deltaXL; \ - if (xL0 < 0) { \ - kMinX = ((-xL0) + deltaXL - 1) / deltaXL; \ - } \ - } else { \ - if (xL0 < 0) \ - continue; \ - kMaxX = xL0 / (-deltaXL); \ - if (lxPred < xL0) { \ - kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); \ - } \ - } \ - if (deltaYL == 0) { \ - if ((yL0 < 0) || (lyPred < yL0)) \ - continue; \ - } else if (deltaYL > 0) { \ - if (lyPred < yL0) \ - continue; \ - kMaxY = (lyPred - yL0) / deltaYL; \ - if (yL0 < 0) { \ - kMinY = ((-yL0) + deltaYL - 1) / deltaYL; \ - } \ - } else { \ - if (yL0 < 0) \ - continue; \ - kMaxY = yL0 / (-deltaYL); \ - if (lyPred < yL0) { \ - kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); \ - } \ - } \ - kMin = std::max({kMinX, kMinY, (int)0}); \ - kMax = std::min(kMaxX, kMaxY, xMax - xMin); \ - dnPix = dnRow + xMin + kMin; \ - dnEndPix = dnRow + xMin + kMax + 1; \ - xL = xL0 + (kMin - 1) * deltaXL; \ - yL = yL0 + (kMin - 1) * deltaYL; \ - for (; dnPix < dnEndPix - 32; ++dnPix) { \ - INTERNAL_LOOP_THE_FIRST_X_32; \ - } \ - for (; dnPix < dnEndPix - 16; ++dnPix) { \ - INTERNAL_LOOP_THE_FIRST_X_16; \ - } \ - for (; dnPix < dnEndPix - 8; ++dnPix) { \ - INTERNAL_LOOP_THE_FIRST_X_8; \ - } \ - for (; dnPix < dnEndPix - 4; ++dnPix) { \ - INTERNAL_LOOP_THE_FIRST_X_4; \ - } \ - for (; dnPix < dnEndPix - 2; ++dnPix) { \ - INTERNAL_LOOP_THE_FIRST_X_2; \ - } \ - for (; dnPix < dnEndPix; ++dnPix) { \ - INTERNAL_LOOP_THE_FIRST \ - } +#define EXTERNAL_LOOP_THE_FIRST \ + a = invAff * TPointD(xMin, y); \ + xL0 = tround(a.x * (1 << PADN)); \ + yL0 = tround(a.y * (1 << PADN)); \ + kMinX = 0; \ + kMaxX = xMax - xMin; \ + kMinY = 0; \ + kMaxY = xMax - xMin; \ + if (deltaXL == 0) { \ + if ((xL0 < 0) || (lxPred < xL0)) continue; \ + } else if (deltaXL > 0) { \ + if (lxPred < xL0) continue; \ + kMaxX = (lxPred - xL0) / deltaXL; \ + if (xL0 < 0) { \ + kMinX = ((-xL0) + deltaXL - 1) / deltaXL; \ + } \ + } else { \ + if (xL0 < 0) continue; \ + kMaxX = xL0 / (-deltaXL); \ + if (lxPred < xL0) { \ + kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); \ + } \ + } \ + if (deltaYL == 0) { \ + if ((yL0 < 0) || (lyPred < yL0)) continue; \ + } else if (deltaYL > 0) { \ + if (lyPred < yL0) continue; \ + kMaxY = (lyPred - yL0) / deltaYL; \ + if (yL0 < 0) { \ + kMinY = ((-yL0) + deltaYL - 1) / deltaYL; \ + } \ + } else { \ + if (yL0 < 0) continue; \ + kMaxY = yL0 / (-deltaYL); \ + if (lyPred < yL0) { \ + kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); \ + } \ + } \ + kMin = std::max({kMinX, kMinY, (int)0}); \ + kMax = std::min(kMaxX, kMaxY, xMax - xMin); \ + dnPix = dnRow + xMin + kMin; \ + dnEndPix = dnRow + xMin + kMax + 1; \ + xL = xL0 + (kMin - 1) * deltaXL; \ + yL = yL0 + (kMin - 1) * deltaYL; \ + for (; dnPix < dnEndPix - 32; ++dnPix) { \ + INTERNAL_LOOP_THE_FIRST_X_32; \ + } \ + for (; dnPix < dnEndPix - 16; ++dnPix) { \ + INTERNAL_LOOP_THE_FIRST_X_16; \ + } \ + for (; dnPix < dnEndPix - 8; ++dnPix) { \ + INTERNAL_LOOP_THE_FIRST_X_8; \ + } \ + for (; dnPix < dnEndPix - 4; ++dnPix) { \ + INTERNAL_LOOP_THE_FIRST_X_4; \ + } \ + for (; dnPix < dnEndPix - 2; ++dnPix) { \ + INTERNAL_LOOP_THE_FIRST_X_2; \ + } \ + for (; dnPix < dnEndPix; ++dnPix) { \ + INTERNAL_LOOP_THE_FIRST \ + } // ------------------------------------------------------------------------------------------------- -#define EXTERNAL_LOOP_THE_FIRST_X_2 \ - EXTERNAL_LOOP_THE_FIRST \ - ++y; \ - dnRow += dnWrap; \ - EXTERNAL_LOOP_THE_FIRST +#define EXTERNAL_LOOP_THE_FIRST_X_2 \ + EXTERNAL_LOOP_THE_FIRST \ + ++y; \ + dnRow += dnWrap; \ + EXTERNAL_LOOP_THE_FIRST // ------------------------------------------------------------------------------------------------- -#define EXTERNAL_LOOP_THE_FIRST_X_4 \ - EXTERNAL_LOOP_THE_FIRST_X_2 \ - ++y; \ - dnRow += dnWrap; \ - EXTERNAL_LOOP_THE_FIRST_X_2 +#define EXTERNAL_LOOP_THE_FIRST_X_4 \ + EXTERNAL_LOOP_THE_FIRST_X_2 \ + ++y; \ + dnRow += dnWrap; \ + EXTERNAL_LOOP_THE_FIRST_X_2 // ------------------------------------------------------------------------------------------------- -#define EXTERNAL_LOOP_THE_FIRST_X_8 \ - EXTERNAL_LOOP_THE_FIRST_X_4 \ - ++y; \ - dnRow += dnWrap; \ - EXTERNAL_LOOP_THE_FIRST_X_4 +#define EXTERNAL_LOOP_THE_FIRST_X_8 \ + EXTERNAL_LOOP_THE_FIRST_X_4 \ + ++y; \ + dnRow += dnWrap; \ + EXTERNAL_LOOP_THE_FIRST_X_4 // ------------------------------------------------------------------------------------------------- -#define EXTERNAL_LOOP_THE_FIRST_X_16 \ - EXTERNAL_LOOP_THE_FIRST_X_8 \ - ++y; \ - dnRow += dnWrap; \ - EXTERNAL_LOOP_THE_FIRST_X_8 +#define EXTERNAL_LOOP_THE_FIRST_X_16 \ + EXTERNAL_LOOP_THE_FIRST_X_8 \ + ++y; \ + dnRow += dnWrap; \ + EXTERNAL_LOOP_THE_FIRST_X_8 // ------------------------------------------------------------------------------------------------- -#define EXTERNAL_LOOP_THE_FIRST_X_32 \ - EXTERNAL_LOOP_THE_FIRST_X_16 \ - ++y; \ - dnRow += dnWrap; \ - EXTERNAL_LOOP_THE_FIRST_X_16 +#define EXTERNAL_LOOP_THE_FIRST_X_32 \ + EXTERNAL_LOOP_THE_FIRST_X_16 \ + ++y; \ + dnRow += dnWrap; \ + EXTERNAL_LOOP_THE_FIRST_X_16 /* - assert ((0 <= xI) && (xI <= up->getLx() - 1) && \ - (0 <= yI) && (yI <= up->getLy() - 1) ); \ + assert ((0 <= xI) && (xI <= up->getLx() - 1) && \ + (0 <= yI) && (yI <= up->getLy() - 1) ); \ */ // ------------------------------------------------------------------------------------------------- -#define INTERNAL_LOOP_THE_SECOND \ - xL += deltaXL; \ - xI = xL >> PADN; \ - upPix00 = upBasePix + (yI * upWrap + xI); \ - upPix10 = upPix00 + 1; \ - upPix01 = upPix00 + upWrap; \ - upPix11 = upPix00 + upWrap + 1; \ - xWeight1 = (xL & MASKN); \ - xWeight0 = (1 << PADN) - xWeight1; \ - c1 = MULT_2_X_16BIT(upPix00->r, upPix00->g, xWeight0); \ - c3 = MULT_2_X_16BIT(upPix00->b, upPix01->r, xWeight0); \ - c5 = MULT_2_X_16BIT(upPix01->g, upPix01->b, xWeight0); \ - c2 = MULT_2_X_16BIT(upPix10->r, upPix10->g, xWeight1); \ - c4 = MULT_2_X_16BIT(upPix10->b, upPix11->r, xWeight1); \ - c6 = MULT_2_X_16BIT(upPix11->g, upPix11->b, xWeight1); \ - s_gb = (c5 + c6) >> 16; \ - gColUpTmp = s_gb >> 32; \ - bColUpTmp = s_gb & 0x1FF; \ - s_br = (c3 + c4) >> 16; \ - bColDownTmp = s_br >> 32; \ - rColUpTmp = s_br & 0x1FF; \ - s_rg = (c1 + c2) >> 16; \ - rColDownTmp = s_rg >> 32; \ - gColDownTmp = s_rg & 0x1FF; \ - rCol = \ - (unsigned char)((yWeight0 * rColDownTmp + yWeight1 * rColUpTmp) >> PADN); \ - gCol = \ - (unsigned char)((yWeight0 * gColDownTmp + yWeight1 * gColUpTmp) >> PADN); \ - bCol = \ - (unsigned char)((yWeight0 * bColDownTmp + yWeight1 * bColUpTmp) >> PADN); \ - *dnPix = TPixel32(rCol, gCol, bCol, upPix00->m); +#define INTERNAL_LOOP_THE_SECOND \ + xL += deltaXL; \ + xI = xL >> PADN; \ + upPix00 = upBasePix + (yI * upWrap + xI); \ + upPix10 = upPix00 + 1; \ + upPix01 = upPix00 + upWrap; \ + upPix11 = upPix00 + upWrap + 1; \ + xWeight1 = (xL & MASKN); \ + xWeight0 = (1 << PADN) - xWeight1; \ + c1 = MULT_2_X_16BIT(upPix00->r, upPix00->g, xWeight0); \ + c3 = MULT_2_X_16BIT(upPix00->b, upPix01->r, xWeight0); \ + c5 = MULT_2_X_16BIT(upPix01->g, upPix01->b, xWeight0); \ + c2 = MULT_2_X_16BIT(upPix10->r, upPix10->g, xWeight1); \ + c4 = MULT_2_X_16BIT(upPix10->b, upPix11->r, xWeight1); \ + c6 = MULT_2_X_16BIT(upPix11->g, upPix11->b, xWeight1); \ + s_gb = (c5 + c6) >> 16; \ + gColUpTmp = s_gb >> 32; \ + bColUpTmp = s_gb & 0x1FF; \ + s_br = (c3 + c4) >> 16; \ + bColDownTmp = s_br >> 32; \ + rColUpTmp = s_br & 0x1FF; \ + s_rg = (c1 + c2) >> 16; \ + rColDownTmp = s_rg >> 32; \ + gColDownTmp = s_rg & 0x1FF; \ + rCol = (unsigned char)((yWeight0 * rColDownTmp + yWeight1 * rColUpTmp) >> \ + PADN); \ + gCol = (unsigned char)((yWeight0 * gColDownTmp + yWeight1 * gColUpTmp) >> \ + PADN); \ + bCol = (unsigned char)((yWeight0 * bColDownTmp + yWeight1 * bColUpTmp) >> \ + PADN); \ + *dnPix = TPixel32(rCol, gCol, bCol, upPix00->m); // ------------------------------------------------------------------------------------------------- -#define INTERNAL_LOOP_THE_SECOND_X_2 \ - INTERNAL_LOOP_THE_SECOND \ - ++dnPix; \ - INTERNAL_LOOP_THE_SECOND +#define INTERNAL_LOOP_THE_SECOND_X_2 \ + INTERNAL_LOOP_THE_SECOND \ + ++dnPix; \ + INTERNAL_LOOP_THE_SECOND // ------------------------------------------------------------------------------------------------- -#define INTERNAL_LOOP_THE_SECOND_X_4 \ - INTERNAL_LOOP_THE_SECOND_X_2 \ - ++dnPix; \ - INTERNAL_LOOP_THE_SECOND_X_2 +#define INTERNAL_LOOP_THE_SECOND_X_4 \ + INTERNAL_LOOP_THE_SECOND_X_2 \ + ++dnPix; \ + INTERNAL_LOOP_THE_SECOND_X_2 // ------------------------------------------------------------------------------------------------- -#define INTERNAL_LOOP_THE_SECOND_X_8 \ - INTERNAL_LOOP_THE_SECOND_X_4 \ - ++dnPix; \ - INTERNAL_LOOP_THE_SECOND_X_4 +#define INTERNAL_LOOP_THE_SECOND_X_8 \ + INTERNAL_LOOP_THE_SECOND_X_4 \ + ++dnPix; \ + INTERNAL_LOOP_THE_SECOND_X_4 // ------------------------------------------------------------------------------------------------- -#define INTERNAL_LOOP_THE_SECOND_X_16 \ - INTERNAL_LOOP_THE_SECOND_X_8 \ - ++dnPix; \ - INTERNAL_LOOP_THE_SECOND_X_8 +#define INTERNAL_LOOP_THE_SECOND_X_16 \ + INTERNAL_LOOP_THE_SECOND_X_8 \ + ++dnPix; \ + INTERNAL_LOOP_THE_SECOND_X_8 // ------------------------------------------------------------------------------------------------- -#define INTERNAL_LOOP_THE_SECOND_X_32 \ - INTERNAL_LOOP_THE_SECOND_X_16 \ - ++dnPix; \ - INTERNAL_LOOP_THE_SECOND_X_16 +#define INTERNAL_LOOP_THE_SECOND_X_32 \ + INTERNAL_LOOP_THE_SECOND_X_16 \ + ++dnPix; \ + INTERNAL_LOOP_THE_SECOND_X_16 // ------------------------------------------------------------------------------------------------- -#define EXTERNAL_LOOP_THE_SECOND \ - xL = xL0 + (kMinX - 1) * deltaXL; \ - yL += deltaYL; \ - yI = yL >> PADN; \ - yWeight1 = (yL & MASKN); \ - yWeight0 = (1 << PADN) - yWeight1; \ - dnPix = dnRow + xMin + kMinX; \ - dnEndPix = dnRow + xMin + kMaxX + 1; \ - for (; dnPix < dnEndPix - 32; ++dnPix) { \ - INTERNAL_LOOP_THE_SECOND_X_32; \ - } \ - for (; dnPix < dnEndPix - 16; ++dnPix) { \ - INTERNAL_LOOP_THE_SECOND_X_16; \ - } \ - for (; dnPix < dnEndPix - 8; ++dnPix) { \ - INTERNAL_LOOP_THE_SECOND_X_8; \ - } \ - for (; dnPix < dnEndPix - 4; ++dnPix) { \ - INTERNAL_LOOP_THE_SECOND_X_4; \ - } \ - for (; dnPix < dnEndPix - 2; ++dnPix) { \ - INTERNAL_LOOP_THE_SECOND_X_2; \ - } \ - for (; dnPix < dnEndPix; ++dnPix) { \ - INTERNAL_LOOP_THE_SECOND \ - } +#define EXTERNAL_LOOP_THE_SECOND \ + xL = xL0 + (kMinX - 1) * deltaXL; \ + yL += deltaYL; \ + yI = yL >> PADN; \ + yWeight1 = (yL & MASKN); \ + yWeight0 = (1 << PADN) - yWeight1; \ + dnPix = dnRow + xMin + kMinX; \ + dnEndPix = dnRow + xMin + kMaxX + 1; \ + for (; dnPix < dnEndPix - 32; ++dnPix) { \ + INTERNAL_LOOP_THE_SECOND_X_32; \ + } \ + for (; dnPix < dnEndPix - 16; ++dnPix) { \ + INTERNAL_LOOP_THE_SECOND_X_16; \ + } \ + for (; dnPix < dnEndPix - 8; ++dnPix) { \ + INTERNAL_LOOP_THE_SECOND_X_8; \ + } \ + for (; dnPix < dnEndPix - 4; ++dnPix) { \ + INTERNAL_LOOP_THE_SECOND_X_4; \ + } \ + for (; dnPix < dnEndPix - 2; ++dnPix) { \ + INTERNAL_LOOP_THE_SECOND_X_2; \ + } \ + for (; dnPix < dnEndPix; ++dnPix) { \ + INTERNAL_LOOP_THE_SECOND \ + } // ------------------------------------------------------------------------------------------------- -#define EXTERNAL_LOOP_THE_SECOND_X_2 \ - EXTERNAL_LOOP_THE_SECOND \ - ++kY; \ - dnRow += dnWrap; \ - EXTERNAL_LOOP_THE_SECOND +#define EXTERNAL_LOOP_THE_SECOND_X_2 \ + EXTERNAL_LOOP_THE_SECOND \ + ++kY; \ + dnRow += dnWrap; \ + EXTERNAL_LOOP_THE_SECOND // ------------------------------------------------------------------------------------------------- -#define EXTERNAL_LOOP_THE_SECOND_X_4 \ - EXTERNAL_LOOP_THE_SECOND_X_2 \ - ++kY; \ - dnRow += dnWrap; \ - EXTERNAL_LOOP_THE_SECOND_X_2 +#define EXTERNAL_LOOP_THE_SECOND_X_4 \ + EXTERNAL_LOOP_THE_SECOND_X_2 \ + ++kY; \ + dnRow += dnWrap; \ + EXTERNAL_LOOP_THE_SECOND_X_2 // ------------------------------------------------------------------------------------------------- -#define EXTERNAL_LOOP_THE_SECOND_X_8 \ - EXTERNAL_LOOP_THE_SECOND_X_4 \ - ++kY; \ - dnRow += dnWrap; \ - EXTERNAL_LOOP_THE_SECOND_X_4 +#define EXTERNAL_LOOP_THE_SECOND_X_8 \ + EXTERNAL_LOOP_THE_SECOND_X_4 \ + ++kY; \ + dnRow += dnWrap; \ + EXTERNAL_LOOP_THE_SECOND_X_4 // ------------------------------------------------------------------------------------------------- -#define EXTERNAL_LOOP_THE_SECOND_X_16 \ - EXTERNAL_LOOP_THE_SECOND_X_8 \ - ++kY; \ - dnRow += dnWrap; \ - EXTERNAL_LOOP_THE_SECOND_X_8 +#define EXTERNAL_LOOP_THE_SECOND_X_16 \ + EXTERNAL_LOOP_THE_SECOND_X_8 \ + ++kY; \ + dnRow += dnWrap; \ + EXTERNAL_LOOP_THE_SECOND_X_8 // ------------------------------------------------------------------------------------------------- -#define EXTERNAL_LOOP_THE_SECOND_X_32 \ - EXTERNAL_LOOP_THE_SECOND_X_16 \ - ++kY; \ - dnRow += dnWrap; \ - EXTERNAL_LOOP_THE_SECOND_X_16 +#define EXTERNAL_LOOP_THE_SECOND_X_32 \ + EXTERNAL_LOOP_THE_SECOND_X_16 \ + ++kY; \ + dnRow += dnWrap; \ + EXTERNAL_LOOP_THE_SECOND_X_16 #endif diff --git a/toonz/sources/common/trop/optimize_for_lp64.h b/toonz/sources/common/trop/optimize_for_lp64.h index c0ba7f1..0ed051c 100644 --- a/toonz/sources/common/trop/optimize_for_lp64.h +++ b/toonz/sources/common/trop/optimize_for_lp64.h @@ -12,61 +12,61 @@ ***************************************************************************** ____________OSS 1:___________________________________________________________ - + se devo fare DUE MOLTIPLICAZIONI 13 bit * 8 bit posso farle in un colpo solo, ad esempio: siano X = xxxxxxxxxxxxx - S = ssssssss - Y = yyyyyyyyyyyyy + S = ssssssss + Y = yyyyyyyyyyyyy T = tttttttt - e devo calcolare + e devo calcolare U = X * S V = Y * T posso farlo in un colpo solo impacchettando i bit cosi': A = X 0 00000000 Y = xxxxxxxxxxxxx 0 00000000 yyyyyyyyyyyyy B = 00000 S 0 00000000 00000 T = 00000ssssssss 0 00000000 00000tttttttt - - ora se faccio C = A * B si ha - C = U ?????????????????????? V = + ora se faccio C = A * B si ha + + C = U ?????????????????????? V = = uuuuuuuuuuuuuuuuuuuuu ?????????????????????? vvvvvvvvvvvvvvvvvvvvv dove C e' di 64 bit; cioe' i primi 21 bit sono X * S = U e gli ultimi 21 sono Y * T = V ____________OSS 2:___________________________________________________________ - - - se devo fare DUE MOLTIPLICAZIONI 16 bit * 16 bit del tipo + + + se devo fare DUE MOLTIPLICAZIONI 16 bit * 16 bit del tipo X * S = U Y * S = V con - + #X = 16, #Y = 16, #S = 16 - - (dove l'operatore '#' da' come risultato il numero di bit di cui e' composto + + (dove l'operatore '#' da' come risultato il numero di bit di cui e' composto un numero intero) posso farle tutte e due in un solo colpo impacchettando i bit cosi': - + O = 0000000000000000, #O = 16 A = X O Y , #A = 48 B = S , #B = 16 C = A * B , #C = 64 - + dove i primi 32 bit sono X * S e i secondi 32 bit sono Y * S ____________OSS 3:___________________________________________________________ - - - se devo fare QUATTRO MOLTIPLICAZIONI 8 bit * 8 bit del tipo + + + se devo fare QUATTRO MOLTIPLICAZIONI 8 bit * 8 bit del tipo X * S = I #X = 8, #S = 8, #I = 16 Y * S = J #Y = 8, #S = 8, #J = 16 Z * S = K #Z = 8, #S = 8, #K = 16 @@ -74,13 +74,13 @@ posso farle tutte e due in un solo colpo impacchettando i bit cosi': - + O = 00000000 #O = 8 C = XOYOZOW * OOOOOOS #C = 64 - - dove - I sono i primi 16 bit, - J sono i secondi 16 bit, + + dove + I sono i primi 16 bit, + J sono i secondi 16 bit, K sono i terzi 16 bit, L i quarti 16 bit _____________________________________________________________________________ @@ -149,37 +149,32 @@ UINT64 mult_2_x_16bit ( UINT16 a1, UINT16 a2, /* ------------------------------------------------------------------------- */ -#define ADD_3_X_16BIT(a1, a2, a3, b1, b2, b3) \ - (0L | (UINT64)(a1) << 34 | (UINT64)(a2) << 17 | (a3)) + \ - (0L | (UINT64)(b1) << 34 | (UINT64)(b2) << 17 | (b3)) +#define ADD_3_X_16BIT(a1, a2, a3, b1, b2, b3) \ + (0L | (UINT64)(a1) << 34 | (UINT64)(a2) << 17 | (a3)) + \ + (0L | (UINT64)(b1) << 34 | (UINT64)(b2) << 17 | (b3)) -inline UINT64 add_3_x_16bit(UINT16 a1, UINT16 a2, UINT16 a3, - UINT16 b1, UINT16 b2, UINT16 b3) -{ - return (0L | (UINT64)a1 << 34 | (UINT64)a2 << 17 | a3) + - (0L | (UINT64)b1 << 34 | (UINT64)b2 << 17 | b3); +inline UINT64 add_3_x_16bit(UINT16 a1, UINT16 a2, UINT16 a3, UINT16 b1, + UINT16 b2, UINT16 b3) { + return (0L | (UINT64)a1 << 34 | (UINT64)a2 << 17 | a3) + + (0L | (UINT64)b1 << 34 | (UINT64)b2 << 17 | b3); } /* ------------------------------------------------------------------------- */ -#define ADD_2_X_24BIT(a1, a2, b1, b2) \ - (0L | (UINT64)(a1) << 25 | (a2)) + (0L | (UINT64)(b1) << 25 | (b2)) +#define ADD_2_X_24BIT(a1, a2, b1, b2) \ + (0L | (UINT64)(a1) << 25 | (a2)) + (0L | (UINT64)(b1) << 25 | (b2)) -inline UINT50 add_2_x_24bit(UINT24 a1, UINT24 a2, - UINT24 b1, UINT24 b2) -{ - return (0L | (UINT64)a1 << 25 | a2) + - (0L | (UINT64)b1 << 25 | b2); +inline UINT50 add_2_x_24bit(UINT24 a1, UINT24 a2, UINT24 b1, UINT24 b2) { + return (0L | (UINT64)a1 << 25 | a2) + (0L | (UINT64)b1 << 25 | b2); } /* ------------------------------------------------------------------------- */ -#define MULT_2_X_16BIT(a1, a2, b) ((UINT64)b) * (((UINT64)(a1) << 32) | (UINT64)a2) +#define MULT_2_X_16BIT(a1, a2, b) \ + ((UINT64)b) * (((UINT64)(a1) << 32) | (UINT64)a2) -inline UINT64 mult_2_x_16bit(UINT16 a1, UINT16 a2, - UINT16 b) -{ - return (0L | (UINT64)a1 << 32 | a2) * b; +inline UINT64 mult_2_x_16bit(UINT16 a1, UINT16 a2, UINT16 b) { + return (0L | (UINT64)a1 << 32 | a2) * b; } #endif diff --git a/toonz/sources/common/trop/pixelselectors.h b/toonz/sources/common/trop/pixelselectors.h index 0b832db..17c6cb7 100644 --- a/toonz/sources/common/trop/pixelselectors.h +++ b/toonz/sources/common/trop/pixelselectors.h @@ -7,124 +7,131 @@ #include "tpixelgr.h" #include "tpixelcm.h" -namespace TRop -{ -namespace borders -{ +namespace TRop { +namespace borders { //**************************************************************** // Standard Pixel Selectors //**************************************************************** template -class PixelSelector -{ - bool m_skip; +class PixelSelector { + bool m_skip; public: - typedef Pix pixel_type; - typedef Pix value_type; + typedef Pix pixel_type; + typedef Pix value_type; public: - PixelSelector(bool onlyCorners = true) - : m_skip(onlyCorners) {} + PixelSelector(bool onlyCorners = true) : m_skip(onlyCorners) {} - value_type transparent() const { return pixel_type::Transparent; } - bool transparent(const pixel_type &pix) const { return (pix.m == 0); } + value_type transparent() const { return pixel_type::Transparent; } + bool transparent(const pixel_type &pix) const { return (pix.m == 0); } - value_type value(const pixel_type &pix) const { return pix; } - bool equal(const pixel_type &a, const pixel_type &b) const { return a == b; } + value_type value(const pixel_type &pix) const { return pix; } + bool equal(const pixel_type &a, const pixel_type &b) const { return a == b; } - void setSkip(bool skip) { m_skip = skip; } - bool skip(const value_type &prevLeftValue, const value_type &leftValue) const { return m_skip; } + void setSkip(bool skip) { m_skip = skip; } + bool skip(const value_type &prevLeftValue, + const value_type &leftValue) const { + return m_skip; + } }; //-------------------------------------------------------------------------------- template <> -class PixelSelector -{ - bool m_skip; - TPixelGR8 m_transpColor; +class PixelSelector { + bool m_skip; + TPixelGR8 m_transpColor; public: - typedef TPixelGR8 pixel_type; - typedef TPixelGR8 value_type; + typedef TPixelGR8 pixel_type; + typedef TPixelGR8 value_type; public: - PixelSelector(bool onlyCorners = true, - pixel_type transparentColor = pixel_type::White) - : m_skip(onlyCorners), m_transpColor(transparentColor) {} - - value_type transparent() const { return m_transpColor; } - bool transparent(const pixel_type &pix) const { return (pix == m_transpColor); } - - value_type value(const pixel_type &pix) const { return pix; } - bool equal(const pixel_type &a, const pixel_type &b) const { return a == b; } - - void setSkip(bool skip) { m_skip = skip; } - bool skip(const value_type &prevLeftValue, const value_type &leftValue) const { return m_skip; } + PixelSelector(bool onlyCorners = true, + pixel_type transparentColor = pixel_type::White) + : m_skip(onlyCorners), m_transpColor(transparentColor) {} + + value_type transparent() const { return m_transpColor; } + bool transparent(const pixel_type &pix) const { + return (pix == m_transpColor); + } + + value_type value(const pixel_type &pix) const { return pix; } + bool equal(const pixel_type &a, const pixel_type &b) const { return a == b; } + + void setSkip(bool skip) { m_skip = skip; } + bool skip(const value_type &prevLeftValue, + const value_type &leftValue) const { + return m_skip; + } }; //-------------------------------------------------------------------------------- template <> -class PixelSelector -{ - bool m_skip; - TPixelGR16 m_transpColor; +class PixelSelector { + bool m_skip; + TPixelGR16 m_transpColor; public: - typedef TPixelGR16 pixel_type; - typedef TPixelGR16 value_type; + typedef TPixelGR16 pixel_type; + typedef TPixelGR16 value_type; public: - PixelSelector(bool onlyCorners = true, - pixel_type transparentColor = pixel_type::White) - : m_skip(onlyCorners), m_transpColor(transparentColor) {} - - value_type transparent() const { return m_transpColor; } - bool transparent(const pixel_type &pix) const { return (pix == m_transpColor); } - - value_type value(const pixel_type &pix) const { return pix; } - bool equal(const pixel_type &a, const pixel_type &b) const { return a == b; } - - void setSkip(bool skip) { m_skip = skip; } - bool skip(const value_type &prevLeftValue, const value_type &leftValue) const { return m_skip; } + PixelSelector(bool onlyCorners = true, + pixel_type transparentColor = pixel_type::White) + : m_skip(onlyCorners), m_transpColor(transparentColor) {} + + value_type transparent() const { return m_transpColor; } + bool transparent(const pixel_type &pix) const { + return (pix == m_transpColor); + } + + value_type value(const pixel_type &pix) const { return pix; } + bool equal(const pixel_type &a, const pixel_type &b) const { return a == b; } + + void setSkip(bool skip) { m_skip = skip; } + bool skip(const value_type &prevLeftValue, + const value_type &leftValue) const { + return m_skip; + } }; //-------------------------------------------------------------------------------- template <> -class PixelSelector -{ - int m_tone; - bool m_skip; +class PixelSelector { + int m_tone; + bool m_skip; public: - typedef TPixelCM32 pixel_type; - typedef TUINT32 value_type; + typedef TPixelCM32 pixel_type; + typedef TUINT32 value_type; public: - PixelSelector(bool onlyCorners = true, int tone = 128) - : m_tone(tone), m_skip(onlyCorners) {} - - value_type transparent() const { return 0; } - bool transparent(const pixel_type &pix) const { return value(pix) == 0; } - - value_type value(const pixel_type &pix) const - { - return (pix.getTone() < m_tone) ? pix.getInk() : pix.getPaint(); - } - bool equal(const pixel_type &a, const pixel_type &b) const - { - return value(a) == value(b); - } - - void setSkip(bool skip) { m_skip = skip; } - bool skip(const value_type &prevLeftValue, const value_type &leftValue) const { return m_skip; } + PixelSelector(bool onlyCorners = true, int tone = 128) + : m_tone(tone), m_skip(onlyCorners) {} + + value_type transparent() const { return 0; } + bool transparent(const pixel_type &pix) const { return value(pix) == 0; } + + value_type value(const pixel_type &pix) const { + return (pix.getTone() < m_tone) ? pix.getInk() : pix.getPaint(); + } + bool equal(const pixel_type &a, const pixel_type &b) const { + return value(a) == value(b); + } + + void setSkip(bool skip) { m_skip = skip; } + bool skip(const value_type &prevLeftValue, + const value_type &leftValue) const { + return m_skip; + } }; } -} //namespace TRop::borders +} // namespace TRop::borders -#endif //PIXEL_SELECTORS_H +#endif // PIXEL_SELECTORS_H diff --git a/toonz/sources/common/trop/quickput.cpp b/toonz/sources/common/trop/quickput.cpp index 1384381..e30bd4d 100644 --- a/toonz/sources/common/trop/quickput.cpp +++ b/toonz/sources/common/trop/quickput.cpp @@ -15,9 +15,9 @@ #endif */ -//The following must be old IRIX code. Should be re-tested. -//It seems that gcc compiles it, but requiring a LOT of -//resources... very suspect... +// The following must be old IRIX code. Should be re-tested. +// It seems that gcc compiles it, but requiring a LOT of +// resources... very suspect... /*#ifdef __LP64__ #include "optimize_for_lp64.h" @@ -28,2150 +28,2083 @@ //============================================================================= #ifdef OPTIMIZE_FOR_LP64 -void quickResample_optimized( - const TRasterP &dn, - const TRasterP &up, - const TAffine &aff, - TRop::ResampleFilterType filterType); +void quickResample_optimized(const TRasterP &dn, const TRasterP &up, + const TAffine &aff, + TRop::ResampleFilterType filterType); #endif -namespace -{ - -inline TPixel32 applyColorScale(const TPixel32 &color, const TPixel32 &colorScale, bool toBePremultiplied = false) -{ - /*-- 半透明のラスタをViewer上で半透明にquickputするとき、色が暗くなってしまうのを防ぐ --*/ - if (colorScale.r == 0 && colorScale.g == 0 && colorScale.b == 0) { - /*-- toBePremultipliedがONのときは、後でPremultiplyをするので、ここでは行わない --*/ - if (toBePremultiplied) - return TPixel32(color.r, color.g, color.b, color.m * colorScale.m / 255); - else - return TPixel32(color.r * colorScale.m / 255, color.g * colorScale.m / 255, color.b * colorScale.m / 255, color.m * colorScale.m / 255); - } - int r = color.r + colorScale.r; - int g = color.g + colorScale.g; - int b = color.b + colorScale.b; - - return premultiply(TPixel32(r > 255 ? 255 : r, g > 255 ? 255 : g, b > 255 ? 255 : b, color.m * colorScale.m / 255)); +namespace { + +inline TPixel32 applyColorScale(const TPixel32 &color, + const TPixel32 &colorScale, + bool toBePremultiplied = false) { + /*-- + * 半透明のラスタをViewer上で半透明にquickputするとき、色が暗くなってしまうのを防ぐ + * --*/ + if (colorScale.r == 0 && colorScale.g == 0 && colorScale.b == 0) { + /*-- + * toBePremultipliedがONのときは、後でPremultiplyをするので、ここでは行わない + * --*/ + if (toBePremultiplied) + return TPixel32(color.r, color.g, color.b, color.m * colorScale.m / 255); + else + return TPixel32( + color.r * colorScale.m / 255, color.g * colorScale.m / 255, + color.b * colorScale.m / 255, color.m * colorScale.m / 255); + } + int r = color.r + colorScale.r; + int g = color.g + colorScale.g; + int b = color.b + colorScale.b; + + return premultiply(TPixel32(r > 255 ? 255 : r, g > 255 ? 255 : g, + b > 255 ? 255 : b, color.m * colorScale.m / 255)); } //------------------------------------------------------------------------------ -inline TPixel32 applyColorScaleCMapped(const TPixel32 &color, const TPixel32 &colorScale) -{ - int r = color.r + colorScale.r; - int g = color.g + colorScale.g; - int b = color.b + colorScale.b; +inline TPixel32 applyColorScaleCMapped(const TPixel32 &color, + const TPixel32 &colorScale) { + int r = color.r + colorScale.r; + int g = color.g + colorScale.g; + int b = color.b + colorScale.b; - return premultiply(TPixel32(r > 255 ? 255 : r, g > 255 ? 255 : g, b > 255 ? 255 : b, color.m * colorScale.m / 255)); + return premultiply(TPixel32(r > 255 ? 255 : r, g > 255 ? 255 : g, + b > 255 ? 255 : b, color.m * colorScale.m / 255)); } //------------------------------------------------------------------------------ -void doQuickPutFilter( - const TRaster32P &dn, - const TRaster32P &up, - const TAffine &aff) -{ - // se aff e' degenere la controimmagine di up e' un segmento (o un punto) - if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) - return; - - // contatore bit di shift - const int PADN = 16; - - // maschera del filtro bilineare - const int MASKN = (1 << PADN) - 1; - - // max dimensioni di up gestibili (limite imposto dal numero di bit - // disponibili per la parte intera di xL, yL) - assert(std::max(up->getLx(), up->getLy()) < (1 << (8 * sizeof(int) - PADN - 1))); - - TRectD boundingBoxD = TRectD(convert(dn->getSize())) * - (aff * TRectD(0, 0, up->getLx() - 2, up->getLy() - 2)); - // clipping - if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) - return; - - // clipping y su dn - int yMin = std::max(tfloor(boundingBoxD.y0), 0); - - // clipping y su dn - int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); - - // clipping x su dn - int xMin = std::max(tfloor(boundingBoxD.x0), 0); - - // clipping x su dn - int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); - - TAffine invAff = inv(aff); // inversa di aff - - // nel disegnare la y-esima scanline di dn, il passaggio al pixel successivo - // comporta l'incremento (deltaXD, deltaYD) delle coordinate del pixel - // corrispondente di up - double deltaXD = invAff.a11; - double deltaYD = invAff.a21; - - // deltaXD "TLonghizzato" (round) - int deltaXL = tround(deltaXD * (1 << PADN)); - - // deltaYD "TLonghizzato" (round) - int deltaYL = tround(deltaYD * (1 << PADN)); - - // se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un - // segmento (o un punto) - if ((deltaXL == 0) && (deltaYL == 0)) - return; - - // naturale predecessore di up->getLx() - 1 - int lxPred = (up->getLx() - 2) * (1 << PADN); - - // naturale predecessore di up->getLy() - 1 - int lyPred = (up->getLy() - 2) * (1 << PADN); - - int dnWrap = dn->getWrap(); - int upWrap = up->getWrap(); - dn->lock(); - up->lock(); - TPixel32 *dnRow = dn->pixels(yMin); - TPixel32 *upBasePix = up->pixels(); - - // scorre le scanline di boundingBoxD - for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) { - // (1) equazione k-parametrica della y-esima - // scanline di boundingBoxD: - // (xMin, y) + k*(1, 0), k = 0, ..., (xMax - xMin) - - // (2) equazione k-parametrica dell'immagine mediante - // invAff di (1): - // invAff*(xMin, y) + k*(deltaXD, deltaYD), - // k = kMin, ..., kMax - // con 0 <= kMin <= kMax <= (xMax - xMin) - - // calcola kMin, kMax per la scanline corrente intersecando la (2) - // con i lati di up - - // il segmento [a, b] di up e' la controimmagine mediante aff - // della porzione di scanline [ (xMin, y), (xMax, y) ] di dn - - // TPointD b = invAff*TPointD(xMax, y); - TPointD a = invAff * TPointD(xMin, y); - - // (xL0, yL0) sono le coordinate di a in versione "TLonghizzata" - // 0 <= xL0 + k*deltaXL - // <= (up->getLx() - 2)*(1<getLy() - 2)*(1<getLx() - 2)*(1< - // 0 <= xL0 + k*deltaXL <= lxPred - // - // - // 0 <= yL0 + k*deltaYL <= (up->getLy() - 2)*(1< - // 0 <= yL0 + k*deltaYL <= lyPred - - // calcola kMinX, kMaxX - if (deltaXL == 0) { - // [a, b] verticale esterno ad up contratto - if ((xL0 < 0) || (lxPred < xL0)) - continue; - // altrimenti usa solo - // kMinY, kMaxY ((deltaXL != 0) || (deltaYL != 0)) - } else if (deltaXL > 0) { - if (lxPred < xL0) // [a, b] esterno ad up+(bordo destro) - continue; - - kMaxX = (lxPred - xL0) / deltaXL; // floor - if (xL0 < 0) { - kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil - } - } else // (deltaXL < 0) - { - if (xL0 < 0) // [a, b] esterno ad up contratto - continue; - - kMaxX = xL0 / (-deltaXL); // floor - if (lxPred < xL0) { - kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil - } - } - - // calcola kMinY, kMaxY - if (deltaYL == 0) { - // [a, b] orizzontale esterno ad up contratto - if ((yL0 < 0) || (lyPred < yL0)) - continue; - // altrimenti usa solo - // kMinX, kMaxX ((deltaXL != 0) || (deltaYL != 0)) - } else if (deltaYL > 0) { - if (lyPred < yL0) // [a, b] esterno ad up contratto - continue; - - kMaxY = (lyPred - yL0) / deltaYL; // floor - if (yL0 < 0) { - kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil - } - } else // (deltaYL < 0) - { - if (yL0 < 0) // [a, b] esterno ad up contratto - continue; - - kMaxY = yL0 / (-deltaYL); // floor - if (lyPred < yL0) { - kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil - } - } - - // calcola kMin, kMax effettuando anche il clipping su dn - int kMin = std::max({kMinX, kMinY, (int)0}); - int kMax = std::min({kMaxX, kMaxY, xMax - xMin}); - - TPixel32 *dnPix = dnRow + xMin + kMin; - TPixel32 *dnEndPix = dnRow + xMin + kMax + 1; - - // (xL, yL) sono le coordinate (inizializzate per il round) - // in versione "TLonghizzata" - // del pixel corrente di up - int xL = xL0 + (kMin - 1) * deltaXL; // inizializza xL - int yL = yL0 + (kMin - 1) * deltaYL; // inizializza yL - - // scorre i pixel sulla y-esima scanline di boundingBoxD - for (; dnPix < dnEndPix; ++dnPix) { - xL += deltaXL; - yL += deltaYL; - - // il punto di up TPointD(xL/(1<> PADN; // troncato - int yI = yL >> PADN; // troncato - - assert((0 <= xI) && (xI <= up->getLx() - 1) && - (0 <= yI) && (yI <= up->getLy() - 1)); - - // (xI, yI) - TPixel32 *upPix00 = upBasePix + (yI * upWrap + xI); - - // (xI + 1, yI) - TPixel32 *upPix10 = upPix00 + 1; - - // (xI, yI + 1) - TPixel32 *upPix01 = upPix00 + upWrap; - - // (xI + 1, yI + 1) - TPixel32 *upPix11 = upPix00 + upWrap + 1; - - // filtro bilineare 4 pixels: calcolo dei pesi - int xWeight1 = (xL & MASKN); - int xWeight0 = (1 << PADN) - xWeight1; - int yWeight1 = (yL & MASKN); - int yWeight0 = (1 << PADN) - yWeight1; - - // filtro bilineare 4 pixels: media pesata sui singoli canali - int rColDownTmp = (xWeight0 * (upPix00->r) + - xWeight1 * ((upPix10)->r)) >> - PADN; - - int gColDownTmp = (xWeight0 * (upPix00->g) + - xWeight1 * ((upPix10)->g)) >> - PADN; - - int bColDownTmp = (xWeight0 * (upPix00->b) + - xWeight1 * ((upPix10)->b)) >> - PADN; - - int rColUpTmp = (xWeight0 * ((upPix01)->r) + - xWeight1 * ((upPix11)->r)) >> - PADN; - - int gColUpTmp = (xWeight0 * ((upPix01)->g) + - xWeight1 * ((upPix11)->g)) >> - PADN; - - int bColUpTmp = (xWeight0 * ((upPix01)->b) + - xWeight1 * ((upPix11)->b)) >> - PADN; - - unsigned char rCol = - (unsigned char)((yWeight0 * rColDownTmp + yWeight1 * rColUpTmp) >> PADN); - - unsigned char gCol = - (unsigned char)((yWeight0 * gColDownTmp + yWeight1 * gColUpTmp) >> PADN); - - unsigned char bCol = - (unsigned char)((yWeight0 * bColDownTmp + yWeight1 * bColUpTmp) >> PADN); - - TPixel32 upPix = TPixel32(rCol, gCol, bCol, upPix00->m); - - if (upPix.m == 0) - continue; - else if (upPix.m == 255) - *dnPix = upPix; - else - *dnPix = quickOverPix(*dnPix, upPix); - } - } - dn->unlock(); - up->unlock(); +void doQuickPutFilter(const TRaster32P &dn, const TRaster32P &up, + const TAffine &aff) { + // se aff e' degenere la controimmagine di up e' un segmento (o un punto) + if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) return; + + // contatore bit di shift + const int PADN = 16; + + // maschera del filtro bilineare + const int MASKN = (1 << PADN) - 1; + + // max dimensioni di up gestibili (limite imposto dal numero di bit + // disponibili per la parte intera di xL, yL) + assert(std::max(up->getLx(), up->getLy()) < + (1 << (8 * sizeof(int) - PADN - 1))); + + TRectD boundingBoxD = TRectD(convert(dn->getSize())) * + (aff * TRectD(0, 0, up->getLx() - 2, up->getLy() - 2)); + // clipping + if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) + return; + + // clipping y su dn + int yMin = std::max(tfloor(boundingBoxD.y0), 0); + + // clipping y su dn + int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); + + // clipping x su dn + int xMin = std::max(tfloor(boundingBoxD.x0), 0); + + // clipping x su dn + int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); + + TAffine invAff = inv(aff); // inversa di aff + + // nel disegnare la y-esima scanline di dn, il passaggio al pixel successivo + // comporta l'incremento (deltaXD, deltaYD) delle coordinate del pixel + // corrispondente di up + double deltaXD = invAff.a11; + double deltaYD = invAff.a21; + + // deltaXD "TLonghizzato" (round) + int deltaXL = tround(deltaXD * (1 << PADN)); + + // deltaYD "TLonghizzato" (round) + int deltaYL = tround(deltaYD * (1 << PADN)); + + // se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un + // segmento (o un punto) + if ((deltaXL == 0) && (deltaYL == 0)) return; + + // naturale predecessore di up->getLx() - 1 + int lxPred = (up->getLx() - 2) * (1 << PADN); + + // naturale predecessore di up->getLy() - 1 + int lyPred = (up->getLy() - 2) * (1 << PADN); + + int dnWrap = dn->getWrap(); + int upWrap = up->getWrap(); + dn->lock(); + up->lock(); + TPixel32 *dnRow = dn->pixels(yMin); + TPixel32 *upBasePix = up->pixels(); + + // scorre le scanline di boundingBoxD + for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) { + // (1) equazione k-parametrica della y-esima + // scanline di boundingBoxD: + // (xMin, y) + k*(1, 0), k = 0, ..., (xMax - xMin) + + // (2) equazione k-parametrica dell'immagine mediante + // invAff di (1): + // invAff*(xMin, y) + k*(deltaXD, deltaYD), + // k = kMin, ..., kMax + // con 0 <= kMin <= kMax <= (xMax - xMin) + + // calcola kMin, kMax per la scanline corrente intersecando la (2) + // con i lati di up + + // il segmento [a, b] di up e' la controimmagine mediante aff + // della porzione di scanline [ (xMin, y), (xMax, y) ] di dn + + // TPointD b = invAff*TPointD(xMax, y); + TPointD a = invAff * TPointD(xMin, y); + + // (xL0, yL0) sono le coordinate di a in versione "TLonghizzata" + // 0 <= xL0 + k*deltaXL + // <= (up->getLx() - 2)*(1<getLy() - 2)*(1<getLx() - 2)*(1< + // 0 <= xL0 + k*deltaXL <= lxPred + // + // + // 0 <= yL0 + k*deltaYL <= (up->getLy() - 2)*(1< + // 0 <= yL0 + k*deltaYL <= lyPred + + // calcola kMinX, kMaxX + if (deltaXL == 0) { + // [a, b] verticale esterno ad up contratto + if ((xL0 < 0) || (lxPred < xL0)) continue; + // altrimenti usa solo + // kMinY, kMaxY ((deltaXL != 0) || (deltaYL != 0)) + } else if (deltaXL > 0) { + if (lxPred < xL0) // [a, b] esterno ad up+(bordo destro) + continue; + + kMaxX = (lxPred - xL0) / deltaXL; // floor + if (xL0 < 0) { + kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil + } + } else // (deltaXL < 0) + { + if (xL0 < 0) // [a, b] esterno ad up contratto + continue; + + kMaxX = xL0 / (-deltaXL); // floor + if (lxPred < xL0) { + kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil + } + } + + // calcola kMinY, kMaxY + if (deltaYL == 0) { + // [a, b] orizzontale esterno ad up contratto + if ((yL0 < 0) || (lyPred < yL0)) continue; + // altrimenti usa solo + // kMinX, kMaxX ((deltaXL != 0) || (deltaYL != 0)) + } else if (deltaYL > 0) { + if (lyPred < yL0) // [a, b] esterno ad up contratto + continue; + + kMaxY = (lyPred - yL0) / deltaYL; // floor + if (yL0 < 0) { + kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil + } + } else // (deltaYL < 0) + { + if (yL0 < 0) // [a, b] esterno ad up contratto + continue; + + kMaxY = yL0 / (-deltaYL); // floor + if (lyPred < yL0) { + kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil + } + } + + // calcola kMin, kMax effettuando anche il clipping su dn + int kMin = std::max({kMinX, kMinY, (int)0}); + int kMax = std::min({kMaxX, kMaxY, xMax - xMin}); + + TPixel32 *dnPix = dnRow + xMin + kMin; + TPixel32 *dnEndPix = dnRow + xMin + kMax + 1; + + // (xL, yL) sono le coordinate (inizializzate per il round) + // in versione "TLonghizzata" + // del pixel corrente di up + int xL = xL0 + (kMin - 1) * deltaXL; // inizializza xL + int yL = yL0 + (kMin - 1) * deltaYL; // inizializza yL + + // scorre i pixel sulla y-esima scanline di boundingBoxD + for (; dnPix < dnEndPix; ++dnPix) { + xL += deltaXL; + yL += deltaYL; + + // il punto di up TPointD(xL/(1<> PADN; // troncato + int yI = yL >> PADN; // troncato + + assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) && + (yI <= up->getLy() - 1)); + + // (xI, yI) + TPixel32 *upPix00 = upBasePix + (yI * upWrap + xI); + + // (xI + 1, yI) + TPixel32 *upPix10 = upPix00 + 1; + + // (xI, yI + 1) + TPixel32 *upPix01 = upPix00 + upWrap; + + // (xI + 1, yI + 1) + TPixel32 *upPix11 = upPix00 + upWrap + 1; + + // filtro bilineare 4 pixels: calcolo dei pesi + int xWeight1 = (xL & MASKN); + int xWeight0 = (1 << PADN) - xWeight1; + int yWeight1 = (yL & MASKN); + int yWeight0 = (1 << PADN) - yWeight1; + + // filtro bilineare 4 pixels: media pesata sui singoli canali + int rColDownTmp = + (xWeight0 * (upPix00->r) + xWeight1 * ((upPix10)->r)) >> PADN; + + int gColDownTmp = + (xWeight0 * (upPix00->g) + xWeight1 * ((upPix10)->g)) >> PADN; + + int bColDownTmp = + (xWeight0 * (upPix00->b) + xWeight1 * ((upPix10)->b)) >> PADN; + + int rColUpTmp = + (xWeight0 * ((upPix01)->r) + xWeight1 * ((upPix11)->r)) >> PADN; + + int gColUpTmp = + (xWeight0 * ((upPix01)->g) + xWeight1 * ((upPix11)->g)) >> PADN; + + int bColUpTmp = + (xWeight0 * ((upPix01)->b) + xWeight1 * ((upPix11)->b)) >> PADN; + + unsigned char rCol = + (unsigned char)((yWeight0 * rColDownTmp + yWeight1 * rColUpTmp) >> + PADN); + + unsigned char gCol = + (unsigned char)((yWeight0 * gColDownTmp + yWeight1 * gColUpTmp) >> + PADN); + + unsigned char bCol = + (unsigned char)((yWeight0 * bColDownTmp + yWeight1 * bColUpTmp) >> + PADN); + + TPixel32 upPix = TPixel32(rCol, gCol, bCol, upPix00->m); + + if (upPix.m == 0) + continue; + else if (upPix.m == 255) + *dnPix = upPix; + else + *dnPix = quickOverPix(*dnPix, upPix); + } + } + dn->unlock(); + up->unlock(); } //============================================================================= //============================================================================= //============================================================================= -void doQuickPutNoFilter( - const TRaster32P &dn, - const TRaster32P &up, - const TAffine &aff, - const TPixel32 &colorScale, - bool doPremultiply, - bool whiteTransp, - bool firstColumn, - bool doRasterDarkenBlendedView) -{ - // se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine - // di up e' un segmento (o un punto) - if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) - return; - - // contatore bit di shift - const int PADN = 16; - - // max dimensioni di up gestibili (limite imposto dal numero di bit - // disponibili per la parte intera di xL, yL) - assert(std::max(up->getLx(), up->getLy()) < (1 << (8 * sizeof(int) - PADN - 1))); - - TRectD boundingBoxD = TRectD(convert(dn->getBounds())) * - (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5)); - - // clipping - if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) - return; - - // clipping y su dn - int yMin = std::max(tfloor(boundingBoxD.y0), 0); - - // clipping y su dn - int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); - - // clipping x su dn - int xMin = std::max(tfloor(boundingBoxD.x0), 0); - - // clipping x su dn - int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); - - // inversa di aff - TAffine invAff = inv(aff); - - // nel disegnare la y-esima scanline di dn, il passaggio al pixel - // successivo comporta l'incremento (deltaXD, deltaYD) delle coordinate del - // pixel corrispondente di up - double deltaXD = invAff.a11; - double deltaYD = invAff.a21; - - // deltaXD "TLonghizzato" (round) - int deltaXL = tround(deltaXD * (1 << PADN)); - - // deltaYD "TLonghizzato" (round) - int deltaYL = tround(deltaYD * (1 << PADN)); - - // se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un - // segmento (o un punto) - if ((deltaXL == 0) && (deltaYL == 0)) - return; - - // TINT32 predecessore di up->getLx() - int lxPred = up->getLx() * (1 << PADN) - 1; - - // TINT32 predecessore di up->getLy() - int lyPred = up->getLy() * (1 << PADN) - 1; - - int dnWrap = dn->getWrap(); - int upWrap = up->getWrap(); - dn->lock(); - up->lock(); - - TPixel32 *dnRow = dn->pixels(yMin); - TPixel32 *upBasePix = up->pixels(); - - // scorre le scanline di boundingBoxD - for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) { - // (1) equazione k-parametrica della y-esima scanline di boundingBoxD: - // (xMin, y) + k*(1, 0), k = 0, ..., (xMax - xMin) - - // (2) equazione k-parametrica dell'immagine mediante invAff di (1): - // invAff*(xMin, y) + k*(deltaXD, deltaYD), - // k = kMin, ..., kMax con 0 <= kMin <= kMax <= (xMax - xMin) - - // calcola kMin, kMax per la scanline corrente - // intersecando la (2) con i lati di up - - // il segmento [a, b] di up e' la controimmagine mediante aff della - // porzione di scanline [ (xMin, y), (xMax, y) ] di dn - - // TPointD b = invAff*TPointD(xMax, y); - TPointD a = invAff * TPointD(xMin, y); - - // (xL0, yL0) sono le coordinate di a (inizializzate per il round) - // in versione "TLonghizzata" - // 0 <= xL0 + k*deltaXL - // < up->getLx()*(1<getLy()*(1<getLx()*(1< - // 0 <= xL0 + k*deltaXL - // <= lxPred - // - // 0 <= yL0 + k*deltaYL - // < up->getLy()*(1< - // 0 <= yL0 + k*deltaYL - // <= lyPred - - // calcola kMinX, kMaxX - if (deltaXL == 0) { - // [a, b] verticale esterno ad up+(bordo destro/basso) - if ((xL0 < 0) || (lxPred < xL0)) - continue; - // altrimenti usa solo - // kMinY, kMaxY ((deltaXL != 0) || (deltaYL != 0)) - } else if (deltaXL > 0) { - // [a, b] esterno ad up+(bordo destro/basso) - if (lxPred < xL0) - continue; - - kMaxX = (lxPred - xL0) / deltaXL; // floor - if (xL0 < 0) { - kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil - } - } else // (deltaXL < 0) - { - // [a, b] esterno ad up+(bordo destro/basso) - if (xL0 < 0) - continue; - - kMaxX = xL0 / (-deltaXL); // floor - if (lxPred < xL0) { - kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil - } - } - - // calcola kMinY, kMaxY - if (deltaYL == 0) { - // [a, b] orizzontale esterno ad up+(bordo destro/basso) - if ((yL0 < 0) || (lyPred < yL0)) - continue; - // altrimenti usa solo - // kMinX, kMaxX ((deltaXL != 0) || (deltaYL != 0)) - } else if (deltaYL > 0) { - // [a, b] esterno ad up+(bordo destro/basso) - if (lyPred < yL0) - continue; - - kMaxY = (lyPred - yL0) / deltaYL; // floor - if (yL0 < 0) { - kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil - } - } else // (deltaYL < 0) - { - // [a, b] esterno ad up+(bordo destro/basso) - if (yL0 < 0) - continue; - - kMaxY = yL0 / (-deltaYL); // floor - if (lyPred < yL0) { - kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil - } - } - - // calcola kMin, kMax effettuando anche il clippind su dn - int kMin = std::max({kMinX, kMinY, (int)0}); - int kMax = std::min({kMaxX, kMaxY, xMax - xMin}); - - TPixel32 *dnPix = dnRow + xMin + kMin; - TPixel32 *dnEndPix = dnRow + xMin + kMax + 1; - - // (xL, yL) sono le coordinate (inizializzate per il round) - // in versione "TLonghizzata" del pixel corrente di up - int xL = xL0 + (kMin - 1) * deltaXL; // inizializza xL - int yL = yL0 + (kMin - 1) * deltaYL; // inizializza yL - - // scorre i pixel sulla y-esima scanline di boundingBoxD - for (; dnPix < dnEndPix; ++dnPix) { - xL += deltaXL; - yL += deltaYL; - - // il punto di up TPointD(xL/(1<> PADN; // round - int yI = yL >> PADN; // round - - assert((0 <= xI) && (xI <= up->getLx() - 1) && - (0 <= yI) && (yI <= up->getLy() - 1)); - - TPixel32 upPix = *(upBasePix + (yI * upWrap + xI)); - - if (firstColumn) - upPix.m = 255; - if (upPix.m == 0 || (whiteTransp && upPix == TPixel::White)) - continue; - - if (colorScale != TPixel32::Black) - upPix = applyColorScale(upPix, colorScale, doPremultiply); - - if (doRasterDarkenBlendedView) - *dnPix = quickOverPixDarkenBlended(*dnPix, upPix); - else { - if (upPix.m == 255) - *dnPix = upPix; - else if (doPremultiply) - *dnPix = quickOverPixPremult(*dnPix, upPix); - else - *dnPix = quickOverPix(*dnPix, upPix); - } - } - } - dn->unlock(); - up->unlock(); +void doQuickPutNoFilter(const TRaster32P &dn, const TRaster32P &up, + const TAffine &aff, const TPixel32 &colorScale, + bool doPremultiply, bool whiteTransp, bool firstColumn, + bool doRasterDarkenBlendedView) { + // se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine + // di up e' un segmento (o un punto) + if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) return; + + // contatore bit di shift + const int PADN = 16; + + // max dimensioni di up gestibili (limite imposto dal numero di bit + // disponibili per la parte intera di xL, yL) + assert(std::max(up->getLx(), up->getLy()) < + (1 << (8 * sizeof(int) - PADN - 1))); + + TRectD boundingBoxD = + TRectD(convert(dn->getBounds())) * + (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5)); + + // clipping + if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) + return; + + // clipping y su dn + int yMin = std::max(tfloor(boundingBoxD.y0), 0); + + // clipping y su dn + int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); + + // clipping x su dn + int xMin = std::max(tfloor(boundingBoxD.x0), 0); + + // clipping x su dn + int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); + + // inversa di aff + TAffine invAff = inv(aff); + + // nel disegnare la y-esima scanline di dn, il passaggio al pixel + // successivo comporta l'incremento (deltaXD, deltaYD) delle coordinate del + // pixel corrispondente di up + double deltaXD = invAff.a11; + double deltaYD = invAff.a21; + + // deltaXD "TLonghizzato" (round) + int deltaXL = tround(deltaXD * (1 << PADN)); + + // deltaYD "TLonghizzato" (round) + int deltaYL = tround(deltaYD * (1 << PADN)); + + // se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un + // segmento (o un punto) + if ((deltaXL == 0) && (deltaYL == 0)) return; + + // TINT32 predecessore di up->getLx() + int lxPred = up->getLx() * (1 << PADN) - 1; + + // TINT32 predecessore di up->getLy() + int lyPred = up->getLy() * (1 << PADN) - 1; + + int dnWrap = dn->getWrap(); + int upWrap = up->getWrap(); + dn->lock(); + up->lock(); + + TPixel32 *dnRow = dn->pixels(yMin); + TPixel32 *upBasePix = up->pixels(); + + // scorre le scanline di boundingBoxD + for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) { + // (1) equazione k-parametrica della y-esima scanline di boundingBoxD: + // (xMin, y) + k*(1, 0), k = 0, ..., (xMax - xMin) + + // (2) equazione k-parametrica dell'immagine mediante invAff di (1): + // invAff*(xMin, y) + k*(deltaXD, deltaYD), + // k = kMin, ..., kMax con 0 <= kMin <= kMax <= (xMax - xMin) + + // calcola kMin, kMax per la scanline corrente + // intersecando la (2) con i lati di up + + // il segmento [a, b] di up e' la controimmagine mediante aff della + // porzione di scanline [ (xMin, y), (xMax, y) ] di dn + + // TPointD b = invAff*TPointD(xMax, y); + TPointD a = invAff * TPointD(xMin, y); + + // (xL0, yL0) sono le coordinate di a (inizializzate per il round) + // in versione "TLonghizzata" + // 0 <= xL0 + k*deltaXL + // < up->getLx()*(1<getLy()*(1<getLx()*(1< + // 0 <= xL0 + k*deltaXL + // <= lxPred + // + // 0 <= yL0 + k*deltaYL + // < up->getLy()*(1< + // 0 <= yL0 + k*deltaYL + // <= lyPred + + // calcola kMinX, kMaxX + if (deltaXL == 0) { + // [a, b] verticale esterno ad up+(bordo destro/basso) + if ((xL0 < 0) || (lxPred < xL0)) continue; + // altrimenti usa solo + // kMinY, kMaxY ((deltaXL != 0) || (deltaYL != 0)) + } else if (deltaXL > 0) { + // [a, b] esterno ad up+(bordo destro/basso) + if (lxPred < xL0) continue; + + kMaxX = (lxPred - xL0) / deltaXL; // floor + if (xL0 < 0) { + kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil + } + } else // (deltaXL < 0) + { + // [a, b] esterno ad up+(bordo destro/basso) + if (xL0 < 0) continue; + + kMaxX = xL0 / (-deltaXL); // floor + if (lxPred < xL0) { + kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil + } + } + + // calcola kMinY, kMaxY + if (deltaYL == 0) { + // [a, b] orizzontale esterno ad up+(bordo destro/basso) + if ((yL0 < 0) || (lyPred < yL0)) continue; + // altrimenti usa solo + // kMinX, kMaxX ((deltaXL != 0) || (deltaYL != 0)) + } else if (deltaYL > 0) { + // [a, b] esterno ad up+(bordo destro/basso) + if (lyPred < yL0) continue; + + kMaxY = (lyPred - yL0) / deltaYL; // floor + if (yL0 < 0) { + kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil + } + } else // (deltaYL < 0) + { + // [a, b] esterno ad up+(bordo destro/basso) + if (yL0 < 0) continue; + + kMaxY = yL0 / (-deltaYL); // floor + if (lyPred < yL0) { + kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil + } + } + + // calcola kMin, kMax effettuando anche il clippind su dn + int kMin = std::max({kMinX, kMinY, (int)0}); + int kMax = std::min({kMaxX, kMaxY, xMax - xMin}); + + TPixel32 *dnPix = dnRow + xMin + kMin; + TPixel32 *dnEndPix = dnRow + xMin + kMax + 1; + + // (xL, yL) sono le coordinate (inizializzate per il round) + // in versione "TLonghizzata" del pixel corrente di up + int xL = xL0 + (kMin - 1) * deltaXL; // inizializza xL + int yL = yL0 + (kMin - 1) * deltaYL; // inizializza yL + + // scorre i pixel sulla y-esima scanline di boundingBoxD + for (; dnPix < dnEndPix; ++dnPix) { + xL += deltaXL; + yL += deltaYL; + + // il punto di up TPointD(xL/(1<> PADN; // round + int yI = yL >> PADN; // round + + assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) && + (yI <= up->getLy() - 1)); + + TPixel32 upPix = *(upBasePix + (yI * upWrap + xI)); + + if (firstColumn) upPix.m = 255; + if (upPix.m == 0 || (whiteTransp && upPix == TPixel::White)) continue; + + if (colorScale != TPixel32::Black) + upPix = applyColorScale(upPix, colorScale, doPremultiply); + + if (doRasterDarkenBlendedView) + *dnPix = quickOverPixDarkenBlended(*dnPix, upPix); + else { + if (upPix.m == 255) + *dnPix = upPix; + else if (doPremultiply) + *dnPix = quickOverPixPremult(*dnPix, upPix); + else + *dnPix = quickOverPix(*dnPix, upPix); + } + } + } + dn->unlock(); + up->unlock(); } //============================================================================= //============================================================================= //============================================================================= -void doQuickPutNoFilter( - const TRaster32P &dn, - const TRaster64P &up, - const TAffine &aff, - bool doPremultiply, - bool firstColumn) -{ - // se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine - // di up e' un segmento (o un punto) - if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) - return; - - // contatore bit di shift - const int PADN = 16; - - // max dimensioni di up gestibili (limite imposto dal numero di bit - // disponibili per la parte intera di xL, yL) - assert(std::max(up->getLx(), up->getLy()) < (1 << (8 * sizeof(int) - PADN - 1))); - - TRectD boundingBoxD = TRectD(convert(dn->getBounds())) * - (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5)); - - // clipping - if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) - return; - - // clipping y su dn - int yMin = std::max(tfloor(boundingBoxD.y0), 0); - - // clipping y su dn - int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); - - // clipping x su dn - int xMin = std::max(tfloor(boundingBoxD.x0), 0); - - // clipping x su dn - int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); - - // inversa di aff - TAffine invAff = inv(aff); - - // nel disegnare la y-esima scanline di dn, il passaggio al pixel - // successivo comporta l'incremento (deltaXD, deltaYD) delle coordinate del - // pixel corrispondente di up - double deltaXD = invAff.a11; - double deltaYD = invAff.a21; - - // deltaXD "TLonghizzato" (round) - int deltaXL = tround(deltaXD * (1 << PADN)); - - // deltaYD "TLonghizzato" (round) - int deltaYL = tround(deltaYD * (1 << PADN)); - - // se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un - // segmento (o un punto) - if ((deltaXL == 0) && (deltaYL == 0)) - return; - - // TINT32 predecessore di up->getLx() - int lxPred = up->getLx() * (1 << PADN) - 1; - - // TINT32 predecessore di up->getLy() - int lyPred = up->getLy() * (1 << PADN) - 1; - - int dnWrap = dn->getWrap(); - int upWrap = up->getWrap(); - dn->lock(); - up->lock(); - - TPixel32 *dnRow = dn->pixels(yMin); - TPixel64 *upBasePix = up->pixels(); - - // scorre le scanline di boundingBoxD - for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) { - // (1) equazione k-parametrica della y-esima scanline di boundingBoxD: - // (xMin, y) + k*(1, 0), k = 0, ..., (xMax - xMin) - - // (2) equazione k-parametrica dell'immagine mediante invAff di (1): - // invAff*(xMin, y) + k*(deltaXD, deltaYD), - // k = kMin, ..., kMax con 0 <= kMin <= kMax <= (xMax - xMin) - - // calcola kMin, kMax per la scanline corrente - // intersecando la (2) con i lati di up - - // il segmento [a, b] di up e' la controimmagine mediante aff della - // porzione di scanline [ (xMin, y), (xMax, y) ] di dn - - // TPointD b = invAff*TPointD(xMax, y); - TPointD a = invAff * TPointD(xMin, y); - - // (xL0, yL0) sono le coordinate di a (inizializzate per il round) - // in versione "TLonghizzata" - // 0 <= xL0 + k*deltaXL - // < up->getLx()*(1<getLy()*(1<getLx()*(1< - // 0 <= xL0 + k*deltaXL - // <= lxPred - // - // 0 <= yL0 + k*deltaYL - // < up->getLy()*(1< - // 0 <= yL0 + k*deltaYL - // <= lyPred - - // calcola kMinX, kMaxX - if (deltaXL == 0) { - // [a, b] verticale esterno ad up+(bordo destro/basso) - if ((xL0 < 0) || (lxPred < xL0)) - continue; - // altrimenti usa solo - // kMinY, kMaxY ((deltaXL != 0) || (deltaYL != 0)) - } else if (deltaXL > 0) { - // [a, b] esterno ad up+(bordo destro/basso) - if (lxPred < xL0) - continue; - - kMaxX = (lxPred - xL0) / deltaXL; // floor - if (xL0 < 0) { - kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil - } - } else // (deltaXL < 0) - { - // [a, b] esterno ad up+(bordo destro/basso) - if (xL0 < 0) - continue; - - kMaxX = xL0 / (-deltaXL); // floor - if (lxPred < xL0) { - kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil - } - } - - // calcola kMinY, kMaxY - if (deltaYL == 0) { - // [a, b] orizzontale esterno ad up+(bordo destro/basso) - if ((yL0 < 0) || (lyPred < yL0)) - continue; - // altrimenti usa solo - // kMinX, kMaxX ((deltaXL != 0) || (deltaYL != 0)) - } else if (deltaYL > 0) { - // [a, b] esterno ad up+(bordo destro/basso) - if (lyPred < yL0) - continue; - - kMaxY = (lyPred - yL0) / deltaYL; // floor - if (yL0 < 0) { - kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil - } - } else // (deltaYL < 0) - { - // [a, b] esterno ad up+(bordo destro/basso) - if (yL0 < 0) - continue; - - kMaxY = yL0 / (-deltaYL); // floor - if (lyPred < yL0) { - kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil - } - } - - // calcola kMin, kMax effettuando anche il clippind su dn - int kMin = std::max({kMinX, kMinY, (int)0}); - int kMax = std::min({kMaxX, kMaxY, xMax - xMin}); - - TPixel32 *dnPix = dnRow + xMin + kMin; - TPixel32 *dnEndPix = dnRow + xMin + kMax + 1; - - // (xL, yL) sono le coordinate (inizializzate per il round) - // in versione "TLonghizzata" del pixel corrente di up - int xL = xL0 + (kMin - 1) * deltaXL; // inizializza xL - int yL = yL0 + (kMin - 1) * deltaYL; // inizializza yL - - // scorre i pixel sulla y-esima scanline di boundingBoxD - for (; dnPix < dnEndPix; ++dnPix) { - xL += deltaXL; - yL += deltaYL; - - // il punto di up TPointD(xL/(1<> PADN; // round - int yI = yL >> PADN; // round - - assert((0 <= xI) && (xI <= up->getLx() - 1) && - (0 <= yI) && (yI <= up->getLy() - 1)); - - TPixel64 *upPix = upBasePix + (yI * upWrap + xI); - if (firstColumn) - upPix->m = 65535; - if (upPix->m == 0) - continue; - else if (upPix->m == 65535) - *dnPix = PixelConverter::from(*upPix); - else if (doPremultiply) - *dnPix = quickOverPixPremult(*dnPix, PixelConverter::from(*upPix)); - else - *dnPix = quickOverPix(*dnPix, PixelConverter::from(*upPix)); - } - } - dn->unlock(); - up->unlock(); +void doQuickPutNoFilter(const TRaster32P &dn, const TRaster64P &up, + const TAffine &aff, bool doPremultiply, + bool firstColumn) { + // se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine + // di up e' un segmento (o un punto) + if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) return; + + // contatore bit di shift + const int PADN = 16; + + // max dimensioni di up gestibili (limite imposto dal numero di bit + // disponibili per la parte intera di xL, yL) + assert(std::max(up->getLx(), up->getLy()) < + (1 << (8 * sizeof(int) - PADN - 1))); + + TRectD boundingBoxD = + TRectD(convert(dn->getBounds())) * + (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5)); + + // clipping + if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) + return; + + // clipping y su dn + int yMin = std::max(tfloor(boundingBoxD.y0), 0); + + // clipping y su dn + int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); + + // clipping x su dn + int xMin = std::max(tfloor(boundingBoxD.x0), 0); + + // clipping x su dn + int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); + + // inversa di aff + TAffine invAff = inv(aff); + + // nel disegnare la y-esima scanline di dn, il passaggio al pixel + // successivo comporta l'incremento (deltaXD, deltaYD) delle coordinate del + // pixel corrispondente di up + double deltaXD = invAff.a11; + double deltaYD = invAff.a21; + + // deltaXD "TLonghizzato" (round) + int deltaXL = tround(deltaXD * (1 << PADN)); + + // deltaYD "TLonghizzato" (round) + int deltaYL = tround(deltaYD * (1 << PADN)); + + // se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un + // segmento (o un punto) + if ((deltaXL == 0) && (deltaYL == 0)) return; + + // TINT32 predecessore di up->getLx() + int lxPred = up->getLx() * (1 << PADN) - 1; + + // TINT32 predecessore di up->getLy() + int lyPred = up->getLy() * (1 << PADN) - 1; + + int dnWrap = dn->getWrap(); + int upWrap = up->getWrap(); + dn->lock(); + up->lock(); + + TPixel32 *dnRow = dn->pixels(yMin); + TPixel64 *upBasePix = up->pixels(); + + // scorre le scanline di boundingBoxD + for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) { + // (1) equazione k-parametrica della y-esima scanline di boundingBoxD: + // (xMin, y) + k*(1, 0), k = 0, ..., (xMax - xMin) + + // (2) equazione k-parametrica dell'immagine mediante invAff di (1): + // invAff*(xMin, y) + k*(deltaXD, deltaYD), + // k = kMin, ..., kMax con 0 <= kMin <= kMax <= (xMax - xMin) + + // calcola kMin, kMax per la scanline corrente + // intersecando la (2) con i lati di up + + // il segmento [a, b] di up e' la controimmagine mediante aff della + // porzione di scanline [ (xMin, y), (xMax, y) ] di dn + + // TPointD b = invAff*TPointD(xMax, y); + TPointD a = invAff * TPointD(xMin, y); + + // (xL0, yL0) sono le coordinate di a (inizializzate per il round) + // in versione "TLonghizzata" + // 0 <= xL0 + k*deltaXL + // < up->getLx()*(1<getLy()*(1<getLx()*(1< + // 0 <= xL0 + k*deltaXL + // <= lxPred + // + // 0 <= yL0 + k*deltaYL + // < up->getLy()*(1< + // 0 <= yL0 + k*deltaYL + // <= lyPred + + // calcola kMinX, kMaxX + if (deltaXL == 0) { + // [a, b] verticale esterno ad up+(bordo destro/basso) + if ((xL0 < 0) || (lxPred < xL0)) continue; + // altrimenti usa solo + // kMinY, kMaxY ((deltaXL != 0) || (deltaYL != 0)) + } else if (deltaXL > 0) { + // [a, b] esterno ad up+(bordo destro/basso) + if (lxPred < xL0) continue; + + kMaxX = (lxPred - xL0) / deltaXL; // floor + if (xL0 < 0) { + kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil + } + } else // (deltaXL < 0) + { + // [a, b] esterno ad up+(bordo destro/basso) + if (xL0 < 0) continue; + + kMaxX = xL0 / (-deltaXL); // floor + if (lxPred < xL0) { + kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil + } + } + + // calcola kMinY, kMaxY + if (deltaYL == 0) { + // [a, b] orizzontale esterno ad up+(bordo destro/basso) + if ((yL0 < 0) || (lyPred < yL0)) continue; + // altrimenti usa solo + // kMinX, kMaxX ((deltaXL != 0) || (deltaYL != 0)) + } else if (deltaYL > 0) { + // [a, b] esterno ad up+(bordo destro/basso) + if (lyPred < yL0) continue; + + kMaxY = (lyPred - yL0) / deltaYL; // floor + if (yL0 < 0) { + kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil + } + } else // (deltaYL < 0) + { + // [a, b] esterno ad up+(bordo destro/basso) + if (yL0 < 0) continue; + + kMaxY = yL0 / (-deltaYL); // floor + if (lyPred < yL0) { + kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil + } + } + + // calcola kMin, kMax effettuando anche il clippind su dn + int kMin = std::max({kMinX, kMinY, (int)0}); + int kMax = std::min({kMaxX, kMaxY, xMax - xMin}); + + TPixel32 *dnPix = dnRow + xMin + kMin; + TPixel32 *dnEndPix = dnRow + xMin + kMax + 1; + + // (xL, yL) sono le coordinate (inizializzate per il round) + // in versione "TLonghizzata" del pixel corrente di up + int xL = xL0 + (kMin - 1) * deltaXL; // inizializza xL + int yL = yL0 + (kMin - 1) * deltaYL; // inizializza yL + + // scorre i pixel sulla y-esima scanline di boundingBoxD + for (; dnPix < dnEndPix; ++dnPix) { + xL += deltaXL; + yL += deltaYL; + + // il punto di up TPointD(xL/(1<> PADN; // round + int yI = yL >> PADN; // round + + assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) && + (yI <= up->getLy() - 1)); + + TPixel64 *upPix = upBasePix + (yI * upWrap + xI); + if (firstColumn) upPix->m = 65535; + if (upPix->m == 0) + continue; + else if (upPix->m == 65535) + *dnPix = PixelConverter::from(*upPix); + else if (doPremultiply) + *dnPix = + quickOverPixPremult(*dnPix, PixelConverter::from(*upPix)); + else + *dnPix = quickOverPix(*dnPix, PixelConverter::from(*upPix)); + } + } + dn->unlock(); + up->unlock(); } //============================================================================= //============================================================================= //============================================================================= -void doQuickPutNoFilter( - const TRaster32P &dn, - const TRasterGR8P &up, - const TAffine &aff, - const TPixel32 &colorScale) -{ - if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) - return; - const int PADN = 16; - assert(std::max(up->getLx(), up->getLy()) < (1 << (8 * sizeof(int) - PADN - 1))); - - TRectD boundingBoxD = TRectD(convert(dn->getBounds())) * - (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5)); - - if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) - return; +void doQuickPutNoFilter(const TRaster32P &dn, const TRasterGR8P &up, + const TAffine &aff, const TPixel32 &colorScale) { + if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) return; + const int PADN = 16; + assert(std::max(up->getLx(), up->getLy()) < + (1 << (8 * sizeof(int) - PADN - 1))); - int yMin = std::max(tfloor(boundingBoxD.y0), 0); + TRectD boundingBoxD = + TRectD(convert(dn->getBounds())) * + (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5)); - int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); + if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) + return; - int xMin = std::max(tfloor(boundingBoxD.x0), 0); + int yMin = std::max(tfloor(boundingBoxD.y0), 0); - int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); + int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); - TAffine invAff = inv(aff); + int xMin = std::max(tfloor(boundingBoxD.x0), 0); - double deltaXD = invAff.a11; - double deltaYD = invAff.a21; + int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); - int deltaXL = tround(deltaXD * (1 << PADN)); + TAffine invAff = inv(aff); - int deltaYL = tround(deltaYD * (1 << PADN)); + double deltaXD = invAff.a11; + double deltaYD = invAff.a21; - if ((deltaXL == 0) && (deltaYL == 0)) - return; + int deltaXL = tround(deltaXD * (1 << PADN)); - int lxPred = up->getLx() * (1 << PADN) - 1; + int deltaYL = tround(deltaYD * (1 << PADN)); - int lyPred = up->getLy() * (1 << PADN) - 1; + if ((deltaXL == 0) && (deltaYL == 0)) return; - int dnWrap = dn->getWrap(); - int upWrap = up->getWrap(); - dn->lock(); - up->lock(); - - TPixel32 *dnRow = dn->pixels(yMin); - TPixelGR8 *upBasePix = up->pixels(); - - for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) { - - TPointD a = invAff * TPointD(xMin, y); - - int xL0 = tround((a.x + 0.5) * (1 << PADN)); - - int yL0 = tround((a.y + 0.5) * (1 << PADN)); - - int kMinX = 0, kMaxX = xMax - xMin; // clipping su dn - int kMinY = 0, kMaxY = xMax - xMin; // clipping su dn - - if (deltaXL == 0) { - if ((xL0 < 0) || (lxPred < xL0)) - continue; - } else if (deltaXL > 0) { - if (lxPred < xL0) - continue; - - kMaxX = (lxPred - xL0) / deltaXL; // floor - if (xL0 < 0) { - kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil - } - } else // (deltaXL < 0) - { - // [a, b] esterno ad up+(bordo destro/basso) - if (xL0 < 0) - continue; - - kMaxX = xL0 / (-deltaXL); // floor - if (lxPred < xL0) { - kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil - } - } - - // calcola kMinY, kMaxY - if (deltaYL == 0) { - // [a, b] orizzontale esterno ad up+(bordo destro/basso) - if ((yL0 < 0) || (lyPred < yL0)) - continue; - // altrimenti usa solo - // kMinX, kMaxX ((deltaXL != 0) || (deltaYL != 0)) - } else if (deltaYL > 0) { - // [a, b] esterno ad up+(bordo destro/basso) - if (lyPred < yL0) - continue; - - kMaxY = (lyPred - yL0) / deltaYL; // floor - if (yL0 < 0) { - kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil - } - } else // (deltaYL < 0) - { - // [a, b] esterno ad up+(bordo destro/basso) - if (yL0 < 0) - continue; - - kMaxY = yL0 / (-deltaYL); // floor - if (lyPred < yL0) { - kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil - } - } - - // calcola kMin, kMax effettuando anche il clippind su dn - int kMin = std::max({kMinX, kMinY, (int)0}); - int kMax = std::min({kMaxX, kMaxY, xMax - xMin}); - - TPixel32 *dnPix = dnRow + xMin + kMin; - TPixel32 *dnEndPix = dnRow + xMin + kMax + 1; - - // (xL, yL) sono le coordinate (inizializzate per il round) - // in versione "TLonghizzata" del pixel corrente di up - int xL = xL0 + (kMin - 1) * deltaXL; // inizializza xL - int yL = yL0 + (kMin - 1) * deltaYL; // inizializza yL - - // scorre i pixel sulla y-esima scanline di boundingBoxD - for (; dnPix < dnEndPix; ++dnPix) { - xL += deltaXL; - yL += deltaYL; - - // il punto di up TPointD(xL/(1<> PADN; // round - int yI = yL >> PADN; // round - - assert((0 <= xI) && (xI <= up->getLx() - 1) && - (0 <= yI) && (yI <= up->getLy() - 1)); - - TPixelGR8 *upPix = upBasePix + (yI * upWrap + xI); - if (colorScale == TPixel32::Black) { - - if (upPix->value == 0) - dnPix->r = dnPix->g = dnPix->b = 0; - else if (upPix->value == 255) - dnPix->r = dnPix->g = dnPix->b = upPix->value; - else - *dnPix = quickOverPix(*dnPix, *upPix); - dnPix->m = 255; - } else { - TPixel32 upPix32(upPix->value, upPix->value, upPix->value, 255); - upPix32 = applyColorScale(upPix32, colorScale); - - if (upPix32.m == 255) - *dnPix = upPix32; - else - *dnPix = quickOverPix(*dnPix, upPix32); - } - } - } - dn->unlock(); - up->unlock(); + int lxPred = up->getLx() * (1 << PADN) - 1; + + int lyPred = up->getLy() * (1 << PADN) - 1; + + int dnWrap = dn->getWrap(); + int upWrap = up->getWrap(); + dn->lock(); + up->lock(); + + TPixel32 *dnRow = dn->pixels(yMin); + TPixelGR8 *upBasePix = up->pixels(); + + for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) { + TPointD a = invAff * TPointD(xMin, y); + + int xL0 = tround((a.x + 0.5) * (1 << PADN)); + + int yL0 = tround((a.y + 0.5) * (1 << PADN)); + + int kMinX = 0, kMaxX = xMax - xMin; // clipping su dn + int kMinY = 0, kMaxY = xMax - xMin; // clipping su dn + + if (deltaXL == 0) { + if ((xL0 < 0) || (lxPred < xL0)) continue; + } else if (deltaXL > 0) { + if (lxPred < xL0) continue; + + kMaxX = (lxPred - xL0) / deltaXL; // floor + if (xL0 < 0) { + kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil + } + } else // (deltaXL < 0) + { + // [a, b] esterno ad up+(bordo destro/basso) + if (xL0 < 0) continue; + + kMaxX = xL0 / (-deltaXL); // floor + if (lxPred < xL0) { + kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil + } + } + + // calcola kMinY, kMaxY + if (deltaYL == 0) { + // [a, b] orizzontale esterno ad up+(bordo destro/basso) + if ((yL0 < 0) || (lyPred < yL0)) continue; + // altrimenti usa solo + // kMinX, kMaxX ((deltaXL != 0) || (deltaYL != 0)) + } else if (deltaYL > 0) { + // [a, b] esterno ad up+(bordo destro/basso) + if (lyPred < yL0) continue; + + kMaxY = (lyPred - yL0) / deltaYL; // floor + if (yL0 < 0) { + kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil + } + } else // (deltaYL < 0) + { + // [a, b] esterno ad up+(bordo destro/basso) + if (yL0 < 0) continue; + + kMaxY = yL0 / (-deltaYL); // floor + if (lyPred < yL0) { + kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil + } + } + + // calcola kMin, kMax effettuando anche il clippind su dn + int kMin = std::max({kMinX, kMinY, (int)0}); + int kMax = std::min({kMaxX, kMaxY, xMax - xMin}); + + TPixel32 *dnPix = dnRow + xMin + kMin; + TPixel32 *dnEndPix = dnRow + xMin + kMax + 1; + + // (xL, yL) sono le coordinate (inizializzate per il round) + // in versione "TLonghizzata" del pixel corrente di up + int xL = xL0 + (kMin - 1) * deltaXL; // inizializza xL + int yL = yL0 + (kMin - 1) * deltaYL; // inizializza yL + + // scorre i pixel sulla y-esima scanline di boundingBoxD + for (; dnPix < dnEndPix; ++dnPix) { + xL += deltaXL; + yL += deltaYL; + + // il punto di up TPointD(xL/(1<> PADN; // round + int yI = yL >> PADN; // round + + assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) && + (yI <= up->getLy() - 1)); + + TPixelGR8 *upPix = upBasePix + (yI * upWrap + xI); + if (colorScale == TPixel32::Black) { + if (upPix->value == 0) + dnPix->r = dnPix->g = dnPix->b = 0; + else if (upPix->value == 255) + dnPix->r = dnPix->g = dnPix->b = upPix->value; + else + *dnPix = quickOverPix(*dnPix, *upPix); + dnPix->m = 255; + } else { + TPixel32 upPix32(upPix->value, upPix->value, upPix->value, 255); + upPix32 = applyColorScale(upPix32, colorScale); + + if (upPix32.m == 255) + *dnPix = upPix32; + else + *dnPix = quickOverPix(*dnPix, upPix32); + } + } + } + dn->unlock(); + up->unlock(); } //============================================================================= -void doQuickPutFilter( - const TRaster32P &dn, - const TRaster32P &up, - double sx, double sy, - double tx, double ty) -{ - // se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine - // di up e' un segmento (o un punto) - if ((sx == 0) || (sy == 0)) - return; - - // contatore bit di shift - const int PADN = 16; - - // maschera del filtro bilineare - const int MASKN = (1 << PADN) - 1; - - assert(std::max(up->getLx(), up->getLy()) < (1 << (8 * sizeof(int) - PADN - 1))); - - // max dimensioni di up gestibili (limite imposto dal numero di bit - // disponibili per la parte intera di xL, yL) - TAffine aff(sx, 0, tx, 0, sy, ty); - TRectD boundingBoxD = TRectD(convert(dn->getSize())) * - (aff * TRectD(0, 0, up->getLx() - 2, up->getLy() - 2)); - - // clipping - if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) - return; - - // clipping y su dn - int yMin = std::max(tfloor(boundingBoxD.y0), 0); - - // clipping y su dn - int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); - - // clipping x su dn - int xMin = std::max(tfloor(boundingBoxD.x0), 0); - - // clipping x su dn - int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); - - // inversa di aff - TAffine invAff = inv(aff); - - // nello scorrere le scanline di boundingBoxD, il passaggio alla scanline - // successiva comporta l'incremento (0, deltaYD) delle coordinate dei - // pixels corrispondenti di up - - // nel disegnare la y-esima scanline di dn, il passaggio al pixel - // successivo comporta l'incremento (deltaXD, 0) delle coordinate del - // pixel corrispondente di up - - double deltaXD = invAff.a11; - double deltaYD = invAff.a22; - - // deltaXD "TLonghizzato" (round) - int deltaXL = tround(deltaXD * (1 << PADN)); - - // deltaYD "TLonghizzato" (round) - int deltaYL = tround(deltaYD * (1 << PADN)); - - // se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un - // segmento (o un punto) - if ((deltaXL == 0) || (deltaYL == 0)) - return; - - // (1) equazione (kX, kY)-parametrica di boundingBoxD: - // (xMin, yMin) + kX*(1, 0) + kY*(0, 1), - // kX = 0, ..., (xMax - xMin), - // kY = 0, ..., (yMax - yMin) - - // (2) equazione (kX, kY)-parametrica dell'immagine - // mediante invAff di (1): - // invAff*(xMin, yMin) + kX*(deltaXD, 0) + kY*(0, deltaYD), - // kX = kMinX, ..., kMaxX - // con 0 <= kMinX <= kMaxX <= (xMax - xMin) - // - // kY = kMinY, ..., kMaxY - // con 0 <= kMinY <= kMaxY <= (yMax - yMin) - - // calcola kMinX, kMaxX, kMinY, kMaxY intersecando la (2) con i lati di up - - // il segmento [a, b] di up (con gli estremi eventualmente invertiti) e' - // la controimmagine - // mediante aff della porzione di scanline [ (xMin, yMin), (xMax, yMin) ] - // di dn - - // TPointD b = invAff*TPointD(xMax, yMin); - TPointD a = invAff * TPointD(xMin, yMin); - - // (xL0, yL0) sono le coordinate di a (inizializzate per il round) in - // versione "TLonghizzata" - // - // 0 <= xL0 + kX*deltaXL - // <= (up->getLx() - 2)*(1<getLy() - 2)*(1<getLx() - 1) - int lxPred = (up->getLx() - 2) * (1 << PADN); - - // TINT32 predecessore di (up->getLy() - 1) - int lyPred = (up->getLy() - 2) * (1 << PADN); - - // 0 <= xL0 + k*deltaXL - // <= (up->getLx() - 2)*(1< - // 0 <= xL0 + k*deltaXL <= lxPred - // - // 0 <= yL0 + k*deltaYL - // <= (up->getLy() - 2)*(1< - // 0 <= yL0 + k*deltaYL <= lyPred - - // calcola kMinY, kMaxY intersecando la (2) con - // i lati (y = yMin) e (y = yMax) di up - if (deltaYL > 0) // (deltaYL != 0) - { - // [a, b] interno ad up contratto - assert(yL0 <= lyPred); - kMaxY = (lyPred - yL0) / deltaYL; // floor - if (yL0 < 0) { - kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil - } - } else // (deltaYL < 0) - { - // [a, b] interno ad up contratto - assert(0 <= yL0); - - kMaxY = yL0 / (-deltaYL); // floor - if (lyPred < yL0) { - kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil - } - } - // calcola kMinY, kMaxY effettuando anche il clippind su dn - kMinY = std::max(kMinY, (int)0); - kMaxY = std::min(kMaxY, yMax - yMin); - - // calcola kMinX, kMaxX intersecando la (2) con - // i lati (x = xMin) e (x = xMax) di up - if (deltaXL > 0) // (deltaXL != 0) - { - // [a, b] interno ad up contratto - assert(xL0 <= lxPred); - - kMaxX = (lxPred - xL0) / deltaXL; // floor - if (xL0 < 0) { - kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil - } - } else // (deltaXL < 0) - { - // [a, b] interno ad up contratto - assert(0 <= xL0); - - kMaxX = xL0 / (-deltaXL); // floor - if (lxPred < xL0) { - kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil - } - } - // calcola kMinX, kMaxX effettuando anche il clippind su dn - kMinX = std::max(kMinX, (int)0); - kMaxX = std::min(kMaxX, xMax - xMin); - - int dnWrap = dn->getWrap(); - int upWrap = up->getWrap(); - dn->lock(); - up->lock(); - - TPixel32 *upBasePix = up->pixels(); - TPixel32 *dnRow = dn->pixels(yMin + kMinY); - - // (xL, yL) sono le coordinate (inizializzate per il round) - // in versione "TLonghizzata" del pixel corrente di up - - // inizializza yL - int yL = yL0 + (kMinY - 1) * deltaYL; - - // scorre le scanline di boundingBoxD - for (int kY = kMinY; kY <= kMaxY; kY++, dnRow += dnWrap) { - // inizializza xL - int xL = xL0 + (kMinX - 1) * deltaXL; - yL += deltaYL; - // il punto di up TPointD(xL/(1<> PADN; // troncato - - // filtro bilineare 4 pixels: calcolo degli y-pesi - int yWeight1 = (yL & MASKN); - int yWeight0 = (1 << PADN) - yWeight1; - - TPixel32 *dnPix = dnRow + xMin + kMinX; - TPixel32 *dnEndPix = dnRow + xMin + kMaxX + 1; - - // scorre i pixel sulla (yMin + kY)-esima scanline di dn - for (; dnPix < dnEndPix; ++dnPix) { - xL += deltaXL; - // il punto di up TPointD(xL/(1<> PADN; // troncato - - assert((0 <= xI) && (xI <= up->getLx() - 1) && - (0 <= yI) && (yI <= up->getLy() - 1)); - - // (xI, yI) - TPixel32 *upPix00 = upBasePix + (yI * upWrap + xI); - - // (xI + 1, yI) - TPixel32 *upPix10 = upPix00 + 1; - - // (xI, yI + 1) - TPixel32 *upPix01 = upPix00 + upWrap; - - // (xI + 1, yI + 1) - TPixel32 *upPix11 = upPix00 + upWrap + 1; - - // filtro bilineare 4 pixels: calcolo degli x-pesi - int xWeight1 = (xL & MASKN); - int xWeight0 = (1 << PADN) - xWeight1; - - // filtro bilineare 4 pixels: media pesata sui singoli canali - int rColDownTmp = - (xWeight0 * (upPix00->r) + xWeight1 * ((upPix10)->r)) >> PADN; - - int gColDownTmp = - (xWeight0 * (upPix00->g) + xWeight1 * ((upPix10)->g)) >> PADN; - - int bColDownTmp = - (xWeight0 * (upPix00->b) + xWeight1 * ((upPix10)->b)) >> PADN; - - int rColUpTmp = - (xWeight0 * ((upPix01)->r) + xWeight1 * ((upPix11)->r)) >> PADN; - - int gColUpTmp = - (xWeight0 * ((upPix01)->g) + xWeight1 * ((upPix11)->g)) >> PADN; - - int bColUpTmp = - (xWeight0 * ((upPix01)->b) + xWeight1 * ((upPix11)->b)) >> PADN; - - unsigned char rCol = - (unsigned char)((yWeight0 * rColDownTmp + yWeight1 * rColUpTmp) >> PADN); - - unsigned char gCol = - (unsigned char)((yWeight0 * gColDownTmp + yWeight1 * gColUpTmp) >> PADN); - - unsigned char bCol = - (unsigned char)((yWeight0 * bColDownTmp + yWeight1 * bColUpTmp) >> PADN); - - TPixel32 upPix = TPixel32(rCol, gCol, bCol, upPix00->m); - - if (upPix.m == 0) - continue; - else if (upPix.m == 255) - *dnPix = upPix; - else - *dnPix = quickOverPix(*dnPix, upPix); - } - } - dn->unlock(); - up->unlock(); +void doQuickPutFilter(const TRaster32P &dn, const TRaster32P &up, double sx, + double sy, double tx, double ty) { + // se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine + // di up e' un segmento (o un punto) + if ((sx == 0) || (sy == 0)) return; + + // contatore bit di shift + const int PADN = 16; + + // maschera del filtro bilineare + const int MASKN = (1 << PADN) - 1; + + assert(std::max(up->getLx(), up->getLy()) < + (1 << (8 * sizeof(int) - PADN - 1))); + + // max dimensioni di up gestibili (limite imposto dal numero di bit + // disponibili per la parte intera di xL, yL) + TAffine aff(sx, 0, tx, 0, sy, ty); + TRectD boundingBoxD = TRectD(convert(dn->getSize())) * + (aff * TRectD(0, 0, up->getLx() - 2, up->getLy() - 2)); + + // clipping + if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) + return; + + // clipping y su dn + int yMin = std::max(tfloor(boundingBoxD.y0), 0); + + // clipping y su dn + int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); + + // clipping x su dn + int xMin = std::max(tfloor(boundingBoxD.x0), 0); + + // clipping x su dn + int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); + + // inversa di aff + TAffine invAff = inv(aff); + + // nello scorrere le scanline di boundingBoxD, il passaggio alla scanline + // successiva comporta l'incremento (0, deltaYD) delle coordinate dei + // pixels corrispondenti di up + + // nel disegnare la y-esima scanline di dn, il passaggio al pixel + // successivo comporta l'incremento (deltaXD, 0) delle coordinate del + // pixel corrispondente di up + + double deltaXD = invAff.a11; + double deltaYD = invAff.a22; + + // deltaXD "TLonghizzato" (round) + int deltaXL = tround(deltaXD * (1 << PADN)); + + // deltaYD "TLonghizzato" (round) + int deltaYL = tround(deltaYD * (1 << PADN)); + + // se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un + // segmento (o un punto) + if ((deltaXL == 0) || (deltaYL == 0)) return; + + // (1) equazione (kX, kY)-parametrica di boundingBoxD: + // (xMin, yMin) + kX*(1, 0) + kY*(0, 1), + // kX = 0, ..., (xMax - xMin), + // kY = 0, ..., (yMax - yMin) + + // (2) equazione (kX, kY)-parametrica dell'immagine + // mediante invAff di (1): + // invAff*(xMin, yMin) + kX*(deltaXD, 0) + kY*(0, deltaYD), + // kX = kMinX, ..., kMaxX + // con 0 <= kMinX <= kMaxX <= (xMax - xMin) + // + // kY = kMinY, ..., kMaxY + // con 0 <= kMinY <= kMaxY <= (yMax - yMin) + + // calcola kMinX, kMaxX, kMinY, kMaxY intersecando la (2) con i lati di up + + // il segmento [a, b] di up (con gli estremi eventualmente invertiti) e' + // la controimmagine + // mediante aff della porzione di scanline [ (xMin, yMin), (xMax, yMin) ] + // di dn + + // TPointD b = invAff*TPointD(xMax, yMin); + TPointD a = invAff * TPointD(xMin, yMin); + + // (xL0, yL0) sono le coordinate di a (inizializzate per il round) in + // versione "TLonghizzata" + // + // 0 <= xL0 + kX*deltaXL + // <= (up->getLx() - 2)*(1<getLy() - 2)*(1<getLx() - 1) + int lxPred = (up->getLx() - 2) * (1 << PADN); + + // TINT32 predecessore di (up->getLy() - 1) + int lyPred = (up->getLy() - 2) * (1 << PADN); + + // 0 <= xL0 + k*deltaXL + // <= (up->getLx() - 2)*(1< + // 0 <= xL0 + k*deltaXL <= lxPred + // + // 0 <= yL0 + k*deltaYL + // <= (up->getLy() - 2)*(1< + // 0 <= yL0 + k*deltaYL <= lyPred + + // calcola kMinY, kMaxY intersecando la (2) con + // i lati (y = yMin) e (y = yMax) di up + if (deltaYL > 0) // (deltaYL != 0) + { + // [a, b] interno ad up contratto + assert(yL0 <= lyPred); + kMaxY = (lyPred - yL0) / deltaYL; // floor + if (yL0 < 0) { + kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil + } + } else // (deltaYL < 0) + { + // [a, b] interno ad up contratto + assert(0 <= yL0); + + kMaxY = yL0 / (-deltaYL); // floor + if (lyPred < yL0) { + kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil + } + } + // calcola kMinY, kMaxY effettuando anche il clippind su dn + kMinY = std::max(kMinY, (int)0); + kMaxY = std::min(kMaxY, yMax - yMin); + + // calcola kMinX, kMaxX intersecando la (2) con + // i lati (x = xMin) e (x = xMax) di up + if (deltaXL > 0) // (deltaXL != 0) + { + // [a, b] interno ad up contratto + assert(xL0 <= lxPred); + + kMaxX = (lxPred - xL0) / deltaXL; // floor + if (xL0 < 0) { + kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil + } + } else // (deltaXL < 0) + { + // [a, b] interno ad up contratto + assert(0 <= xL0); + + kMaxX = xL0 / (-deltaXL); // floor + if (lxPred < xL0) { + kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil + } + } + // calcola kMinX, kMaxX effettuando anche il clippind su dn + kMinX = std::max(kMinX, (int)0); + kMaxX = std::min(kMaxX, xMax - xMin); + + int dnWrap = dn->getWrap(); + int upWrap = up->getWrap(); + dn->lock(); + up->lock(); + + TPixel32 *upBasePix = up->pixels(); + TPixel32 *dnRow = dn->pixels(yMin + kMinY); + + // (xL, yL) sono le coordinate (inizializzate per il round) + // in versione "TLonghizzata" del pixel corrente di up + + // inizializza yL + int yL = yL0 + (kMinY - 1) * deltaYL; + + // scorre le scanline di boundingBoxD + for (int kY = kMinY; kY <= kMaxY; kY++, dnRow += dnWrap) { + // inizializza xL + int xL = xL0 + (kMinX - 1) * deltaXL; + yL += deltaYL; + // il punto di up TPointD(xL/(1<> PADN; // troncato + + // filtro bilineare 4 pixels: calcolo degli y-pesi + int yWeight1 = (yL & MASKN); + int yWeight0 = (1 << PADN) - yWeight1; + + TPixel32 *dnPix = dnRow + xMin + kMinX; + TPixel32 *dnEndPix = dnRow + xMin + kMaxX + 1; + + // scorre i pixel sulla (yMin + kY)-esima scanline di dn + for (; dnPix < dnEndPix; ++dnPix) { + xL += deltaXL; + // il punto di up TPointD(xL/(1<> PADN; // troncato + + assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) && + (yI <= up->getLy() - 1)); + + // (xI, yI) + TPixel32 *upPix00 = upBasePix + (yI * upWrap + xI); + + // (xI + 1, yI) + TPixel32 *upPix10 = upPix00 + 1; + + // (xI, yI + 1) + TPixel32 *upPix01 = upPix00 + upWrap; + + // (xI + 1, yI + 1) + TPixel32 *upPix11 = upPix00 + upWrap + 1; + + // filtro bilineare 4 pixels: calcolo degli x-pesi + int xWeight1 = (xL & MASKN); + int xWeight0 = (1 << PADN) - xWeight1; + + // filtro bilineare 4 pixels: media pesata sui singoli canali + int rColDownTmp = + (xWeight0 * (upPix00->r) + xWeight1 * ((upPix10)->r)) >> PADN; + + int gColDownTmp = + (xWeight0 * (upPix00->g) + xWeight1 * ((upPix10)->g)) >> PADN; + + int bColDownTmp = + (xWeight0 * (upPix00->b) + xWeight1 * ((upPix10)->b)) >> PADN; + + int rColUpTmp = + (xWeight0 * ((upPix01)->r) + xWeight1 * ((upPix11)->r)) >> PADN; + + int gColUpTmp = + (xWeight0 * ((upPix01)->g) + xWeight1 * ((upPix11)->g)) >> PADN; + + int bColUpTmp = + (xWeight0 * ((upPix01)->b) + xWeight1 * ((upPix11)->b)) >> PADN; + + unsigned char rCol = + (unsigned char)((yWeight0 * rColDownTmp + yWeight1 * rColUpTmp) >> + PADN); + + unsigned char gCol = + (unsigned char)((yWeight0 * gColDownTmp + yWeight1 * gColUpTmp) >> + PADN); + + unsigned char bCol = + (unsigned char)((yWeight0 * bColDownTmp + yWeight1 * bColUpTmp) >> + PADN); + + TPixel32 upPix = TPixel32(rCol, gCol, bCol, upPix00->m); + + if (upPix.m == 0) + continue; + else if (upPix.m == 255) + *dnPix = upPix; + else + *dnPix = quickOverPix(*dnPix, upPix); + } + } + dn->unlock(); + up->unlock(); } //============================================================================= //============================================================================= //============================================================================= -void doQuickPutNoFilter( - const TRaster32P &dn, - const TRaster32P &up, - double sx, double sy, - double tx, double ty, - const TPixel32 &colorScale, - bool doPremultiply, bool whiteTransp, bool firstColumn, - bool doRasterDarkenBlendedView) -{ - // se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine - // di up e' un segmento (o un punto) - if ((sx == 0) || (sy == 0)) - return; - - // contatore bit di shift - const int PADN = 16; - assert(std::max(up->getLx(), up->getLy()) < (1 << (8 * sizeof(int) - PADN - 1))); - // max dimensioni di up gestibili (limite imposto dal numero di bit - // disponibili per la parte intera di xL, yL) - - TAffine aff(sx, 0, tx, 0, sy, ty); - TRectD boundingBoxD = TRectD(convert(dn->getBounds())) * - (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5)); - - // clipping - if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) - return; - - // clipping y su dn - int yMin = std::max(tfloor(boundingBoxD.y0), 0); - - // clipping y su dn - int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); - - // clipping x su dn - int xMin = std::max(tfloor(boundingBoxD.x0), 0); - - // clipping x su dn - int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); - - TAffine invAff = inv(aff); // inversa di aff - - // nello scorrere le scanline di boundingBoxD, il passaggio alla scanline - // successiva comporta l'incremento (0, deltaYD) delle coordinate dei - // pixels corrispondenti di up - - // nel disegnare la y-esima scanline di dn, il passaggio al pixel - // successivo comporta l'incremento (deltaXD, 0) delle coordinate del - // pixel corrispondente di up - - double deltaXD = invAff.a11; - double deltaYD = invAff.a22; - - // deltaXD "TLonghizzato" (round) - int deltaXL = tround(deltaXD * (1 << PADN)); - - // deltaYD "TLonghizzato" (round) - int deltaYL = tround(deltaYD * (1 << PADN)); - - // se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un - // segmento (o un punto) - if ((deltaXL == 0) || (deltaYL == 0)) - return; - - // (1) equazione (kX, kY)-parametrica di boundingBoxD: - // (xMin, yMin) + kX*(1, 0) + kY*(0, 1), - // kX = 0, ..., (xMax - xMin), - // kY = 0, ..., (yMax - yMin) - - // (2) equazione (kX, kY)-parametrica dell'immagine - // mediante invAff di (1): - // invAff*(xMin, yMin) + kX*(deltaXD, 0) + kY*(0, deltaYD), - // kX = kMinX, ..., kMaxX - // con 0 <= kMinX <= kMaxX <= (xMax - xMin) - // - // kY = kMinY, ..., kMaxY - // con 0 <= kMinY <= kMaxY <= (yMax - yMin) - - // calcola kMinX, kMaxX, kMinY, kMaxY intersecando la (2) con i lati di up - - // il segmento [a, b] di up e' la controimmagine mediante aff della - // porzione di scanline [ (xMin, yMin), (xMax, yMin) ] di dn - - // TPointD b = invAff*TPointD(xMax, yMin); - TPointD a = invAff * TPointD(xMin, yMin); - - // (xL0, yL0) sono le coordinate di a (inizializzate per il round) - // in versione "TLonghizzata" - // 0 <= xL0 + kX*deltaXL - // < up->getLx()*(1<getLy()*(1<getLx() - int lxPred = up->getLx() * (1 << PADN) - 1; - - // TINT32 predecessore di up->getLy() - int lyPred = up->getLy() * (1 << PADN) - 1; - - // 0 <= xL0 + k*deltaXL < up->getLx()*(1< - // 0 <= xL0 + k*deltaXL <= lxPred - - // 0 <= yL0 + k*deltaYL < up->getLy()*(1< - // 0 <= yL0 + k*deltaYL <= lyPred - - // calcola kMinY, kMaxY intersecando la (2) con i lati - // (y = yMin) e (y = yMax) di up - if (deltaYL > 0) // (deltaYL != 0) - { - // [a, b] interno ad up+(bordo destro/basso) - assert(yL0 <= lyPred); - - kMaxY = (lyPred - yL0) / deltaYL; // floor - if (yL0 < 0) { - kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil - } - } else // (deltaYL < 0) - { - // [a, b] interno ad up+(bordo destro/basso) - assert(0 <= yL0); - - kMaxY = yL0 / (-deltaYL); // floor - if (lyPred < yL0) { - kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil - } - } - // calcola kMinY, kMaxY effettuando anche il clippind su dn - kMinY = std::max(kMinY, (int)0); - kMaxY = std::min(kMaxY, yMax - yMin); - - // calcola kMinX, kMaxX intersecando la (2) con i lati - // (x = xMin) e (x = xMax) di up - if (deltaXL > 0) // (deltaXL != 0) - { - // [a, b] interno ad up+(bordo destro/basso) - assert(xL0 <= lxPred); - - kMaxX = (lxPred - xL0) / deltaXL; // floor - if (xL0 < 0) { - kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil - } - } else // (deltaXL < 0) - { - // [a, b] interno ad up+(bordo destro/basso) - assert(0 <= xL0); - - kMaxX = xL0 / (-deltaXL); // floor - if (lxPred < xL0) { - kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil - } - } - // calcola kMinX, kMaxX effettuando anche il clippind su dn - kMinX = std::max(kMinX, (int)0); - kMaxX = std::min(kMaxX, xMax - xMin); - - int dnWrap = dn->getWrap(); - int upWrap = up->getWrap(); - dn->lock(); - up->lock(); - - TPixel32 *upBasePix = up->pixels(); - TPixel32 *dnRow = dn->pixels(yMin + kMinY); - - // (xL, yL) sono le coordinate (inizializzate per il round) - // in versione "TLonghizzata" del pixel corrente di up - - // inizializza yL - int yL = yL0 + (kMinY - 1) * deltaYL; - - // scorre le scanline di boundingBoxD - for (int kY = kMinY; kY <= kMaxY; kY++, dnRow += dnWrap) { - // inizializza xL - int xL = xL0 + (kMinX - 1) * deltaXL; - yL += deltaYL; - - // il punto di up TPointD(xL/(1<> PADN; // round - - TPixel32 *dnPix = dnRow + xMin + kMinX; - TPixel32 *dnEndPix = dnRow + xMin + kMaxX + 1; - - // scorre i pixel sulla (yMin + kY)-esima scanline di dn - for (; dnPix < dnEndPix; ++dnPix) { - xL += deltaXL; - // il punto di up TPointD(xL/(1<> PADN; // round - - assert((0 <= xI) && (xI <= up->getLx() - 1) && - (0 <= yI) && (yI <= up->getLy() - 1)); - - TPixel32 upPix = *(upBasePix + (yI * upWrap + xI)); - - if (firstColumn) - upPix.m = 65535; - - if (upPix.m == 0 || (whiteTransp && upPix == TPixel::White)) - continue; - - if (colorScale != TPixel32::Black) - upPix = applyColorScale(upPix, colorScale, doPremultiply); - - if (doRasterDarkenBlendedView) - *dnPix = quickOverPixDarkenBlended(*dnPix, upPix); - else { - if (upPix.m == 255) - *dnPix = upPix; - else if (doPremultiply) - *dnPix = quickOverPixPremult(*dnPix, upPix); - else - *dnPix = quickOverPix(*dnPix, upPix); - } - } - } - dn->unlock(); - up->unlock(); +void doQuickPutNoFilter(const TRaster32P &dn, const TRaster32P &up, double sx, + double sy, double tx, double ty, + const TPixel32 &colorScale, bool doPremultiply, + bool whiteTransp, bool firstColumn, + bool doRasterDarkenBlendedView) { + // se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine + // di up e' un segmento (o un punto) + if ((sx == 0) || (sy == 0)) return; + + // contatore bit di shift + const int PADN = 16; + assert(std::max(up->getLx(), up->getLy()) < + (1 << (8 * sizeof(int) - PADN - 1))); + // max dimensioni di up gestibili (limite imposto dal numero di bit + // disponibili per la parte intera di xL, yL) + + TAffine aff(sx, 0, tx, 0, sy, ty); + TRectD boundingBoxD = + TRectD(convert(dn->getBounds())) * + (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5)); + + // clipping + if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) + return; + + // clipping y su dn + int yMin = std::max(tfloor(boundingBoxD.y0), 0); + + // clipping y su dn + int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); + + // clipping x su dn + int xMin = std::max(tfloor(boundingBoxD.x0), 0); + + // clipping x su dn + int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); + + TAffine invAff = inv(aff); // inversa di aff + + // nello scorrere le scanline di boundingBoxD, il passaggio alla scanline + // successiva comporta l'incremento (0, deltaYD) delle coordinate dei + // pixels corrispondenti di up + + // nel disegnare la y-esima scanline di dn, il passaggio al pixel + // successivo comporta l'incremento (deltaXD, 0) delle coordinate del + // pixel corrispondente di up + + double deltaXD = invAff.a11; + double deltaYD = invAff.a22; + + // deltaXD "TLonghizzato" (round) + int deltaXL = tround(deltaXD * (1 << PADN)); + + // deltaYD "TLonghizzato" (round) + int deltaYL = tround(deltaYD * (1 << PADN)); + + // se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un + // segmento (o un punto) + if ((deltaXL == 0) || (deltaYL == 0)) return; + + // (1) equazione (kX, kY)-parametrica di boundingBoxD: + // (xMin, yMin) + kX*(1, 0) + kY*(0, 1), + // kX = 0, ..., (xMax - xMin), + // kY = 0, ..., (yMax - yMin) + + // (2) equazione (kX, kY)-parametrica dell'immagine + // mediante invAff di (1): + // invAff*(xMin, yMin) + kX*(deltaXD, 0) + kY*(0, deltaYD), + // kX = kMinX, ..., kMaxX + // con 0 <= kMinX <= kMaxX <= (xMax - xMin) + // + // kY = kMinY, ..., kMaxY + // con 0 <= kMinY <= kMaxY <= (yMax - yMin) + + // calcola kMinX, kMaxX, kMinY, kMaxY intersecando la (2) con i lati di up + + // il segmento [a, b] di up e' la controimmagine mediante aff della + // porzione di scanline [ (xMin, yMin), (xMax, yMin) ] di dn + + // TPointD b = invAff*TPointD(xMax, yMin); + TPointD a = invAff * TPointD(xMin, yMin); + + // (xL0, yL0) sono le coordinate di a (inizializzate per il round) + // in versione "TLonghizzata" + // 0 <= xL0 + kX*deltaXL + // < up->getLx()*(1<getLy()*(1<getLx() + int lxPred = up->getLx() * (1 << PADN) - 1; + + // TINT32 predecessore di up->getLy() + int lyPred = up->getLy() * (1 << PADN) - 1; + + // 0 <= xL0 + k*deltaXL < up->getLx()*(1< + // 0 <= xL0 + k*deltaXL <= lxPred + + // 0 <= yL0 + k*deltaYL < up->getLy()*(1< + // 0 <= yL0 + k*deltaYL <= lyPred + + // calcola kMinY, kMaxY intersecando la (2) con i lati + // (y = yMin) e (y = yMax) di up + if (deltaYL > 0) // (deltaYL != 0) + { + // [a, b] interno ad up+(bordo destro/basso) + assert(yL0 <= lyPred); + + kMaxY = (lyPred - yL0) / deltaYL; // floor + if (yL0 < 0) { + kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil + } + } else // (deltaYL < 0) + { + // [a, b] interno ad up+(bordo destro/basso) + assert(0 <= yL0); + + kMaxY = yL0 / (-deltaYL); // floor + if (lyPred < yL0) { + kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil + } + } + // calcola kMinY, kMaxY effettuando anche il clippind su dn + kMinY = std::max(kMinY, (int)0); + kMaxY = std::min(kMaxY, yMax - yMin); + + // calcola kMinX, kMaxX intersecando la (2) con i lati + // (x = xMin) e (x = xMax) di up + if (deltaXL > 0) // (deltaXL != 0) + { + // [a, b] interno ad up+(bordo destro/basso) + assert(xL0 <= lxPred); + + kMaxX = (lxPred - xL0) / deltaXL; // floor + if (xL0 < 0) { + kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil + } + } else // (deltaXL < 0) + { + // [a, b] interno ad up+(bordo destro/basso) + assert(0 <= xL0); + + kMaxX = xL0 / (-deltaXL); // floor + if (lxPred < xL0) { + kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil + } + } + // calcola kMinX, kMaxX effettuando anche il clippind su dn + kMinX = std::max(kMinX, (int)0); + kMaxX = std::min(kMaxX, xMax - xMin); + + int dnWrap = dn->getWrap(); + int upWrap = up->getWrap(); + dn->lock(); + up->lock(); + + TPixel32 *upBasePix = up->pixels(); + TPixel32 *dnRow = dn->pixels(yMin + kMinY); + + // (xL, yL) sono le coordinate (inizializzate per il round) + // in versione "TLonghizzata" del pixel corrente di up + + // inizializza yL + int yL = yL0 + (kMinY - 1) * deltaYL; + + // scorre le scanline di boundingBoxD + for (int kY = kMinY; kY <= kMaxY; kY++, dnRow += dnWrap) { + // inizializza xL + int xL = xL0 + (kMinX - 1) * deltaXL; + yL += deltaYL; + + // il punto di up TPointD(xL/(1<> PADN; // round + + TPixel32 *dnPix = dnRow + xMin + kMinX; + TPixel32 *dnEndPix = dnRow + xMin + kMaxX + 1; + + // scorre i pixel sulla (yMin + kY)-esima scanline di dn + for (; dnPix < dnEndPix; ++dnPix) { + xL += deltaXL; + // il punto di up TPointD(xL/(1<> PADN; // round + + assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) && + (yI <= up->getLy() - 1)); + + TPixel32 upPix = *(upBasePix + (yI * upWrap + xI)); + + if (firstColumn) upPix.m = 65535; + + if (upPix.m == 0 || (whiteTransp && upPix == TPixel::White)) continue; + + if (colorScale != TPixel32::Black) + upPix = applyColorScale(upPix, colorScale, doPremultiply); + + if (doRasterDarkenBlendedView) + *dnPix = quickOverPixDarkenBlended(*dnPix, upPix); + else { + if (upPix.m == 255) + *dnPix = upPix; + else if (doPremultiply) + *dnPix = quickOverPixPremult(*dnPix, upPix); + else + *dnPix = quickOverPix(*dnPix, upPix); + } + } + } + dn->unlock(); + up->unlock(); } //============================================================================= -void doQuickPutNoFilter( - const TRaster32P &dn, - const TRasterGR8P &up, - double sx, double sy, - double tx, double ty, - const TPixel32 &colorScale) -{ - if ((sx == 0) || (sy == 0)) - return; - - const int PADN = 16; - assert(std::max(up->getLx(), up->getLy()) < (1 << (8 * sizeof(int) - PADN - 1))); - - TAffine aff(sx, 0, tx, 0, sy, ty); - TRectD boundingBoxD = TRectD(convert(dn->getBounds())) * - (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5)); - - if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) - return; - - int yMin = std::max(tfloor(boundingBoxD.y0), 0); - int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); - int xMin = std::max(tfloor(boundingBoxD.x0), 0); - int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); - - TAffine invAff = inv(aff); // inversa di aff - - double deltaXD = invAff.a11; - double deltaYD = invAff.a22; - int deltaXL = tround(deltaXD * (1 << PADN)); - int deltaYL = tround(deltaYD * (1 << PADN)); - if ((deltaXL == 0) || (deltaYL == 0)) - return; - TPointD a = invAff * TPointD(xMin, yMin); - - int xL0 = tround((a.x + 0.5) * (1 << PADN)); - int yL0 = tround((a.y + 0.5) * (1 << PADN)); - int kMinX = 0, kMaxX = xMax - xMin; // clipping su dn - int kMinY = 0, kMaxY = yMax - yMin; // clipping su dn - int lxPred = up->getLx() * (1 << PADN) - 1; - int lyPred = up->getLy() * (1 << PADN) - 1; - - if (deltaYL > 0) // (deltaYL != 0) - { - assert(yL0 <= lyPred); - - kMaxY = (lyPred - yL0) / deltaYL; // floor - if (yL0 < 0) { - kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil - } - } else // (deltaYL < 0) - { - assert(0 <= yL0); - - kMaxY = yL0 / (-deltaYL); // floor - if (lyPred < yL0) { - kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil - } - } - kMinY = std::max(kMinY, (int)0); - kMaxY = std::min(kMaxY, yMax - yMin); - - if (deltaXL > 0) // (deltaXL != 0) - { - assert(xL0 <= lxPred); - - kMaxX = (lxPred - xL0) / deltaXL; // floor - if (xL0 < 0) { - kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil - } - } else // (deltaXL < 0) - { - assert(0 <= xL0); - - kMaxX = xL0 / (-deltaXL); // floor - if (lxPred < xL0) { - kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil - } - } - kMinX = std::max(kMinX, (int)0); - kMaxX = std::min(kMaxX, xMax - xMin); - - int dnWrap = dn->getWrap(); - int upWrap = up->getWrap(); - dn->lock(); - up->lock(); - - TPixelGR8 *upBasePix = up->pixels(); - TPixel32 *dnRow = dn->pixels(yMin + kMinY); - - int yL = yL0 + (kMinY - 1) * deltaYL; - - for (int kY = kMinY; kY <= kMaxY; kY++, dnRow += dnWrap) { - // inizializza xL - int xL = xL0 + (kMinX - 1) * deltaXL; - yL += deltaYL; - - // il punto di up TPointD(xL/(1<> PADN; // round - - TPixel32 *dnPix = dnRow + xMin + kMinX; - TPixel32 *dnEndPix = dnRow + xMin + kMaxX + 1; - - // scorre i pixel sulla (yMin + kY)-esima scanline di dn - for (; dnPix < dnEndPix; ++dnPix) { - xL += deltaXL; - int xI = xL >> PADN; // round - - assert((0 <= xI) && (xI <= up->getLx() - 1) && - (0 <= yI) && (yI <= up->getLy() - 1)); - - TPixelGR8 *upPix = upBasePix + (yI * upWrap + xI); - if (colorScale == TPixel32::Black) { - dnPix->r = dnPix->g = dnPix->b = upPix->value; - dnPix->m = 255; - } else { - TPixel32 upPix32(upPix->value, upPix->value, upPix->value, 255); - upPix32 = applyColorScale(upPix32, colorScale); - - if (upPix32.m == 255) - *dnPix = upPix32; - else - *dnPix = quickOverPix(*dnPix, upPix32); - } - - /* - if (upPix->value == 0) - dnPix->r = dnPix->g = dnPix->b = dnPix->m = upPix->value; - else if (upPix->value == 255) - dnPix->r = dnPix->g = dnPix->b = dnPix->m = upPix->value; - else - *dnPix = quickOverPix(*dnPix, *upPix); - */ - } - } - dn->unlock(); - up->unlock(); +void doQuickPutNoFilter(const TRaster32P &dn, const TRasterGR8P &up, double sx, + double sy, double tx, double ty, + const TPixel32 &colorScale) { + if ((sx == 0) || (sy == 0)) return; + + const int PADN = 16; + assert(std::max(up->getLx(), up->getLy()) < + (1 << (8 * sizeof(int) - PADN - 1))); + + TAffine aff(sx, 0, tx, 0, sy, ty); + TRectD boundingBoxD = + TRectD(convert(dn->getBounds())) * + (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5)); + + if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) + return; + + int yMin = std::max(tfloor(boundingBoxD.y0), 0); + int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); + int xMin = std::max(tfloor(boundingBoxD.x0), 0); + int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); + + TAffine invAff = inv(aff); // inversa di aff + + double deltaXD = invAff.a11; + double deltaYD = invAff.a22; + int deltaXL = tround(deltaXD * (1 << PADN)); + int deltaYL = tround(deltaYD * (1 << PADN)); + if ((deltaXL == 0) || (deltaYL == 0)) return; + TPointD a = invAff * TPointD(xMin, yMin); + + int xL0 = tround((a.x + 0.5) * (1 << PADN)); + int yL0 = tround((a.y + 0.5) * (1 << PADN)); + int kMinX = 0, kMaxX = xMax - xMin; // clipping su dn + int kMinY = 0, kMaxY = yMax - yMin; // clipping su dn + int lxPred = up->getLx() * (1 << PADN) - 1; + int lyPred = up->getLy() * (1 << PADN) - 1; + + if (deltaYL > 0) // (deltaYL != 0) + { + assert(yL0 <= lyPred); + + kMaxY = (lyPred - yL0) / deltaYL; // floor + if (yL0 < 0) { + kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil + } + } else // (deltaYL < 0) + { + assert(0 <= yL0); + + kMaxY = yL0 / (-deltaYL); // floor + if (lyPred < yL0) { + kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil + } + } + kMinY = std::max(kMinY, (int)0); + kMaxY = std::min(kMaxY, yMax - yMin); + + if (deltaXL > 0) // (deltaXL != 0) + { + assert(xL0 <= lxPred); + + kMaxX = (lxPred - xL0) / deltaXL; // floor + if (xL0 < 0) { + kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil + } + } else // (deltaXL < 0) + { + assert(0 <= xL0); + + kMaxX = xL0 / (-deltaXL); // floor + if (lxPred < xL0) { + kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil + } + } + kMinX = std::max(kMinX, (int)0); + kMaxX = std::min(kMaxX, xMax - xMin); + + int dnWrap = dn->getWrap(); + int upWrap = up->getWrap(); + dn->lock(); + up->lock(); + + TPixelGR8 *upBasePix = up->pixels(); + TPixel32 *dnRow = dn->pixels(yMin + kMinY); + + int yL = yL0 + (kMinY - 1) * deltaYL; + + for (int kY = kMinY; kY <= kMaxY; kY++, dnRow += dnWrap) { + // inizializza xL + int xL = xL0 + (kMinX - 1) * deltaXL; + yL += deltaYL; + + // il punto di up TPointD(xL/(1<> PADN; // round + + TPixel32 *dnPix = dnRow + xMin + kMinX; + TPixel32 *dnEndPix = dnRow + xMin + kMaxX + 1; + + // scorre i pixel sulla (yMin + kY)-esima scanline di dn + for (; dnPix < dnEndPix; ++dnPix) { + xL += deltaXL; + int xI = xL >> PADN; // round + + assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) && + (yI <= up->getLy() - 1)); + + TPixelGR8 *upPix = upBasePix + (yI * upWrap + xI); + if (colorScale == TPixel32::Black) { + dnPix->r = dnPix->g = dnPix->b = upPix->value; + dnPix->m = 255; + } else { + TPixel32 upPix32(upPix->value, upPix->value, upPix->value, 255); + upPix32 = applyColorScale(upPix32, colorScale); + + if (upPix32.m == 255) + *dnPix = upPix32; + else + *dnPix = quickOverPix(*dnPix, upPix32); + } + + /* +if (upPix->value == 0) +dnPix->r = dnPix->g = dnPix->b = dnPix->m = upPix->value; +else if (upPix->value == 255) +dnPix->r = dnPix->g = dnPix->b = dnPix->m = upPix->value; +else +*dnPix = quickOverPix(*dnPix, *upPix); +*/ + } + } + dn->unlock(); + up->unlock(); } -void doQuickResampleFilter( - const TRaster32P &dn, - const TRaster32P &up, - const TAffine &aff) -{ - // se aff e' degenere la controimmagine di up e' un segmento (o un punto) - if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) - return; - - // contatore bit di shift - const int PADN = 16; - - // maschera del filtro bilineare - const int MASKN = (1 << PADN) - 1; - assert(std::max(up->getLx(), up->getLy()) < (1 << (8 * sizeof(int) - PADN - 1))); - // max dimensioni di up gestibili (limite imposto dal numero di bit - // disponibili per la parte intera di xL, yL) - - TRectD boundingBoxD = TRectD(convert(dn->getSize())) * - (aff * TRectD(0, 0, up->getLx() - 2, up->getLy() - 2)); - - // clipping - if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) - return; - - // clipping y su dn - int yMin = std::max(tfloor(boundingBoxD.y0), 0); - - // clipping y su dn - int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); - - // clipping x su dn - int xMin = std::max(tfloor(boundingBoxD.x0), 0); - - // clipping x su dn - int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); - - TAffine invAff = inv(aff); // inversa di aff - - // nel disegnare la y-esima scanline di dn, il passaggio al pixel - // successivo comporta l'incremento (deltaXD, deltaYD) delle coordinate - // del pixel corrispondente di up - double deltaXD = invAff.a11; - double deltaYD = invAff.a21; - - // deltaXD "TLonghizzato" (round) - int deltaXL = tround(deltaXD * (1 << PADN)); - - // deltaYD "TLonghizzato" (round) - int deltaYL = tround(deltaYD * (1 << PADN)); - - // se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un - // segmento (o un punto) - if ((deltaXL == 0) && (deltaYL == 0)) - return; - - // naturale predecessore di up->getLx() - 1 - int lxPred = (up->getLx() - 2) * (1 << PADN); - - // naturale predecessore di up->getLy() - 1 - int lyPred = (up->getLy() - 2) * (1 << PADN); - - int dnWrap = dn->getWrap(); - int upWrap = up->getWrap(); - dn->lock(); - up->lock(); - - TPixel32 *dnRow = dn->pixels(yMin); - TPixel32 *upBasePix = up->pixels(); - - // scorre le scanline di boundingBoxD - for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) { - // (1) equazione k-parametrica della y-esima scanline di boundingBoxD: - // (xMin, y) + k*(1, 0), k = 0, ..., (xMax - xMin) - // - // (2) equazione k-parametrica dell'immagine mediante invAff di (1): - // invAff*(xMin, y) + k*(deltaXD, deltaYD), - // k = kMin, ..., kMax - // con 0 <= kMin <= kMax <= (xMax - xMin) - - // calcola kMin, kMax per la scanline corrente intersecando - // la (2) con i lati di up - - // il segmento [a, b] di up e' la controimmagine mediante aff della - // porzione di scanline [ (xMin, y), (xMax, y) ] di dn - - // TPointD b = invAff*TPointD(xMax, y); - TPointD a = invAff * TPointD(xMin, y); - - // (xL0, yL0) sono le coordinate di a in versione "TLonghizzata" - // 0 <= xL0 + k*deltaXL - // <= (up->getLx() - 2)*(1<getLy() - 2)*(1<getLx() - 2)*(1< - // 0 <= xL0 + k*deltaXL <= lxPred - - // 0 <= yL0 + k*deltaYL <= (up->getLy() - 2)*(1< - // 0 <= yL0 + k*deltaYL <= lyPred - - // calcola kMinX, kMaxX - if (deltaXL == 0) { - // [a, b] verticale esterno ad up contratto - if ((xL0 < 0) || (lxPred < xL0)) - continue; - // altrimenti usa solo - // kMinY, kMaxY ((deltaXL != 0) || (deltaYL != 0)) - } else if (deltaXL > 0) { - // [a, b] esterno ad up+(bordo destro) - if (lxPred < xL0) - continue; - - kMaxX = (lxPred - xL0) / deltaXL; // floor - if (xL0 < 0) { - kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil - } - } else // (deltaXL < 0) - { - // [a, b] esterno ad up contratto - if (xL0 < 0) - continue; - - kMaxX = xL0 / (-deltaXL); // floor - if (lxPred < xL0) { - kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil - } - } - - // calcola kMinY, kMaxY - if (deltaYL == 0) { - // [a, b] orizzontale esterno ad up contratto - if ((yL0 < 0) || (lyPred < yL0)) - continue; - // altrimenti usa solo - // kMinX, kMaxX ((deltaXL != 0) || (deltaYL != 0)) - } else if (deltaYL > 0) { - // [a, b] esterno ad up contratto - if (lyPred < yL0) - continue; - - kMaxY = (lyPred - yL0) / deltaYL; // floor - if (yL0 < 0) { - kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil - } - } else // (deltaYL < 0) - { - // [a, b] esterno ad up contratto - if (yL0 < 0) - continue; - - kMaxY = yL0 / (-deltaYL); // floor - if (lyPred < yL0) { - kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil - } - } - - // calcola kMin, kMax effettuando anche il clippind su dn - int kMin = std::max({kMinX, kMinY, (int)0}); - int kMax = std::min({kMaxX, kMaxY, xMax - xMin}); - - TPixel32 *dnPix = dnRow + xMin + kMin; - TPixel32 *dnEndPix = dnRow + xMin + kMax + 1; - - // (xL, yL) sono le coordinate (inizializzate per il round) - // in versione "longhizzata" del pixel corrente di up - int xL = xL0 + (kMin - 1) * deltaXL; // inizializza xL - int yL = yL0 + (kMin - 1) * deltaYL; // inizializza yL - - // scorre i pixel sulla y-esima scanline di boundingBoxD - for (; dnPix < dnEndPix; ++dnPix) { - xL += deltaXL; - yL += deltaYL; - // il punto di up TPointD(xL/(1<> PADN; // troncato - int yI = yL >> PADN; // troncato - - assert((0 <= xI) && (xI <= up->getLx() - 1) && - (0 <= yI) && (yI <= up->getLy() - 1)); - - // (xI, yI) - TPixel32 *upPix00 = upBasePix + (yI * upWrap + xI); - - // (xI + 1, yI) - TPixel32 *upPix10 = upPix00 + 1; - - // (xI, yI + 1) - TPixel32 *upPix01 = upPix00 + upWrap; - - // (xI + 1, yI + 1) - TPixel32 *upPix11 = upPix00 + upWrap + 1; - - // filtro bilineare 4 pixels: calcolo dei pesi - int xWeight1 = (xL & MASKN); - int xWeight0 = (1 << PADN) - xWeight1; - int yWeight1 = (yL & MASKN); - int yWeight0 = (1 << PADN) - yWeight1; - - // filtro bilineare 4 pixels: media pesata sui singoli canali - int rColDownTmp = - (xWeight0 * (upPix00->r) + xWeight1 * ((upPix10)->r)) >> PADN; - - int gColDownTmp = - (xWeight0 * (upPix00->g) + xWeight1 * ((upPix10)->g)) >> PADN; - - int bColDownTmp = - (xWeight0 * (upPix00->b) + xWeight1 * ((upPix10)->b)) >> PADN; - - int mColDownTmp = - (xWeight0 * (upPix00->m) + xWeight1 * ((upPix10)->m)) >> PADN; - - int rColUpTmp = - (xWeight0 * ((upPix01)->r) + xWeight1 * ((upPix11)->r)) >> PADN; - - int gColUpTmp = - (xWeight0 * ((upPix01)->g) + xWeight1 * ((upPix11)->g)) >> PADN; - - int bColUpTmp = - (xWeight0 * ((upPix01)->b) + xWeight1 * ((upPix11)->b)) >> PADN; - - int mColUpTmp = - (xWeight0 * ((upPix01)->m) + xWeight1 * ((upPix11)->m)) >> PADN; - - dnPix->r = (unsigned char)((yWeight0 * rColDownTmp + yWeight1 * rColUpTmp) >> PADN); - dnPix->g = (unsigned char)((yWeight0 * gColDownTmp + yWeight1 * gColUpTmp) >> PADN); - dnPix->b = (unsigned char)((yWeight0 * bColDownTmp + yWeight1 * bColUpTmp) >> PADN); - dnPix->m = (unsigned char)((yWeight0 * mColDownTmp + yWeight1 * mColUpTmp) >> PADN); - } - } - dn->unlock(); - up->unlock(); +void doQuickResampleFilter(const TRaster32P &dn, const TRaster32P &up, + const TAffine &aff) { + // se aff e' degenere la controimmagine di up e' un segmento (o un punto) + if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) return; + + // contatore bit di shift + const int PADN = 16; + + // maschera del filtro bilineare + const int MASKN = (1 << PADN) - 1; + assert(std::max(up->getLx(), up->getLy()) < + (1 << (8 * sizeof(int) - PADN - 1))); + // max dimensioni di up gestibili (limite imposto dal numero di bit + // disponibili per la parte intera di xL, yL) + + TRectD boundingBoxD = TRectD(convert(dn->getSize())) * + (aff * TRectD(0, 0, up->getLx() - 2, up->getLy() - 2)); + + // clipping + if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) + return; + + // clipping y su dn + int yMin = std::max(tfloor(boundingBoxD.y0), 0); + + // clipping y su dn + int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); + + // clipping x su dn + int xMin = std::max(tfloor(boundingBoxD.x0), 0); + + // clipping x su dn + int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); + + TAffine invAff = inv(aff); // inversa di aff + + // nel disegnare la y-esima scanline di dn, il passaggio al pixel + // successivo comporta l'incremento (deltaXD, deltaYD) delle coordinate + // del pixel corrispondente di up + double deltaXD = invAff.a11; + double deltaYD = invAff.a21; + + // deltaXD "TLonghizzato" (round) + int deltaXL = tround(deltaXD * (1 << PADN)); + + // deltaYD "TLonghizzato" (round) + int deltaYL = tround(deltaYD * (1 << PADN)); + + // se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un + // segmento (o un punto) + if ((deltaXL == 0) && (deltaYL == 0)) return; + + // naturale predecessore di up->getLx() - 1 + int lxPred = (up->getLx() - 2) * (1 << PADN); + + // naturale predecessore di up->getLy() - 1 + int lyPred = (up->getLy() - 2) * (1 << PADN); + + int dnWrap = dn->getWrap(); + int upWrap = up->getWrap(); + dn->lock(); + up->lock(); + + TPixel32 *dnRow = dn->pixels(yMin); + TPixel32 *upBasePix = up->pixels(); + + // scorre le scanline di boundingBoxD + for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) { + // (1) equazione k-parametrica della y-esima scanline di boundingBoxD: + // (xMin, y) + k*(1, 0), k = 0, ..., (xMax - xMin) + // + // (2) equazione k-parametrica dell'immagine mediante invAff di (1): + // invAff*(xMin, y) + k*(deltaXD, deltaYD), + // k = kMin, ..., kMax + // con 0 <= kMin <= kMax <= (xMax - xMin) + + // calcola kMin, kMax per la scanline corrente intersecando + // la (2) con i lati di up + + // il segmento [a, b] di up e' la controimmagine mediante aff della + // porzione di scanline [ (xMin, y), (xMax, y) ] di dn + + // TPointD b = invAff*TPointD(xMax, y); + TPointD a = invAff * TPointD(xMin, y); + + // (xL0, yL0) sono le coordinate di a in versione "TLonghizzata" + // 0 <= xL0 + k*deltaXL + // <= (up->getLx() - 2)*(1<getLy() - 2)*(1<getLx() - 2)*(1< + // 0 <= xL0 + k*deltaXL <= lxPred + + // 0 <= yL0 + k*deltaYL <= (up->getLy() - 2)*(1< + // 0 <= yL0 + k*deltaYL <= lyPred + + // calcola kMinX, kMaxX + if (deltaXL == 0) { + // [a, b] verticale esterno ad up contratto + if ((xL0 < 0) || (lxPred < xL0)) continue; + // altrimenti usa solo + // kMinY, kMaxY ((deltaXL != 0) || (deltaYL != 0)) + } else if (deltaXL > 0) { + // [a, b] esterno ad up+(bordo destro) + if (lxPred < xL0) continue; + + kMaxX = (lxPred - xL0) / deltaXL; // floor + if (xL0 < 0) { + kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil + } + } else // (deltaXL < 0) + { + // [a, b] esterno ad up contratto + if (xL0 < 0) continue; + + kMaxX = xL0 / (-deltaXL); // floor + if (lxPred < xL0) { + kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil + } + } + + // calcola kMinY, kMaxY + if (deltaYL == 0) { + // [a, b] orizzontale esterno ad up contratto + if ((yL0 < 0) || (lyPred < yL0)) continue; + // altrimenti usa solo + // kMinX, kMaxX ((deltaXL != 0) || (deltaYL != 0)) + } else if (deltaYL > 0) { + // [a, b] esterno ad up contratto + if (lyPred < yL0) continue; + + kMaxY = (lyPred - yL0) / deltaYL; // floor + if (yL0 < 0) { + kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil + } + } else // (deltaYL < 0) + { + // [a, b] esterno ad up contratto + if (yL0 < 0) continue; + + kMaxY = yL0 / (-deltaYL); // floor + if (lyPred < yL0) { + kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil + } + } + + // calcola kMin, kMax effettuando anche il clippind su dn + int kMin = std::max({kMinX, kMinY, (int)0}); + int kMax = std::min({kMaxX, kMaxY, xMax - xMin}); + + TPixel32 *dnPix = dnRow + xMin + kMin; + TPixel32 *dnEndPix = dnRow + xMin + kMax + 1; + + // (xL, yL) sono le coordinate (inizializzate per il round) + // in versione "longhizzata" del pixel corrente di up + int xL = xL0 + (kMin - 1) * deltaXL; // inizializza xL + int yL = yL0 + (kMin - 1) * deltaYL; // inizializza yL + + // scorre i pixel sulla y-esima scanline di boundingBoxD + for (; dnPix < dnEndPix; ++dnPix) { + xL += deltaXL; + yL += deltaYL; + // il punto di up TPointD(xL/(1<> PADN; // troncato + int yI = yL >> PADN; // troncato + + assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) && + (yI <= up->getLy() - 1)); + + // (xI, yI) + TPixel32 *upPix00 = upBasePix + (yI * upWrap + xI); + + // (xI + 1, yI) + TPixel32 *upPix10 = upPix00 + 1; + + // (xI, yI + 1) + TPixel32 *upPix01 = upPix00 + upWrap; + + // (xI + 1, yI + 1) + TPixel32 *upPix11 = upPix00 + upWrap + 1; + + // filtro bilineare 4 pixels: calcolo dei pesi + int xWeight1 = (xL & MASKN); + int xWeight0 = (1 << PADN) - xWeight1; + int yWeight1 = (yL & MASKN); + int yWeight0 = (1 << PADN) - yWeight1; + + // filtro bilineare 4 pixels: media pesata sui singoli canali + int rColDownTmp = + (xWeight0 * (upPix00->r) + xWeight1 * ((upPix10)->r)) >> PADN; + + int gColDownTmp = + (xWeight0 * (upPix00->g) + xWeight1 * ((upPix10)->g)) >> PADN; + + int bColDownTmp = + (xWeight0 * (upPix00->b) + xWeight1 * ((upPix10)->b)) >> PADN; + + int mColDownTmp = + (xWeight0 * (upPix00->m) + xWeight1 * ((upPix10)->m)) >> PADN; + + int rColUpTmp = + (xWeight0 * ((upPix01)->r) + xWeight1 * ((upPix11)->r)) >> PADN; + + int gColUpTmp = + (xWeight0 * ((upPix01)->g) + xWeight1 * ((upPix11)->g)) >> PADN; + + int bColUpTmp = + (xWeight0 * ((upPix01)->b) + xWeight1 * ((upPix11)->b)) >> PADN; + + int mColUpTmp = + (xWeight0 * ((upPix01)->m) + xWeight1 * ((upPix11)->m)) >> PADN; + + dnPix->r = + (unsigned char)((yWeight0 * rColDownTmp + yWeight1 * rColUpTmp) >> + PADN); + dnPix->g = + (unsigned char)((yWeight0 * gColDownTmp + yWeight1 * gColUpTmp) >> + PADN); + dnPix->b = + (unsigned char)((yWeight0 * bColDownTmp + yWeight1 * bColUpTmp) >> + PADN); + dnPix->m = + (unsigned char)((yWeight0 * mColDownTmp + yWeight1 * mColUpTmp) >> + PADN); + } + } + dn->unlock(); + up->unlock(); } //============================================================================= //============================================================================= //============================================================================= -void doQuickResampleFilter( - const TRaster32P &dn, - const TRasterGR8P &up, - const TAffine &aff) -{ - if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) - return; - - const int PADN = 16; - - const int MASKN = (1 << PADN) - 1; - assert(std::max(up->getLx(), up->getLy()) < (1 << (8 * sizeof(int) - PADN - 1))); - - TRectD boundingBoxD = TRectD(convert(dn->getSize())) * - (aff * TRectD(0, 0, up->getLx() - 2, up->getLy() - 2)); - - // clipping - if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) - return; - - int yMin = std::max(tfloor(boundingBoxD.y0), 0); - int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); - int xMin = std::max(tfloor(boundingBoxD.x0), 0); - int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); - - TAffine invAff = inv(aff); // inversa di aff - - double deltaXD = invAff.a11; - double deltaYD = invAff.a21; - int deltaXL = tround(deltaXD * (1 << PADN)); - int deltaYL = tround(deltaYD * (1 << PADN)); - if ((deltaXL == 0) && (deltaYL == 0)) - return; - - int lxPred = (up->getLx() - 2) * (1 << PADN); - int lyPred = (up->getLy() - 2) * (1 << PADN); - - int dnWrap = dn->getWrap(); - int upWrap = up->getWrap(); - dn->lock(); - up->lock(); - - TPixel32 *dnRow = dn->pixels(yMin); - TPixelGR8 *upBasePix = up->pixels(); - - for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) { - TPointD a = invAff * TPointD(xMin, y); - int xL0 = tround(a.x * (1 << PADN)); - int yL0 = tround(a.y * (1 << PADN)); - int kMinX = 0, kMaxX = xMax - xMin; // clipping su dn - int kMinY = 0, kMaxY = xMax - xMin; // clipping su dn - - if (deltaXL == 0) { - if ((xL0 < 0) || (lxPred < xL0)) - continue; - } else if (deltaXL > 0) { - if (lxPred < xL0) - continue; - - kMaxX = (lxPred - xL0) / deltaXL; // floor - if (xL0 < 0) { - kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil - } - } else { - if (xL0 < 0) - continue; - - kMaxX = xL0 / (-deltaXL); // floor - if (lxPred < xL0) { - kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil - } - } - - if (deltaYL == 0) { - if ((yL0 < 0) || (lyPred < yL0)) - continue; - } else if (deltaYL > 0) { - if (lyPred < yL0) - continue; - - kMaxY = (lyPred - yL0) / deltaYL; // floor - if (yL0 < 0) { - kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil - } - } else // (deltaYL < 0) - { - - if (yL0 < 0) - continue; - - kMaxY = yL0 / (-deltaYL); // floor - if (lyPred < yL0) { - kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil - } - } - - int kMin = std::max({kMinX, kMinY, (int)0}); - int kMax = std::min({kMaxX, kMaxY, xMax - xMin}); - - TPixel32 *dnPix = dnRow + xMin + kMin; - TPixel32 *dnEndPix = dnRow + xMin + kMax + 1; - - int xL = xL0 + (kMin - 1) * deltaXL; // inizializza xL - int yL = yL0 + (kMin - 1) * deltaYL; // inizializza yL - - for (; dnPix < dnEndPix; ++dnPix) { - xL += deltaXL; - yL += deltaYL; - - int xI = xL >> PADN; // troncato - int yI = yL >> PADN; // troncato - - assert((0 <= xI) && (xI <= up->getLx() - 1) && - (0 <= yI) && (yI <= up->getLy() - 1)); - - // (xI, yI) - TPixelGR8 *upPix00 = upBasePix + (yI * upWrap + xI); - - // (xI + 1, yI) - TPixelGR8 *upPix10 = upPix00 + 1; - - // (xI, yI + 1) - TPixelGR8 *upPix01 = upPix00 + upWrap; - - // (xI + 1, yI + 1) - TPixelGR8 *upPix11 = upPix00 + upWrap + 1; - - // filtro bilineare 4 pixels: calcolo dei pesi - int xWeight1 = (xL & MASKN); - int xWeight0 = (1 << PADN) - xWeight1; - int yWeight1 = (yL & MASKN); - int yWeight0 = (1 << PADN) - yWeight1; - - // filtro bilineare 4 pixels: media pesata sui singoli canali - int colDownTmp = - (xWeight0 * (upPix00->value) + xWeight1 * ((upPix10)->value)) >> PADN; - - int colUpTmp = - (xWeight0 * ((upPix01)->value) + xWeight1 * ((upPix11)->value)) >> PADN; - - dnPix->r = dnPix->g = dnPix->b = (unsigned char)((yWeight0 * colDownTmp + yWeight1 * colUpTmp) >> PADN); - - dnPix->m = 255; - } - } - dn->unlock(); - up->unlock(); +void doQuickResampleFilter(const TRaster32P &dn, const TRasterGR8P &up, + const TAffine &aff) { + if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) return; + + const int PADN = 16; + + const int MASKN = (1 << PADN) - 1; + assert(std::max(up->getLx(), up->getLy()) < + (1 << (8 * sizeof(int) - PADN - 1))); + + TRectD boundingBoxD = TRectD(convert(dn->getSize())) * + (aff * TRectD(0, 0, up->getLx() - 2, up->getLy() - 2)); + + // clipping + if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) + return; + + int yMin = std::max(tfloor(boundingBoxD.y0), 0); + int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); + int xMin = std::max(tfloor(boundingBoxD.x0), 0); + int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); + + TAffine invAff = inv(aff); // inversa di aff + + double deltaXD = invAff.a11; + double deltaYD = invAff.a21; + int deltaXL = tround(deltaXD * (1 << PADN)); + int deltaYL = tround(deltaYD * (1 << PADN)); + if ((deltaXL == 0) && (deltaYL == 0)) return; + + int lxPred = (up->getLx() - 2) * (1 << PADN); + int lyPred = (up->getLy() - 2) * (1 << PADN); + + int dnWrap = dn->getWrap(); + int upWrap = up->getWrap(); + dn->lock(); + up->lock(); + + TPixel32 *dnRow = dn->pixels(yMin); + TPixelGR8 *upBasePix = up->pixels(); + + for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) { + TPointD a = invAff * TPointD(xMin, y); + int xL0 = tround(a.x * (1 << PADN)); + int yL0 = tround(a.y * (1 << PADN)); + int kMinX = 0, kMaxX = xMax - xMin; // clipping su dn + int kMinY = 0, kMaxY = xMax - xMin; // clipping su dn + + if (deltaXL == 0) { + if ((xL0 < 0) || (lxPred < xL0)) continue; + } else if (deltaXL > 0) { + if (lxPred < xL0) continue; + + kMaxX = (lxPred - xL0) / deltaXL; // floor + if (xL0 < 0) { + kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil + } + } else { + if (xL0 < 0) continue; + + kMaxX = xL0 / (-deltaXL); // floor + if (lxPred < xL0) { + kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil + } + } + + if (deltaYL == 0) { + if ((yL0 < 0) || (lyPred < yL0)) continue; + } else if (deltaYL > 0) { + if (lyPred < yL0) continue; + + kMaxY = (lyPred - yL0) / deltaYL; // floor + if (yL0 < 0) { + kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil + } + } else // (deltaYL < 0) + { + if (yL0 < 0) continue; + + kMaxY = yL0 / (-deltaYL); // floor + if (lyPred < yL0) { + kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil + } + } + + int kMin = std::max({kMinX, kMinY, (int)0}); + int kMax = std::min({kMaxX, kMaxY, xMax - xMin}); + + TPixel32 *dnPix = dnRow + xMin + kMin; + TPixel32 *dnEndPix = dnRow + xMin + kMax + 1; + + int xL = xL0 + (kMin - 1) * deltaXL; // inizializza xL + int yL = yL0 + (kMin - 1) * deltaYL; // inizializza yL + + for (; dnPix < dnEndPix; ++dnPix) { + xL += deltaXL; + yL += deltaYL; + + int xI = xL >> PADN; // troncato + int yI = yL >> PADN; // troncato + + assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) && + (yI <= up->getLy() - 1)); + + // (xI, yI) + TPixelGR8 *upPix00 = upBasePix + (yI * upWrap + xI); + + // (xI + 1, yI) + TPixelGR8 *upPix10 = upPix00 + 1; + + // (xI, yI + 1) + TPixelGR8 *upPix01 = upPix00 + upWrap; + + // (xI + 1, yI + 1) + TPixelGR8 *upPix11 = upPix00 + upWrap + 1; + + // filtro bilineare 4 pixels: calcolo dei pesi + int xWeight1 = (xL & MASKN); + int xWeight0 = (1 << PADN) - xWeight1; + int yWeight1 = (yL & MASKN); + int yWeight0 = (1 << PADN) - yWeight1; + + // filtro bilineare 4 pixels: media pesata sui singoli canali + int colDownTmp = + (xWeight0 * (upPix00->value) + xWeight1 * ((upPix10)->value)) >> PADN; + + int colUpTmp = + (xWeight0 * ((upPix01)->value) + xWeight1 * ((upPix11)->value)) >> + PADN; + + dnPix->r = dnPix->g = dnPix->b = + (unsigned char)((yWeight0 * colDownTmp + yWeight1 * colUpTmp) >> + PADN); + + dnPix->m = 255; + } + } + dn->unlock(); + up->unlock(); } //============================================================================= //============================================================================= //============================================================================= -void doQuickResampleColorFilter( - const TRaster32P &dn, - const TRaster32P &up, - const TAffine &aff, - UCHAR colorMask) -{ - if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) - return; - const int PADN = 16; - - assert(std::max(up->getLx(), up->getLy()) < (1 << (8 * sizeof(int) - PADN - 1))); - - TRectD boundingBoxD = TRectD(convert(dn->getBounds())) * - (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5)); - - if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) - return; - - int yMin = std::max(tfloor(boundingBoxD.y0), 0); // clipping y su dn - int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); // clipping y su dn - int xMin = std::max(tfloor(boundingBoxD.x0), 0); // clipping x su dn - int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); // clipping x su dn - - TAffine invAff = inv(aff); // inversa di aff - - double deltaXD = invAff.a11; - double deltaYD = invAff.a21; - int deltaXL = tround(deltaXD * (1 << PADN)); // deltaXD "TLonghizzato" (round) - int deltaYL = tround(deltaYD * (1 << PADN)); // deltaYD "TLonghizzato" (round) - if ((deltaXL == 0) && (deltaYL == 0)) - return; - - int lxPred = up->getLx() * (1 << PADN) - 1; // TINT32 predecessore di up->getLx() - int lyPred = up->getLy() * (1 << PADN) - 1; // TINT32 predecessore di up->getLy() - - int dnWrap = dn->getWrap(); - int upWrap = up->getWrap(); - dn->lock(); - up->lock(); - - TPixel32 *dnRow = dn->pixels(yMin); - TPixel32 *upBasePix = up->pixels(); - - for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) { - TPointD a = invAff * TPointD(xMin, y); - int xL0 = tround((a.x + 0.5) * (1 << PADN)); - int yL0 = tround((a.y + 0.5) * (1 << PADN)); - int kMinX = 0, kMaxX = xMax - xMin; // clipping su dn - int kMinY = 0, kMaxY = xMax - xMin; // clipping su dn - if (deltaXL == 0) { - if ((xL0 < 0) || (lxPred < xL0)) - continue; - } else if (deltaXL > 0) { - if (lxPred < xL0) - continue; - - kMaxX = (lxPred - xL0) / deltaXL; // floor - if (xL0 < 0) - kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil - } else // (deltaXL < 0) - { - if (xL0 < 0) - continue; - kMaxX = xL0 / (-deltaXL); // floor - if (lxPred < xL0) - kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil - } - if (deltaYL == 0) { - if ((yL0 < 0) || (lyPred < yL0)) - continue; - } else if (deltaYL > 0) { - if (lyPred < yL0) - continue; - - kMaxY = (lyPred - yL0) / deltaYL; // floor - if (yL0 < 0) - kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil - } else // (deltaYL < 0) - { - if (yL0 < 0) - continue; - - kMaxY = yL0 / (-deltaYL); // floor - if (lyPred < yL0) - kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil - } - int kMin = std::max({kMinX, kMinY, (int)0}); - int kMax = std::min({kMaxX, kMaxY, xMax - xMin}); - TPixel32 *dnPix = dnRow + xMin + kMin; - TPixel32 *dnEndPix = dnRow + xMin + kMax + 1; - int xL = xL0 + (kMin - 1) * deltaXL; // inizializza xL - int yL = yL0 + (kMin - 1) * deltaYL; // inizializza yL - for (; dnPix < dnEndPix; ++dnPix) { - xL += deltaXL; - yL += deltaYL; - int xI = xL >> PADN; // round - int yI = yL >> PADN; // round - - assert((0 <= xI) && (xI <= up->getLx() - 1) && - (0 <= yI) && (yI <= up->getLy() - 1)); - - if (colorMask == TRop::MChan) - dnPix->r = dnPix->g = dnPix->b = (upBasePix + (yI * upWrap + xI))->m; - else { - TPixel32 *pix = upBasePix + (yI * upWrap + xI); - dnPix->r = ((colorMask & TRop::RChan) ? pix->r : 0); - dnPix->g = ((colorMask & TRop::GChan) ? pix->g : 0); - dnPix->b = ((colorMask & TRop::BChan) ? pix->b : 0); - } - dnPix->m = 255; - } - } - dn->unlock(); - up->unlock(); +void doQuickResampleColorFilter(const TRaster32P &dn, const TRaster32P &up, + const TAffine &aff, UCHAR colorMask) { + if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) return; + const int PADN = 16; + + assert(std::max(up->getLx(), up->getLy()) < + (1 << (8 * sizeof(int) - PADN - 1))); + + TRectD boundingBoxD = + TRectD(convert(dn->getBounds())) * + (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5)); + + if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) + return; + + int yMin = std::max(tfloor(boundingBoxD.y0), 0); // clipping y su dn + int yMax = + std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); // clipping y su dn + int xMin = std::max(tfloor(boundingBoxD.x0), 0); // clipping x su dn + int xMax = + std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); // clipping x su dn + + TAffine invAff = inv(aff); // inversa di aff + + double deltaXD = invAff.a11; + double deltaYD = invAff.a21; + int deltaXL = + tround(deltaXD * (1 << PADN)); // deltaXD "TLonghizzato" (round) + int deltaYL = + tround(deltaYD * (1 << PADN)); // deltaYD "TLonghizzato" (round) + if ((deltaXL == 0) && (deltaYL == 0)) return; + + int lxPred = + up->getLx() * (1 << PADN) - 1; // TINT32 predecessore di up->getLx() + int lyPred = + up->getLy() * (1 << PADN) - 1; // TINT32 predecessore di up->getLy() + + int dnWrap = dn->getWrap(); + int upWrap = up->getWrap(); + dn->lock(); + up->lock(); + + TPixel32 *dnRow = dn->pixels(yMin); + TPixel32 *upBasePix = up->pixels(); + + for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) { + TPointD a = invAff * TPointD(xMin, y); + int xL0 = tround((a.x + 0.5) * (1 << PADN)); + int yL0 = tround((a.y + 0.5) * (1 << PADN)); + int kMinX = 0, kMaxX = xMax - xMin; // clipping su dn + int kMinY = 0, kMaxY = xMax - xMin; // clipping su dn + if (deltaXL == 0) { + if ((xL0 < 0) || (lxPred < xL0)) continue; + } else if (deltaXL > 0) { + if (lxPred < xL0) continue; + + kMaxX = (lxPred - xL0) / deltaXL; // floor + if (xL0 < 0) kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil + } else // (deltaXL < 0) + { + if (xL0 < 0) continue; + kMaxX = xL0 / (-deltaXL); // floor + if (lxPred < xL0) + kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil + } + if (deltaYL == 0) { + if ((yL0 < 0) || (lyPred < yL0)) continue; + } else if (deltaYL > 0) { + if (lyPred < yL0) continue; + + kMaxY = (lyPred - yL0) / deltaYL; // floor + if (yL0 < 0) kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil + } else // (deltaYL < 0) + { + if (yL0 < 0) continue; + + kMaxY = yL0 / (-deltaYL); // floor + if (lyPred < yL0) + kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil + } + int kMin = std::max({kMinX, kMinY, (int)0}); + int kMax = std::min({kMaxX, kMaxY, xMax - xMin}); + TPixel32 *dnPix = dnRow + xMin + kMin; + TPixel32 *dnEndPix = dnRow + xMin + kMax + 1; + int xL = xL0 + (kMin - 1) * deltaXL; // inizializza xL + int yL = yL0 + (kMin - 1) * deltaYL; // inizializza yL + for (; dnPix < dnEndPix; ++dnPix) { + xL += deltaXL; + yL += deltaYL; + int xI = xL >> PADN; // round + int yI = yL >> PADN; // round + + assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) && + (yI <= up->getLy() - 1)); + + if (colorMask == TRop::MChan) + dnPix->r = dnPix->g = dnPix->b = (upBasePix + (yI * upWrap + xI))->m; + else { + TPixel32 *pix = upBasePix + (yI * upWrap + xI); + dnPix->r = ((colorMask & TRop::RChan) ? pix->r : 0); + dnPix->g = ((colorMask & TRop::GChan) ? pix->g : 0); + dnPix->b = ((colorMask & TRop::BChan) ? pix->b : 0); + } + dnPix->m = 255; + } + } + dn->unlock(); + up->unlock(); } //============================================================================= //============================================================================= @@ -2181,801 +2114,804 @@ void doQuickResampleColorFilter( //============================================================================= //============================================================================= -void doQuickResampleColorFilter( - const TRaster32P &dn, - const TRaster64P &up, - const TAffine &aff, - UCHAR colorMask) -{ - if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) - return; - const int PADN = 16; - - assert(std::max(up->getLx(), up->getLy()) < (1 << (8 * sizeof(int) - PADN - 1))); - - TRectD boundingBoxD = TRectD(convert(dn->getBounds())) * - (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5)); - - if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) - return; - - int yMin = std::max(tfloor(boundingBoxD.y0), 0); // clipping y su dn - int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); // clipping y su dn - int xMin = std::max(tfloor(boundingBoxD.x0), 0); // clipping x su dn - int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); // clipping x su dn - - TAffine invAff = inv(aff); // inversa di aff - - double deltaXD = invAff.a11; - double deltaYD = invAff.a21; - int deltaXL = tround(deltaXD * (1 << PADN)); // deltaXD "TLonghizzato" (round) - int deltaYL = tround(deltaYD * (1 << PADN)); // deltaYD "TLonghizzato" (round) - if ((deltaXL == 0) && (deltaYL == 0)) - return; - - int lxPred = up->getLx() * (1 << PADN) - 1; // TINT32 predecessore di up->getLx() - int lyPred = up->getLy() * (1 << PADN) - 1; // TINT32 predecessore di up->getLy() - - int dnWrap = dn->getWrap(); - int upWrap = up->getWrap(); - dn->lock(); - up->lock(); - - TPixel32 *dnRow = dn->pixels(yMin); - TPixel64 *upBasePix = up->pixels(); - - for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) { - TPointD a = invAff * TPointD(xMin, y); - int xL0 = tround((a.x + 0.5) * (1 << PADN)); - int yL0 = tround((a.y + 0.5) * (1 << PADN)); - int kMinX = 0, kMaxX = xMax - xMin; // clipping su dn - int kMinY = 0, kMaxY = xMax - xMin; // clipping su dn - if (deltaXL == 0) { - if ((xL0 < 0) || (lxPred < xL0)) - continue; - } else if (deltaXL > 0) { - if (lxPred < xL0) - continue; - - kMaxX = (lxPred - xL0) / deltaXL; // floor - if (xL0 < 0) - kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil - } else // (deltaXL < 0) - { - if (xL0 < 0) - continue; - kMaxX = xL0 / (-deltaXL); // floor - if (lxPred < xL0) - kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil - } - if (deltaYL == 0) { - if ((yL0 < 0) || (lyPred < yL0)) - continue; - } else if (deltaYL > 0) { - if (lyPred < yL0) - continue; - - kMaxY = (lyPred - yL0) / deltaYL; // floor - if (yL0 < 0) - kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil - } else // (deltaYL < 0) - { - if (yL0 < 0) - continue; - - kMaxY = yL0 / (-deltaYL); // floor - if (lyPred < yL0) - kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil - } - int kMin = std::max({kMinX, kMinY, (int)0}); - int kMax = std::min({kMaxX, kMaxY, xMax - xMin}); - TPixel32 *dnPix = dnRow + xMin + kMin; - TPixel32 *dnEndPix = dnRow + xMin + kMax + 1; - int xL = xL0 + (kMin - 1) * deltaXL; // inizializza xL - int yL = yL0 + (kMin - 1) * deltaYL; // inizializza yL - for (; dnPix < dnEndPix; ++dnPix) { - xL += deltaXL; - yL += deltaYL; - int xI = xL >> PADN; // round - int yI = yL >> PADN; // round - - assert((0 <= xI) && (xI <= up->getLx() - 1) && - (0 <= yI) && (yI <= up->getLy() - 1)); - - if (colorMask == TRop::MChan) - dnPix->r = dnPix->g = dnPix->b = byteFromUshort((upBasePix + (yI * upWrap + xI))->m); - else { - TPixel64 *pix = upBasePix + (yI * upWrap + xI); - dnPix->r = byteFromUshort(((colorMask & TRop::RChan) ? pix->r : 0)); - dnPix->g = byteFromUshort(((colorMask & TRop::GChan) ? pix->g : 0)); - dnPix->b = byteFromUshort(((colorMask & TRop::BChan) ? pix->b : 0)); - } - dnPix->m = 255; - } - } - dn->unlock(); - up->unlock(); +void doQuickResampleColorFilter(const TRaster32P &dn, const TRaster64P &up, + const TAffine &aff, UCHAR colorMask) { + if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) return; + const int PADN = 16; + + assert(std::max(up->getLx(), up->getLy()) < + (1 << (8 * sizeof(int) - PADN - 1))); + + TRectD boundingBoxD = + TRectD(convert(dn->getBounds())) * + (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5)); + + if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) + return; + + int yMin = std::max(tfloor(boundingBoxD.y0), 0); // clipping y su dn + int yMax = + std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); // clipping y su dn + int xMin = std::max(tfloor(boundingBoxD.x0), 0); // clipping x su dn + int xMax = + std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); // clipping x su dn + + TAffine invAff = inv(aff); // inversa di aff + + double deltaXD = invAff.a11; + double deltaYD = invAff.a21; + int deltaXL = + tround(deltaXD * (1 << PADN)); // deltaXD "TLonghizzato" (round) + int deltaYL = + tround(deltaYD * (1 << PADN)); // deltaYD "TLonghizzato" (round) + if ((deltaXL == 0) && (deltaYL == 0)) return; + + int lxPred = + up->getLx() * (1 << PADN) - 1; // TINT32 predecessore di up->getLx() + int lyPred = + up->getLy() * (1 << PADN) - 1; // TINT32 predecessore di up->getLy() + + int dnWrap = dn->getWrap(); + int upWrap = up->getWrap(); + dn->lock(); + up->lock(); + + TPixel32 *dnRow = dn->pixels(yMin); + TPixel64 *upBasePix = up->pixels(); + + for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) { + TPointD a = invAff * TPointD(xMin, y); + int xL0 = tround((a.x + 0.5) * (1 << PADN)); + int yL0 = tround((a.y + 0.5) * (1 << PADN)); + int kMinX = 0, kMaxX = xMax - xMin; // clipping su dn + int kMinY = 0, kMaxY = xMax - xMin; // clipping su dn + if (deltaXL == 0) { + if ((xL0 < 0) || (lxPred < xL0)) continue; + } else if (deltaXL > 0) { + if (lxPred < xL0) continue; + + kMaxX = (lxPred - xL0) / deltaXL; // floor + if (xL0 < 0) kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil + } else // (deltaXL < 0) + { + if (xL0 < 0) continue; + kMaxX = xL0 / (-deltaXL); // floor + if (lxPred < xL0) + kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil + } + if (deltaYL == 0) { + if ((yL0 < 0) || (lyPred < yL0)) continue; + } else if (deltaYL > 0) { + if (lyPred < yL0) continue; + + kMaxY = (lyPred - yL0) / deltaYL; // floor + if (yL0 < 0) kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil + } else // (deltaYL < 0) + { + if (yL0 < 0) continue; + + kMaxY = yL0 / (-deltaYL); // floor + if (lyPred < yL0) + kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil + } + int kMin = std::max({kMinX, kMinY, (int)0}); + int kMax = std::min({kMaxX, kMaxY, xMax - xMin}); + TPixel32 *dnPix = dnRow + xMin + kMin; + TPixel32 *dnEndPix = dnRow + xMin + kMax + 1; + int xL = xL0 + (kMin - 1) * deltaXL; // inizializza xL + int yL = yL0 + (kMin - 1) * deltaYL; // inizializza yL + for (; dnPix < dnEndPix; ++dnPix) { + xL += deltaXL; + yL += deltaYL; + int xI = xL >> PADN; // round + int yI = yL >> PADN; // round + + assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) && + (yI <= up->getLy() - 1)); + + if (colorMask == TRop::MChan) + dnPix->r = dnPix->g = dnPix->b = + byteFromUshort((upBasePix + (yI * upWrap + xI))->m); + else { + TPixel64 *pix = upBasePix + (yI * upWrap + xI); + dnPix->r = byteFromUshort(((colorMask & TRop::RChan) ? pix->r : 0)); + dnPix->g = byteFromUshort(((colorMask & TRop::GChan) ? pix->g : 0)); + dnPix->b = byteFromUshort(((colorMask & TRop::BChan) ? pix->b : 0)); + } + dnPix->m = 255; + } + } + dn->unlock(); + up->unlock(); } //============================================================================= //============================================================================= //============================================================================= -void doQuickResampleFilter( - const TRaster32P &dn, - const TRaster32P &up, - double sx, double sy, - double tx, double ty) -{ - // se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine - // di up e' un segmento (o un punto) - if ((sx == 0) || (sy == 0)) - return; +void doQuickResampleFilter(const TRaster32P &dn, const TRaster32P &up, + double sx, double sy, double tx, double ty) { + // se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine + // di up e' un segmento (o un punto) + if ((sx == 0) || (sy == 0)) return; - // contatore bit di shift - const int PADN = 16; + // contatore bit di shift + const int PADN = 16; - // maschera del filtro bilineare - const int MASKN = (1 << PADN) - 1; + // maschera del filtro bilineare + const int MASKN = (1 << PADN) - 1; - // max dimensioni di up gestibili (limite imposto dal numero di bit - // disponibili per la parte intera di xL, yL) - assert(std::max(up->getLx(), up->getLy()) < (1 << (8 * sizeof(int) - PADN - 1))); + // max dimensioni di up gestibili (limite imposto dal numero di bit + // disponibili per la parte intera di xL, yL) + assert(std::max(up->getLx(), up->getLy()) < + (1 << (8 * sizeof(int) - PADN - 1))); - TAffine aff(sx, 0, tx, 0, sy, ty); - TRectD boundingBoxD = TRectD(convert(dn->getSize())) * - (aff * TRectD(0, 0, up->getLx() - /*1*/ 2, up->getLy() - /*1*/ 2)); - - // clipping - if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) - return; - - // clipping y su dn - int yMin = std::max(tfloor(boundingBoxD.y0), 0); - - // clipping y su dn - int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); - - // clipping x su dn - int xMin = std::max(tfloor(boundingBoxD.x0), 0); - - // clipping x su dn - int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); - - // inversa di aff - TAffine invAff = inv(aff); - - // nello scorrere le scanline di boundingBoxD, il passaggio alla scanline - // successiva comporta l'incremento (0, deltaYD) delle coordinate dei - // pixels corrispondenti di up - - // nel disegnare la y-esima scanline di dn, il passaggio al pixel - // successivo comporta l'incremento (deltaXD, 0) delle coordinate del - // pixel corrispondente di up - - double deltaXD = invAff.a11; - double deltaYD = invAff.a22; - int deltaXL = tround(deltaXD * (1 << PADN)); // deltaXD "TLonghizzato" (round) - int deltaYL = tround(deltaYD * (1 << PADN)); // deltaYD "TLonghizzato" (round) - - // se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' - // un segmento (o un punto) - if ((deltaXL == 0) || (deltaYL == 0)) - return; - - // (1) equazione (kX, kY)-parametrica di boundingBoxD: - // (xMin, yMin) + kX*(1, 0) + kY*(0, 1), - // kX = 0, ..., (xMax - xMin), - // kY = 0, ..., (yMax - yMin) - - // (2) equazione (kX, kY)-parametrica dell'immagine mediante invAff di (1): - // invAff*(xMin, yMin) + kX*(deltaXD, 0) + kY*(0, deltaYD), - // kX = kMinX, ..., kMaxX - // con 0 <= kMinX <= kMaxX <= (xMax - xMin) - // - // kY = kMinY, ..., kMaxY - // con 0 <= kMinY <= kMaxY <= (yMax - yMin) - - // calcola kMinX, kMaxX, kMinY, kMaxY intersecando la (2) con i lati di up - - // il segmento [a, b] di up (con gli estremi eventualmente invertiti) e' - // la controimmagine mediante aff della porzione di scanline - // [ (xMin, yMin), (xMax, yMin) ] di dn - - // TPointD b = invAff*TPointD(xMax, yMin); - TPointD a = invAff * TPointD(xMin, yMin); - - // (xL0, yL0) sono le coordinate di a (inizializzate per il round) - // in versione "TLonghizzata" - // 0 <= xL0 + kX*deltaXL <= (up->getLx() - 2)*(1<getLy() - 2)*(1<getLx() - 1) - int lxPred = (up->getLx() - /*1*/ 2) * (1 << PADN); - - // TINT32 predecessore di (up->getLy() - 1) - int lyPred = (up->getLy() - /*1*/ 2) * (1 << PADN); - - // 0 <= xL0 + k*deltaXL <= (up->getLx() - 2)*(1< - // 0 <= xL0 + k*deltaXL <= lxPred - - // 0 <= yL0 + k*deltaYL <= (up->getLy() - 2)*(1< - // 0 <= yL0 + k*deltaYL <= lyPred - - // calcola kMinY, kMaxY intersecando la (2) con i lati - // (y = yMin) e (y = yMax) di up - if (deltaYL > 0) // (deltaYL != 0) - { - // [a, b] interno ad up contratto - assert(yL0 <= lyPred); - - kMaxY = (lyPred - yL0) / deltaYL; // floor - if (yL0 < 0) { - kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil - } - } else // (deltaYL < 0) - { - // [a, b] interno ad up contratto - assert(0 <= yL0); - - kMaxY = yL0 / (-deltaYL); // floor - if (lyPred < yL0) { - kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil - } - } - // calcola kMinY, kMaxY effettuando anche il clippind su dn - kMinY = std::max(kMinY, (int)0); - kMaxY = std::min(kMaxY, yMax - yMin); - - // calcola kMinX, kMaxX intersecando la (2) con i lati - // (x = xMin) e (x = xMax) di up - if (deltaXL > 0) // (deltaXL != 0) - { - // [a, b] interno ad up contratto - assert(xL0 <= lxPred); - - kMaxX = (lxPred - xL0) / deltaXL; // floor - if (xL0 < 0) { - kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil - } - } else // (deltaXL < 0) - { - // [a, b] interno ad up contratto - assert(0 <= xL0); - - kMaxX = xL0 / (-deltaXL); // floor - if (lxPred < xL0) { - kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil - } - } - // calcola kMinX, kMaxX effettuando anche il clippind su dn - kMinX = std::max(kMinX, (int)0); - kMaxX = std::min(kMaxX, xMax - xMin); - - int dnWrap = dn->getWrap(); - int upWrap = up->getWrap(); - - dn->lock(); - up->lock(); - TPixel32 *upBasePix = up->pixels(); - TPixel32 *dnRow = dn->pixels(yMin + kMinY); - - // (xL, yL) sono le coordinate (inizializzate per il round) - // in versione "TLonghizzata" - // del pixel corrente di up - int yL = yL0 + (kMinY - 1) * deltaYL; // inizializza yL - - // scorre le scanline di boundingBoxD - for (int kY = kMinY; kY <= kMaxY; kY++, dnRow += dnWrap) { - int xL = xL0 + (kMinX - 1) * deltaXL; // inizializza xL - yL += deltaYL; - // il punto di up TPointD(xL/(1<> PADN; // troncato - - // filtro bilineare 4 pixels: calcolo degli y-pesi - int yWeight1 = (yL & MASKN); - int yWeight0 = (1 << PADN) - yWeight1; - - TPixel32 *dnPix = dnRow + xMin + kMinX; - TPixel32 *dnEndPix = dnRow + xMin + kMaxX + 1; - - // scorre i pixel sulla (yMin + kY)-esima scanline di dn - for (; dnPix < dnEndPix; ++dnPix) { - xL += deltaXL; - // il punto di up TPointD(xL/(1<> PADN; // troncato - - assert((0 <= xI) && (xI <= up->getLx() - 1) && - (0 <= yI) && (yI <= up->getLy() - 1)); - - // (xI, yI) - TPixel32 *upPix00 = upBasePix + (yI * upWrap + xI); - - // (xI + 1, yI) - TPixel32 *upPix10 = upPix00 + 1; - - // (xI, yI + 1) - TPixel32 *upPix01 = upPix00 + upWrap; - - // (xI + 1, yI + 1) - TPixel32 *upPix11 = upPix00 + upWrap + 1; - - // filtro bilineare 4 pixels: calcolo degli x-pesi - int xWeight1 = (xL & MASKN); - int xWeight0 = (1 << PADN) - xWeight1; - - // filtro bilineare 4 pixels: media pesata sui singoli canali - int rColDownTmp = - (xWeight0 * (upPix00->r) + xWeight1 * ((upPix10)->r)) >> PADN; - - int gColDownTmp = - (xWeight0 * (upPix00->g) + xWeight1 * ((upPix10)->g)) >> PADN; - - int bColDownTmp = - (xWeight0 * (upPix00->b) + xWeight1 * ((upPix10)->b)) >> PADN; - - int mColDownTmp = - (xWeight0 * (upPix00->m) + xWeight1 * ((upPix10)->m)) >> PADN; - - int rColUpTmp = - (xWeight0 * ((upPix01)->r) + xWeight1 * ((upPix11)->r)) >> PADN; - - int gColUpTmp = - (xWeight0 * ((upPix01)->g) + xWeight1 * ((upPix11)->g)) >> PADN; - - int bColUpTmp = - (xWeight0 * ((upPix01)->b) + xWeight1 * ((upPix11)->b)) >> PADN; - - int mColUpTmp = - (xWeight0 * ((upPix01)->m) + xWeight1 * ((upPix11)->m)) >> PADN; - - dnPix->r = (unsigned char)((yWeight0 * rColDownTmp + yWeight1 * rColUpTmp) >> PADN); - dnPix->g = (unsigned char)((yWeight0 * gColDownTmp + yWeight1 * gColUpTmp) >> PADN); - dnPix->b = (unsigned char)((yWeight0 * bColDownTmp + yWeight1 * bColUpTmp) >> PADN); - dnPix->m = (unsigned char)((yWeight0 * mColDownTmp + yWeight1 * mColUpTmp) >> PADN); - } - } - dn->unlock(); - up->unlock(); + TAffine aff(sx, 0, tx, 0, sy, ty); + TRectD boundingBoxD = + TRectD(convert(dn->getSize())) * + (aff * TRectD(0, 0, up->getLx() - /*1*/ 2, up->getLy() - /*1*/ 2)); + + // clipping + if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) + return; + + // clipping y su dn + int yMin = std::max(tfloor(boundingBoxD.y0), 0); + + // clipping y su dn + int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); + + // clipping x su dn + int xMin = std::max(tfloor(boundingBoxD.x0), 0); + + // clipping x su dn + int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); + + // inversa di aff + TAffine invAff = inv(aff); + + // nello scorrere le scanline di boundingBoxD, il passaggio alla scanline + // successiva comporta l'incremento (0, deltaYD) delle coordinate dei + // pixels corrispondenti di up + + // nel disegnare la y-esima scanline di dn, il passaggio al pixel + // successivo comporta l'incremento (deltaXD, 0) delle coordinate del + // pixel corrispondente di up + + double deltaXD = invAff.a11; + double deltaYD = invAff.a22; + int deltaXL = + tround(deltaXD * (1 << PADN)); // deltaXD "TLonghizzato" (round) + int deltaYL = + tround(deltaYD * (1 << PADN)); // deltaYD "TLonghizzato" (round) + + // se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' + // un segmento (o un punto) + if ((deltaXL == 0) || (deltaYL == 0)) return; + + // (1) equazione (kX, kY)-parametrica di boundingBoxD: + // (xMin, yMin) + kX*(1, 0) + kY*(0, 1), + // kX = 0, ..., (xMax - xMin), + // kY = 0, ..., (yMax - yMin) + + // (2) equazione (kX, kY)-parametrica dell'immagine mediante invAff di (1): + // invAff*(xMin, yMin) + kX*(deltaXD, 0) + kY*(0, deltaYD), + // kX = kMinX, ..., kMaxX + // con 0 <= kMinX <= kMaxX <= (xMax - xMin) + // + // kY = kMinY, ..., kMaxY + // con 0 <= kMinY <= kMaxY <= (yMax - yMin) + + // calcola kMinX, kMaxX, kMinY, kMaxY intersecando la (2) con i lati di up + + // il segmento [a, b] di up (con gli estremi eventualmente invertiti) e' + // la controimmagine mediante aff della porzione di scanline + // [ (xMin, yMin), (xMax, yMin) ] di dn + + // TPointD b = invAff*TPointD(xMax, yMin); + TPointD a = invAff * TPointD(xMin, yMin); + + // (xL0, yL0) sono le coordinate di a (inizializzate per il round) + // in versione "TLonghizzata" + // 0 <= xL0 + kX*deltaXL <= (up->getLx() - 2)*(1<getLy() - 2)*(1<getLx() - 1) + int lxPred = (up->getLx() - /*1*/ 2) * (1 << PADN); + + // TINT32 predecessore di (up->getLy() - 1) + int lyPred = (up->getLy() - /*1*/ 2) * (1 << PADN); + + // 0 <= xL0 + k*deltaXL <= (up->getLx() - 2)*(1< + // 0 <= xL0 + k*deltaXL <= lxPred + + // 0 <= yL0 + k*deltaYL <= (up->getLy() - 2)*(1< + // 0 <= yL0 + k*deltaYL <= lyPred + + // calcola kMinY, kMaxY intersecando la (2) con i lati + // (y = yMin) e (y = yMax) di up + if (deltaYL > 0) // (deltaYL != 0) + { + // [a, b] interno ad up contratto + assert(yL0 <= lyPred); + + kMaxY = (lyPred - yL0) / deltaYL; // floor + if (yL0 < 0) { + kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil + } + } else // (deltaYL < 0) + { + // [a, b] interno ad up contratto + assert(0 <= yL0); + + kMaxY = yL0 / (-deltaYL); // floor + if (lyPred < yL0) { + kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil + } + } + // calcola kMinY, kMaxY effettuando anche il clippind su dn + kMinY = std::max(kMinY, (int)0); + kMaxY = std::min(kMaxY, yMax - yMin); + + // calcola kMinX, kMaxX intersecando la (2) con i lati + // (x = xMin) e (x = xMax) di up + if (deltaXL > 0) // (deltaXL != 0) + { + // [a, b] interno ad up contratto + assert(xL0 <= lxPred); + + kMaxX = (lxPred - xL0) / deltaXL; // floor + if (xL0 < 0) { + kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil + } + } else // (deltaXL < 0) + { + // [a, b] interno ad up contratto + assert(0 <= xL0); + + kMaxX = xL0 / (-deltaXL); // floor + if (lxPred < xL0) { + kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil + } + } + // calcola kMinX, kMaxX effettuando anche il clippind su dn + kMinX = std::max(kMinX, (int)0); + kMaxX = std::min(kMaxX, xMax - xMin); + + int dnWrap = dn->getWrap(); + int upWrap = up->getWrap(); + + dn->lock(); + up->lock(); + TPixel32 *upBasePix = up->pixels(); + TPixel32 *dnRow = dn->pixels(yMin + kMinY); + + // (xL, yL) sono le coordinate (inizializzate per il round) + // in versione "TLonghizzata" + // del pixel corrente di up + int yL = yL0 + (kMinY - 1) * deltaYL; // inizializza yL + + // scorre le scanline di boundingBoxD + for (int kY = kMinY; kY <= kMaxY; kY++, dnRow += dnWrap) { + int xL = xL0 + (kMinX - 1) * deltaXL; // inizializza xL + yL += deltaYL; + // il punto di up TPointD(xL/(1<> PADN; // troncato + + // filtro bilineare 4 pixels: calcolo degli y-pesi + int yWeight1 = (yL & MASKN); + int yWeight0 = (1 << PADN) - yWeight1; + + TPixel32 *dnPix = dnRow + xMin + kMinX; + TPixel32 *dnEndPix = dnRow + xMin + kMaxX + 1; + + // scorre i pixel sulla (yMin + kY)-esima scanline di dn + for (; dnPix < dnEndPix; ++dnPix) { + xL += deltaXL; + // il punto di up TPointD(xL/(1<> PADN; // troncato + + assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) && + (yI <= up->getLy() - 1)); + + // (xI, yI) + TPixel32 *upPix00 = upBasePix + (yI * upWrap + xI); + + // (xI + 1, yI) + TPixel32 *upPix10 = upPix00 + 1; + + // (xI, yI + 1) + TPixel32 *upPix01 = upPix00 + upWrap; + + // (xI + 1, yI + 1) + TPixel32 *upPix11 = upPix00 + upWrap + 1; + + // filtro bilineare 4 pixels: calcolo degli x-pesi + int xWeight1 = (xL & MASKN); + int xWeight0 = (1 << PADN) - xWeight1; + + // filtro bilineare 4 pixels: media pesata sui singoli canali + int rColDownTmp = + (xWeight0 * (upPix00->r) + xWeight1 * ((upPix10)->r)) >> PADN; + + int gColDownTmp = + (xWeight0 * (upPix00->g) + xWeight1 * ((upPix10)->g)) >> PADN; + + int bColDownTmp = + (xWeight0 * (upPix00->b) + xWeight1 * ((upPix10)->b)) >> PADN; + + int mColDownTmp = + (xWeight0 * (upPix00->m) + xWeight1 * ((upPix10)->m)) >> PADN; + + int rColUpTmp = + (xWeight0 * ((upPix01)->r) + xWeight1 * ((upPix11)->r)) >> PADN; + + int gColUpTmp = + (xWeight0 * ((upPix01)->g) + xWeight1 * ((upPix11)->g)) >> PADN; + + int bColUpTmp = + (xWeight0 * ((upPix01)->b) + xWeight1 * ((upPix11)->b)) >> PADN; + + int mColUpTmp = + (xWeight0 * ((upPix01)->m) + xWeight1 * ((upPix11)->m)) >> PADN; + + dnPix->r = + (unsigned char)((yWeight0 * rColDownTmp + yWeight1 * rColUpTmp) >> + PADN); + dnPix->g = + (unsigned char)((yWeight0 * gColDownTmp + yWeight1 * gColUpTmp) >> + PADN); + dnPix->b = + (unsigned char)((yWeight0 * bColDownTmp + yWeight1 * bColUpTmp) >> + PADN); + dnPix->m = + (unsigned char)((yWeight0 * mColDownTmp + yWeight1 * mColUpTmp) >> + PADN); + } + } + dn->unlock(); + up->unlock(); } //------------------------------------------------------------------------------------------ -void doQuickResampleFilter( - const TRaster32P &dn, - const TRasterGR8P &up, - double sx, double sy, - double tx, double ty) -{ - // se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine - // di up e' un segmento (o un punto) - if ((sx == 0) || (sy == 0)) - return; +void doQuickResampleFilter(const TRaster32P &dn, const TRasterGR8P &up, + double sx, double sy, double tx, double ty) { + // se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine + // di up e' un segmento (o un punto) + if ((sx == 0) || (sy == 0)) return; - // contatore bit di shift - const int PADN = 16; + // contatore bit di shift + const int PADN = 16; - // maschera del filtro bilineare - const int MASKN = (1 << PADN) - 1; + // maschera del filtro bilineare + const int MASKN = (1 << PADN) - 1; - // max dimensioni di up gestibili (limite imposto dal numero di bit - // disponibili per la parte intera di xL, yL) - assert(std::max(up->getLx(), up->getLy()) < (1 << (8 * sizeof(int) - PADN - 1))); + // max dimensioni di up gestibili (limite imposto dal numero di bit + // disponibili per la parte intera di xL, yL) + assert(std::max(up->getLx(), up->getLy()) < + (1 << (8 * sizeof(int) - PADN - 1))); - TAffine aff(sx, 0, tx, 0, sy, ty); - TRectD boundingBoxD = TRectD(convert(dn->getSize())) * - (aff * TRectD(0, 0, up->getLx() - /*1*/ 2, up->getLy() - /*1*/ 2)); - - // clipping - if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) - return; - - // clipping y su dn - int yMin = std::max(tfloor(boundingBoxD.y0), 0); - - // clipping y su dn - int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); - - // clipping x su dn - int xMin = std::max(tfloor(boundingBoxD.x0), 0); - - // clipping x su dn - int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); - - // inversa di aff - TAffine invAff = inv(aff); - - // nello scorrere le scanline di boundingBoxD, il passaggio alla scanline - // successiva comporta l'incremento (0, deltaYD) delle coordinate dei - // pixels corrispondenti di up - - // nel disegnare la y-esima scanline di dn, il passaggio al pixel - // successivo comporta l'incremento (deltaXD, 0) delle coordinate del - // pixel corrispondente di up - - double deltaXD = invAff.a11; - double deltaYD = invAff.a22; - int deltaXL = tround(deltaXD * (1 << PADN)); // deltaXD "TLonghizzato" (round) - int deltaYL = tround(deltaYD * (1 << PADN)); // deltaYD "TLonghizzato" (round) - - // se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' - // un segmento (o un punto) - if ((deltaXL == 0) || (deltaYL == 0)) - return; - - // (1) equazione (kX, kY)-parametrica di boundingBoxD: - // (xMin, yMin) + kX*(1, 0) + kY*(0, 1), - // kX = 0, ..., (xMax - xMin), - // kY = 0, ..., (yMax - yMin) - - // (2) equazione (kX, kY)-parametrica dell'immagine mediante invAff di (1): - // invAff*(xMin, yMin) + kX*(deltaXD, 0) + kY*(0, deltaYD), - // kX = kMinX, ..., kMaxX - // con 0 <= kMinX <= kMaxX <= (xMax - xMin) - // - // kY = kMinY, ..., kMaxY - // con 0 <= kMinY <= kMaxY <= (yMax - yMin) - - // calcola kMinX, kMaxX, kMinY, kMaxY intersecando la (2) con i lati di up - - // il segmento [a, b] di up (con gli estremi eventualmente invertiti) e' - // la controimmagine mediante aff della porzione di scanline - // [ (xMin, yMin), (xMax, yMin) ] di dn - - // TPointD b = invAff*TPointD(xMax, yMin); - TPointD a = invAff * TPointD(xMin, yMin); - - // (xL0, yL0) sono le coordinate di a (inizializzate per il round) - // in versione "TLonghizzata" - // 0 <= xL0 + kX*deltaXL <= (up->getLx() - 2)*(1<getLy() - 2)*(1<getLx() - 1) - int lxPred = (up->getLx() - /*1*/ 2) * (1 << PADN); - - // TINT32 predecessore di (up->getLy() - 1) - int lyPred = (up->getLy() - /*1*/ 2) * (1 << PADN); - - // 0 <= xL0 + k*deltaXL <= (up->getLx() - 2)*(1< - // 0 <= xL0 + k*deltaXL <= lxPred - - // 0 <= yL0 + k*deltaYL <= (up->getLy() - 2)*(1< - // 0 <= yL0 + k*deltaYL <= lyPred - - // calcola kMinY, kMaxY intersecando la (2) con i lati - // (y = yMin) e (y = yMax) di up - if (deltaYL > 0) // (deltaYL != 0) - { - // [a, b] interno ad up contratto - assert(yL0 <= lyPred); - - kMaxY = (lyPred - yL0) / deltaYL; // floor - if (yL0 < 0) { - kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil - } - } else // (deltaYL < 0) - { - // [a, b] interno ad up contratto - assert(0 <= yL0); - - kMaxY = yL0 / (-deltaYL); // floor - if (lyPred < yL0) { - kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil - } - } - // calcola kMinY, kMaxY effettuando anche il clippind su dn - kMinY = std::max(kMinY, (int)0); - kMaxY = std::min(kMaxY, yMax - yMin); - - // calcola kMinX, kMaxX intersecando la (2) con i lati - // (x = xMin) e (x = xMax) di up - if (deltaXL > 0) // (deltaXL != 0) - { - // [a, b] interno ad up contratto - assert(xL0 <= lxPred); - - kMaxX = (lxPred - xL0) / deltaXL; // floor - if (xL0 < 0) { - kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil - } - } else // (deltaXL < 0) - { - // [a, b] interno ad up contratto - assert(0 <= xL0); - - kMaxX = xL0 / (-deltaXL); // floor - if (lxPred < xL0) { - kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil - } - } - // calcola kMinX, kMaxX effettuando anche il clippind su dn - kMinX = std::max(kMinX, (int)0); - kMaxX = std::min(kMaxX, xMax - xMin); - - int dnWrap = dn->getWrap(); - int upWrap = up->getWrap(); - - dn->lock(); - up->lock(); - TPixelGR8 *upBasePix = up->pixels(); - TPixel32 *dnRow = dn->pixels(yMin + kMinY); - - // (xL, yL) sono le coordinate (inizializzate per il round) - // in versione "TLonghizzata" - // del pixel corrente di up - int yL = yL0 + (kMinY - 1) * deltaYL; // inizializza yL - - // scorre le scanline di boundingBoxD - for (int kY = kMinY; kY <= kMaxY; kY++, dnRow += dnWrap) { - int xL = xL0 + (kMinX - 1) * deltaXL; // inizializza xL - yL += deltaYL; - // il punto di up TPointD(xL/(1<> PADN; // troncato - - // filtro bilineare 4 pixels: calcolo degli y-pesi - int yWeight1 = (yL & MASKN); - int yWeight0 = (1 << PADN) - yWeight1; - - TPixel32 *dnPix = dnRow + xMin + kMinX; - TPixel32 *dnEndPix = dnRow + xMin + kMaxX + 1; - - // scorre i pixel sulla (yMin + kY)-esima scanline di dn - for (; dnPix < dnEndPix; ++dnPix) { - xL += deltaXL; - // il punto di up TPointD(xL/(1<> PADN; // troncato - - assert((0 <= xI) && (xI <= up->getLx() - 1) && - (0 <= yI) && (yI <= up->getLy() - 1)); - - // (xI, yI) - TPixelGR8 *upPix00 = upBasePix + (yI * upWrap + xI); - - // (xI + 1, yI) - TPixelGR8 *upPix10 = upPix00 + 1; - - // (xI, yI + 1) - TPixelGR8 *upPix01 = upPix00 + upWrap; - - // (xI + 1, yI + 1) - TPixelGR8 *upPix11 = upPix00 + upWrap + 1; - - // filtro bilineare 4 pixels: calcolo degli x-pesi - int xWeight1 = (xL & MASKN); - int xWeight0 = (1 << PADN) - xWeight1; - - // filtro bilineare 4 pixels: media pesata sui singoli canali - int colDownTmp = - (xWeight0 * (upPix00->value) + xWeight1 * (upPix10->value)) >> PADN; - - int colUpTmp = - (xWeight0 * ((upPix01)->value) + xWeight1 * (upPix11->value)) >> PADN; - - dnPix->m = 255; - dnPix->r = dnPix->g = dnPix->b = (unsigned char)((yWeight0 * colDownTmp + yWeight1 * colUpTmp) >> PADN); - } - } - dn->unlock(); - up->unlock(); + TAffine aff(sx, 0, tx, 0, sy, ty); + TRectD boundingBoxD = + TRectD(convert(dn->getSize())) * + (aff * TRectD(0, 0, up->getLx() - /*1*/ 2, up->getLy() - /*1*/ 2)); + + // clipping + if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) + return; + + // clipping y su dn + int yMin = std::max(tfloor(boundingBoxD.y0), 0); + + // clipping y su dn + int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); + + // clipping x su dn + int xMin = std::max(tfloor(boundingBoxD.x0), 0); + + // clipping x su dn + int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); + + // inversa di aff + TAffine invAff = inv(aff); + + // nello scorrere le scanline di boundingBoxD, il passaggio alla scanline + // successiva comporta l'incremento (0, deltaYD) delle coordinate dei + // pixels corrispondenti di up + + // nel disegnare la y-esima scanline di dn, il passaggio al pixel + // successivo comporta l'incremento (deltaXD, 0) delle coordinate del + // pixel corrispondente di up + + double deltaXD = invAff.a11; + double deltaYD = invAff.a22; + int deltaXL = + tround(deltaXD * (1 << PADN)); // deltaXD "TLonghizzato" (round) + int deltaYL = + tround(deltaYD * (1 << PADN)); // deltaYD "TLonghizzato" (round) + + // se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' + // un segmento (o un punto) + if ((deltaXL == 0) || (deltaYL == 0)) return; + + // (1) equazione (kX, kY)-parametrica di boundingBoxD: + // (xMin, yMin) + kX*(1, 0) + kY*(0, 1), + // kX = 0, ..., (xMax - xMin), + // kY = 0, ..., (yMax - yMin) + + // (2) equazione (kX, kY)-parametrica dell'immagine mediante invAff di (1): + // invAff*(xMin, yMin) + kX*(deltaXD, 0) + kY*(0, deltaYD), + // kX = kMinX, ..., kMaxX + // con 0 <= kMinX <= kMaxX <= (xMax - xMin) + // + // kY = kMinY, ..., kMaxY + // con 0 <= kMinY <= kMaxY <= (yMax - yMin) + + // calcola kMinX, kMaxX, kMinY, kMaxY intersecando la (2) con i lati di up + + // il segmento [a, b] di up (con gli estremi eventualmente invertiti) e' + // la controimmagine mediante aff della porzione di scanline + // [ (xMin, yMin), (xMax, yMin) ] di dn + + // TPointD b = invAff*TPointD(xMax, yMin); + TPointD a = invAff * TPointD(xMin, yMin); + + // (xL0, yL0) sono le coordinate di a (inizializzate per il round) + // in versione "TLonghizzata" + // 0 <= xL0 + kX*deltaXL <= (up->getLx() - 2)*(1<getLy() - 2)*(1<getLx() - 1) + int lxPred = (up->getLx() - /*1*/ 2) * (1 << PADN); + + // TINT32 predecessore di (up->getLy() - 1) + int lyPred = (up->getLy() - /*1*/ 2) * (1 << PADN); + + // 0 <= xL0 + k*deltaXL <= (up->getLx() - 2)*(1< + // 0 <= xL0 + k*deltaXL <= lxPred + + // 0 <= yL0 + k*deltaYL <= (up->getLy() - 2)*(1< + // 0 <= yL0 + k*deltaYL <= lyPred + + // calcola kMinY, kMaxY intersecando la (2) con i lati + // (y = yMin) e (y = yMax) di up + if (deltaYL > 0) // (deltaYL != 0) + { + // [a, b] interno ad up contratto + assert(yL0 <= lyPred); + + kMaxY = (lyPred - yL0) / deltaYL; // floor + if (yL0 < 0) { + kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil + } + } else // (deltaYL < 0) + { + // [a, b] interno ad up contratto + assert(0 <= yL0); + + kMaxY = yL0 / (-deltaYL); // floor + if (lyPred < yL0) { + kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil + } + } + // calcola kMinY, kMaxY effettuando anche il clippind su dn + kMinY = std::max(kMinY, (int)0); + kMaxY = std::min(kMaxY, yMax - yMin); + + // calcola kMinX, kMaxX intersecando la (2) con i lati + // (x = xMin) e (x = xMax) di up + if (deltaXL > 0) // (deltaXL != 0) + { + // [a, b] interno ad up contratto + assert(xL0 <= lxPred); + + kMaxX = (lxPred - xL0) / deltaXL; // floor + if (xL0 < 0) { + kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil + } + } else // (deltaXL < 0) + { + // [a, b] interno ad up contratto + assert(0 <= xL0); + + kMaxX = xL0 / (-deltaXL); // floor + if (lxPred < xL0) { + kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil + } + } + // calcola kMinX, kMaxX effettuando anche il clippind su dn + kMinX = std::max(kMinX, (int)0); + kMaxX = std::min(kMaxX, xMax - xMin); + + int dnWrap = dn->getWrap(); + int upWrap = up->getWrap(); + + dn->lock(); + up->lock(); + TPixelGR8 *upBasePix = up->pixels(); + TPixel32 *dnRow = dn->pixels(yMin + kMinY); + + // (xL, yL) sono le coordinate (inizializzate per il round) + // in versione "TLonghizzata" + // del pixel corrente di up + int yL = yL0 + (kMinY - 1) * deltaYL; // inizializza yL + + // scorre le scanline di boundingBoxD + for (int kY = kMinY; kY <= kMaxY; kY++, dnRow += dnWrap) { + int xL = xL0 + (kMinX - 1) * deltaXL; // inizializza xL + yL += deltaYL; + // il punto di up TPointD(xL/(1<> PADN; // troncato + + // filtro bilineare 4 pixels: calcolo degli y-pesi + int yWeight1 = (yL & MASKN); + int yWeight0 = (1 << PADN) - yWeight1; + + TPixel32 *dnPix = dnRow + xMin + kMinX; + TPixel32 *dnEndPix = dnRow + xMin + kMaxX + 1; + + // scorre i pixel sulla (yMin + kY)-esima scanline di dn + for (; dnPix < dnEndPix; ++dnPix) { + xL += deltaXL; + // il punto di up TPointD(xL/(1<> PADN; // troncato + + assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) && + (yI <= up->getLy() - 1)); + + // (xI, yI) + TPixelGR8 *upPix00 = upBasePix + (yI * upWrap + xI); + + // (xI + 1, yI) + TPixelGR8 *upPix10 = upPix00 + 1; + + // (xI, yI + 1) + TPixelGR8 *upPix01 = upPix00 + upWrap; + + // (xI + 1, yI + 1) + TPixelGR8 *upPix11 = upPix00 + upWrap + 1; + + // filtro bilineare 4 pixels: calcolo degli x-pesi + int xWeight1 = (xL & MASKN); + int xWeight0 = (1 << PADN) - xWeight1; + + // filtro bilineare 4 pixels: media pesata sui singoli canali + int colDownTmp = + (xWeight0 * (upPix00->value) + xWeight1 * (upPix10->value)) >> PADN; + + int colUpTmp = + (xWeight0 * ((upPix01)->value) + xWeight1 * (upPix11->value)) >> PADN; + + dnPix->m = 255; + dnPix->r = dnPix->g = dnPix->b = + (unsigned char)((yWeight0 * colDownTmp + yWeight1 * colUpTmp) >> + PADN); + } + } + dn->unlock(); + up->unlock(); } //============================================================================= //============================================================================= //============================================================================= template -void doQuickResampleNoFilter( - const TRasterPT &dn, - const TRasterPT &up, - double sx, double sy, - double tx, double ty) -{ - // se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine - // di up e' un segmento (o un punto) - if ((sx == 0) || (sy == 0)) - return; - - // contatore bit di shift - const int PADN = 16; - - // max dimensioni di up gestibili (limite imposto dal numero di bit - // disponibili per la parte intera di xL, yL) - assert(std::max(up->getLx(), up->getLy()) < (1 << (8 * sizeof(int) - PADN - 1))); - - TAffine aff(sx, 0, tx, 0, sy, ty); - TRectD boundingBoxD = TRectD(convert(dn->getBounds())) * - (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5)); - // clipping - if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) - return; - - // clipping y su dn - int yMin = std::max(tfloor(boundingBoxD.y0), 0); - - // clipping y su dn - int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); - - // clipping x su dn - int xMin = std::max(tfloor(boundingBoxD.x0), 0); - - // clipping x su dn - int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); - - TAffine invAff = inv(aff); // inversa di aff - - // nello scorrere le scanline di boundingBoxD, il passaggio alla scanline - // successiva comporta l'incremento (0, deltaYD) delle coordinate dei - // pixels corrispondenti di up - - // nel disegnare la y-esima scanline di dn, il passaggio al pixel - // successivo comporta l'incremento (deltaXD, 0) delle coordinate del - // pixel corrispondente di up - - double deltaXD = invAff.a11; - double deltaYD = invAff.a22; - int deltaXL = tround(deltaXD * (1 << PADN)); // deltaXD "TLonghizzato" (round) - int deltaYL = tround(deltaYD * (1 << PADN)); // deltaYD "TLonghizzato" (round) - - // se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un - // segmento (o un punto) - if ((deltaXL == 0) || (deltaYL == 0)) - return; - - // (1) equazione (kX, kY)-parametrica di boundingBoxD: - // (xMin, yMin) + kX*(1, 0) + kY*(0, 1), - // kX = 0, ..., (xMax - xMin), - // kY = 0, ..., (yMax - yMin) - - // (2) equazione (kX, kY)-parametrica dell'immagine mediante invAff di (1): - // invAff*(xMin, yMin) + kX*(deltaXD, 0) + kY*(0, deltaYD), - // kX = kMinX, ..., kMaxX - // con 0 <= kMinX <= kMaxX <= (xMax - xMin) - // kY = kMinY, ..., kMaxY - // con 0 <= kMinY <= kMaxY <= (yMax - yMin) - - // calcola kMinX, kMaxX, kMinY, kMaxY intersecando la (2) con i lati di up - - // il segmento [a, b] di up e' la controimmagine mediante aff della - // porzione di scanline [ (xMin, yMin), (xMax, yMin) ] di dn - - // TPointD b = invAff*TPointD(xMax, yMin); - TPointD a = invAff * TPointD(xMin, yMin); - - // (xL0, yL0) sono le coordinate di a (inizializzate per il round) - // in versione "TLonghizzata" - // 0 <= xL0 + kX*deltaXL < up->getLx()*(1<getLy()*(1<getLx() * (1 << PADN) - 1; // TINT32 predecessore di up->getLx() - int lyPred = up->getLy() * (1 << PADN) - 1; // TINT32 predecessore di up->getLy() - - // 0 <= xL0 + k*deltaXL < up->getLx()*(1< - // 0 <= xL0 + k*deltaXL <= lxPred - - // 0 <= yL0 + k*deltaYL < up->getLy()*(1< - // 0 <= yL0 + k*deltaYL <= lyPred - - // calcola kMinY, kMaxY intersecando la (2) con i lati - // (y = yMin) e (y = yMax) di up - if (deltaYL > 0) // (deltaYL != 0) - { - assert(yL0 <= lyPred); // [a, b] interno ad up+(bordo destro/basso) - kMaxY = (lyPred - yL0) / deltaYL; // floor - if (yL0 < 0) { - kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil - } - } else // (deltaYL < 0) - { - // [a, b] interno ad up+(bordo destro/basso) - assert(0 <= yL0); - - kMaxY = yL0 / (-deltaYL); // floor - if (lyPred < yL0) { - kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil - } - } - // calcola kMinY, kMaxY effettuando anche il clippind su dn - kMinY = std::max(kMinY, (int)0); - kMaxY = std::min(kMaxY, yMax - yMin); - - // calcola kMinX, kMaxX intersecando la (2) con i lati - // (x = xMin) e (x = xMax) di up - if (deltaXL > 0) // (deltaXL != 0) - { - // [a, b] interno ad up+(bordo destro/basso) - assert(xL0 <= lxPred); - - kMaxX = (lxPred - xL0) / deltaXL; // floor - if (xL0 < 0) { - kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil - } - } else // (deltaXL < 0) - { - // [a, b] interno ad up+(bordo destro/basso) - assert(0 <= xL0); - - kMaxX = xL0 / (-deltaXL); // floor - if (lxPred < xL0) { - kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil - } - } - // calcola kMinX, kMaxX effettuando anche il clippind su dn - kMinX = std::max(kMinX, (int)0); - kMaxX = std::min(kMaxX, xMax - xMin); - - int dnWrap = dn->getWrap(); - int upWrap = up->getWrap(); - dn->lock(); - up->lock(); - - PIX *upBasePix = up->pixels(); - PIX *dnRow = dn->pixels(yMin + kMinY); - - // (xL, yL) sono le coordinate (inizializzate per il round) - // in versione "TLonghizzata" del pixel corrente di up - int yL = yL0 + (kMinY - 1) * deltaYL; // inizializza yL - - // scorre le scanline di boundingBoxD - for (int kY = kMinY; kY <= kMaxY; kY++, dnRow += dnWrap) { - int xL = xL0 + (kMinX - 1) * deltaXL; // inizializza xL - yL += deltaYL; - // il punto di up TPointD(xL/(1<> PADN; // round - - PIX *dnPix = dnRow + xMin + kMinX; - PIX *dnEndPix = dnRow + xMin + kMaxX + 1; - - // scorre i pixel sulla (yMin + kY)-esima scanline di dn - for (; dnPix < dnEndPix; ++dnPix) { - xL += deltaXL; - // il punto di up TPointD(xL/(1<> PADN; // round - - assert((0 <= xI) && (xI <= up->getLx() - 1) && - (0 <= yI) && (yI <= up->getLy() - 1)); - - *dnPix = *(upBasePix + (yI * upWrap + xI)); - } - } - - dn->unlock(); - up->unlock(); +void doQuickResampleNoFilter(const TRasterPT &dn, const TRasterPT &up, + double sx, double sy, double tx, double ty) { + // se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine + // di up e' un segmento (o un punto) + if ((sx == 0) || (sy == 0)) return; + + // contatore bit di shift + const int PADN = 16; + + // max dimensioni di up gestibili (limite imposto dal numero di bit + // disponibili per la parte intera di xL, yL) + assert(std::max(up->getLx(), up->getLy()) < + (1 << (8 * sizeof(int) - PADN - 1))); + + TAffine aff(sx, 0, tx, 0, sy, ty); + TRectD boundingBoxD = + TRectD(convert(dn->getBounds())) * + (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5)); + // clipping + if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) + return; + + // clipping y su dn + int yMin = std::max(tfloor(boundingBoxD.y0), 0); + + // clipping y su dn + int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); + + // clipping x su dn + int xMin = std::max(tfloor(boundingBoxD.x0), 0); + + // clipping x su dn + int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); + + TAffine invAff = inv(aff); // inversa di aff + + // nello scorrere le scanline di boundingBoxD, il passaggio alla scanline + // successiva comporta l'incremento (0, deltaYD) delle coordinate dei + // pixels corrispondenti di up + + // nel disegnare la y-esima scanline di dn, il passaggio al pixel + // successivo comporta l'incremento (deltaXD, 0) delle coordinate del + // pixel corrispondente di up + + double deltaXD = invAff.a11; + double deltaYD = invAff.a22; + int deltaXL = + tround(deltaXD * (1 << PADN)); // deltaXD "TLonghizzato" (round) + int deltaYL = + tround(deltaYD * (1 << PADN)); // deltaYD "TLonghizzato" (round) + + // se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un + // segmento (o un punto) + if ((deltaXL == 0) || (deltaYL == 0)) return; + + // (1) equazione (kX, kY)-parametrica di boundingBoxD: + // (xMin, yMin) + kX*(1, 0) + kY*(0, 1), + // kX = 0, ..., (xMax - xMin), + // kY = 0, ..., (yMax - yMin) + + // (2) equazione (kX, kY)-parametrica dell'immagine mediante invAff di (1): + // invAff*(xMin, yMin) + kX*(deltaXD, 0) + kY*(0, deltaYD), + // kX = kMinX, ..., kMaxX + // con 0 <= kMinX <= kMaxX <= (xMax - xMin) + // kY = kMinY, ..., kMaxY + // con 0 <= kMinY <= kMaxY <= (yMax - yMin) + + // calcola kMinX, kMaxX, kMinY, kMaxY intersecando la (2) con i lati di up + + // il segmento [a, b] di up e' la controimmagine mediante aff della + // porzione di scanline [ (xMin, yMin), (xMax, yMin) ] di dn + + // TPointD b = invAff*TPointD(xMax, yMin); + TPointD a = invAff * TPointD(xMin, yMin); + + // (xL0, yL0) sono le coordinate di a (inizializzate per il round) + // in versione "TLonghizzata" + // 0 <= xL0 + kX*deltaXL < up->getLx()*(1<getLy()*(1<getLx() * (1 << PADN) - 1; // TINT32 predecessore di up->getLx() + int lyPred = + up->getLy() * (1 << PADN) - 1; // TINT32 predecessore di up->getLy() + + // 0 <= xL0 + k*deltaXL < up->getLx()*(1< + // 0 <= xL0 + k*deltaXL <= lxPred + + // 0 <= yL0 + k*deltaYL < up->getLy()*(1< + // 0 <= yL0 + k*deltaYL <= lyPred + + // calcola kMinY, kMaxY intersecando la (2) con i lati + // (y = yMin) e (y = yMax) di up + if (deltaYL > 0) // (deltaYL != 0) + { + assert(yL0 <= lyPred); // [a, b] interno ad up+(bordo destro/basso) + kMaxY = (lyPred - yL0) / deltaYL; // floor + if (yL0 < 0) { + kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil + } + } else // (deltaYL < 0) + { + // [a, b] interno ad up+(bordo destro/basso) + assert(0 <= yL0); + + kMaxY = yL0 / (-deltaYL); // floor + if (lyPred < yL0) { + kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil + } + } + // calcola kMinY, kMaxY effettuando anche il clippind su dn + kMinY = std::max(kMinY, (int)0); + kMaxY = std::min(kMaxY, yMax - yMin); + + // calcola kMinX, kMaxX intersecando la (2) con i lati + // (x = xMin) e (x = xMax) di up + if (deltaXL > 0) // (deltaXL != 0) + { + // [a, b] interno ad up+(bordo destro/basso) + assert(xL0 <= lxPred); + + kMaxX = (lxPred - xL0) / deltaXL; // floor + if (xL0 < 0) { + kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil + } + } else // (deltaXL < 0) + { + // [a, b] interno ad up+(bordo destro/basso) + assert(0 <= xL0); + + kMaxX = xL0 / (-deltaXL); // floor + if (lxPred < xL0) { + kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil + } + } + // calcola kMinX, kMaxX effettuando anche il clippind su dn + kMinX = std::max(kMinX, (int)0); + kMaxX = std::min(kMaxX, xMax - xMin); + + int dnWrap = dn->getWrap(); + int upWrap = up->getWrap(); + dn->lock(); + up->lock(); + + PIX *upBasePix = up->pixels(); + PIX *dnRow = dn->pixels(yMin + kMinY); + + // (xL, yL) sono le coordinate (inizializzate per il round) + // in versione "TLonghizzata" del pixel corrente di up + int yL = yL0 + (kMinY - 1) * deltaYL; // inizializza yL + + // scorre le scanline di boundingBoxD + for (int kY = kMinY; kY <= kMaxY; kY++, dnRow += dnWrap) { + int xL = xL0 + (kMinX - 1) * deltaXL; // inizializza xL + yL += deltaYL; + // il punto di up TPointD(xL/(1<> PADN; // round + + PIX *dnPix = dnRow + xMin + kMinX; + PIX *dnEndPix = dnRow + xMin + kMaxX + 1; + + // scorre i pixel sulla (yMin + kY)-esima scanline di dn + for (; dnPix < dnEndPix; ++dnPix) { + xL += deltaXL; + // il punto di up TPointD(xL/(1<> PADN; // round + + assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) && + (yI <= up->getLy() - 1)); + + *dnPix = *(upBasePix + (yI * upWrap + xI)); + } + } + + dn->unlock(); + up->unlock(); } //============================================================================= @@ -2993,276 +2929,265 @@ void doQuickResampleNoFilter( // //============================================================================= -void doQuickPutCmapped( - const TRaster32P &dn, - const TRasterCM32P &up, - const TPaletteP &palette, - const TAffine &aff, - const TPixel32 &globalColorScale, - bool inksOnly) -{ - // se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine - // di up e' un segmento (o un punto) - if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) - return; +void doQuickPutCmapped(const TRaster32P &dn, const TRasterCM32P &up, + const TPaletteP &palette, const TAffine &aff, + const TPixel32 &globalColorScale, bool inksOnly) { + // se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine + // di up e' un segmento (o un punto) + if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) return; - // contatore bit di shift - const int PADN = 16; - - // max dimensioni di up gestibili (limite imposto dal numero di bit - // disponibili per la parte intera di xL, yL) - assert(std::max(up->getLx(), up->getLy()) < (1 << (8 * sizeof(int) - PADN - 1))); - - TRectD boundingBoxD = TRectD(convert(dn->getBounds())) * - (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5)); - - // clipping - if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) - return; + // contatore bit di shift + const int PADN = 16; - // clipping y su dn - int yMin = std::max(tfloor(boundingBoxD.y0), 0); + // max dimensioni di up gestibili (limite imposto dal numero di bit + // disponibili per la parte intera di xL, yL) + assert(std::max(up->getLx(), up->getLy()) < + (1 << (8 * sizeof(int) - PADN - 1))); + + TRectD boundingBoxD = + TRectD(convert(dn->getBounds())) * + (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5)); + + // clipping + if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) + return; + + // clipping y su dn + int yMin = std::max(tfloor(boundingBoxD.y0), 0); - // clipping y su dn - int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); - - // clipping x su dn - int xMin = std::max(tfloor(boundingBoxD.x0), 0); - - // clipping x su dn - int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); - - // inversa di aff - TAffine invAff = inv(aff); - - // nel disegnare la y-esima scanline di dn, il passaggio al pixel - // successivo comporta l'incremento (deltaXD, deltaYD) delle coordinate del - // pixel corrispondente di up - double deltaXD = invAff.a11; - double deltaYD = invAff.a21; - - // deltaXD "TLonghizzato" (round) - int deltaXL = tround(deltaXD * (1 << PADN)); - - // deltaYD "TLonghizzato" (round) - int deltaYL = tround(deltaYD * (1 << PADN)); - - // se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un - // segmento (o un punto) - if ((deltaXL == 0) && (deltaYL == 0)) - return; - - // TINT32 predecessore di up->getLx() - int lxPred = up->getLx() * (1 << PADN) - 1; - - // TINT32 predecessore di up->getLy() - int lyPred = up->getLy() * (1 << PADN) - 1; - - int dnWrap = dn->getWrap(); - int upWrap = up->getWrap(); - - std::vector colors(palette->getStyleCount()); - //vector inks(palette->getStyleCount()); - - if (globalColorScale != TPixel::Black) - for (int i = 0; i < palette->getStyleCount(); i++) - colors[i] = applyColorScaleCMapped(palette->getStyle(i)->getAverageColor(), globalColorScale); - else - for (int i = 0; i < palette->getStyleCount(); i++) - colors[i] = ::premultiply(palette->getStyle(i)->getAverageColor()); - - dn->lock(); - up->lock(); - - TPixel32 *dnRow = dn->pixels(yMin); - TPixelCM32 *upBasePix = up->pixels(); - - // scorre le scanline di boundingBoxD - for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) { - // (1) equazione k-parametrica della y-esima scanline di boundingBoxD: - // (xMin, y) + k*(1, 0), k = 0, ..., (xMax - xMin) - - // (2) equazione k-parametrica dell'immagine mediante invAff di (1): - // invAff*(xMin, y) + k*(deltaXD, deltaYD), - // k = kMin, ..., kMax con 0 <= kMin <= kMax <= (xMax - xMin) - - // calcola kMin, kMax per la scanline corrente - // intersecando la (2) con i lati di up - - // il segmento [a, b] di up e' la controimmagine mediante aff della - // porzione di scanline [ (xMin, y), (xMax, y) ] di dn - - // TPointD b = invAff*TPointD(xMax, y); - TPointD a = invAff * TPointD(xMin, y); - - // (xL0, yL0) sono le coordinate di a (inizializzate per il round) - // in versione "TLonghizzata" - // 0 <= xL0 + k*deltaXL - // < up->getLx()*(1<getLy()*(1<getLx()*(1< - // 0 <= xL0 + k*deltaXL - // <= lxPred - // - // 0 <= yL0 + k*deltaYL - // < up->getLy()*(1< - // 0 <= yL0 + k*deltaYL - // <= lyPred - - // calcola kMinX, kMaxX - if (deltaXL == 0) { - // [a, b] verticale esterno ad up+(bordo destro/basso) - if ((xL0 < 0) || (lxPred < xL0)) - continue; - // altrimenti usa solo - // kMinY, kMaxY ((deltaXL != 0) || (deltaYL != 0)) - } else if (deltaXL > 0) { - // [a, b] esterno ad up+(bordo destro/basso) - if (lxPred < xL0) - continue; - - kMaxX = (lxPred - xL0) / deltaXL; // floor - if (xL0 < 0) { - kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil - } - } else // (deltaXL < 0) - { - // [a, b] esterno ad up+(bordo destro/basso) - if (xL0 < 0) - continue; - - kMaxX = xL0 / (-deltaXL); // floor - if (lxPred < xL0) { - kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil - } - } - - // calcola kMinY, kMaxY - if (deltaYL == 0) { - // [a, b] orizzontale esterno ad up+(bordo destro/basso) - if ((yL0 < 0) || (lyPred < yL0)) - continue; - // altrimenti usa solo - // kMinX, kMaxX ((deltaXL != 0) || (deltaYL != 0)) - } else if (deltaYL > 0) { - // [a, b] esterno ad up+(bordo destro/basso) - if (lyPred < yL0) - continue; - - kMaxY = (lyPred - yL0) / deltaYL; // floor - if (yL0 < 0) { - kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil - } - } else // (deltaYL < 0) - { - // [a, b] esterno ad up+(bordo destro/basso) - if (yL0 < 0) - continue; - - kMaxY = yL0 / (-deltaYL); // floor - if (lyPred < yL0) { - kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil - } - } - - // calcola kMin, kMax effettuando anche il clippind su dn - int kMin = std::max({kMinX, kMinY, (int)0}); - int kMax = std::min({kMaxX, kMaxY, xMax - xMin}); - - TPixel32 *dnPix = dnRow + xMin + kMin; - TPixel32 *dnEndPix = dnRow + xMin + kMax + 1; - - // (xL, yL) sono le coordinate (inizializzate per il round) - // in versione "TLonghizzata" del pixel corrente di up - int xL = xL0 + (kMin - 1) * deltaXL; // inizializza xL - int yL = yL0 + (kMin - 1) * deltaYL; // inizializza yL - - // scorre i pixel sulla y-esima scanline di boundingBoxD - for (; dnPix < dnEndPix; ++dnPix) { - xL += deltaXL; - yL += deltaYL; - - // il punto di up TPointD(xL/(1<> PADN; // round - int yI = yL >> PADN; // round - - assert((0 <= xI) && (xI <= up->getLx() - 1) && - (0 <= yI) && (yI <= up->getLy() - 1)); - - TPixelCM32 *upPix = upBasePix + (yI * upWrap + xI); - int t = upPix->getTone(); - int p = upPix->getPaint(); - - if (t == 0xff && p == 0) - continue; - else { - int i = upPix->getInk(); - TPixel32 colorUp; - if (inksOnly) - switch (t) { - case 0: - colorUp = colors[i]; - break; - case 255: - colorUp = TPixel::Transparent; - break; - default: - colorUp = antialias(colors[i], 255 - t); - break; - } - else - switch (t) { - case 0: - colorUp = colors[i]; - break; - case 255: - colorUp = colors[p]; - break; - default: - colorUp = blend(colors[i], colors[p], t, TPixelCM32::getMaxTone()); - break; - } - - if (colorUp.m == 255) - *dnPix = colorUp; - else if (colorUp.m != 0) - *dnPix = quickOverPix(*dnPix, colorUp); - } - } - } - dn->unlock(); - up->unlock(); + // clipping y su dn + int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); + + // clipping x su dn + int xMin = std::max(tfloor(boundingBoxD.x0), 0); + + // clipping x su dn + int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); + + // inversa di aff + TAffine invAff = inv(aff); + + // nel disegnare la y-esima scanline di dn, il passaggio al pixel + // successivo comporta l'incremento (deltaXD, deltaYD) delle coordinate del + // pixel corrispondente di up + double deltaXD = invAff.a11; + double deltaYD = invAff.a21; + + // deltaXD "TLonghizzato" (round) + int deltaXL = tround(deltaXD * (1 << PADN)); + + // deltaYD "TLonghizzato" (round) + int deltaYL = tround(deltaYD * (1 << PADN)); + + // se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un + // segmento (o un punto) + if ((deltaXL == 0) && (deltaYL == 0)) return; + + // TINT32 predecessore di up->getLx() + int lxPred = up->getLx() * (1 << PADN) - 1; + + // TINT32 predecessore di up->getLy() + int lyPred = up->getLy() * (1 << PADN) - 1; + + int dnWrap = dn->getWrap(); + int upWrap = up->getWrap(); + + std::vector colors(palette->getStyleCount()); + // vector inks(palette->getStyleCount()); + + if (globalColorScale != TPixel::Black) + for (int i = 0; i < palette->getStyleCount(); i++) + colors[i] = applyColorScaleCMapped( + palette->getStyle(i)->getAverageColor(), globalColorScale); + else + for (int i = 0; i < palette->getStyleCount(); i++) + colors[i] = ::premultiply(palette->getStyle(i)->getAverageColor()); + + dn->lock(); + up->lock(); + + TPixel32 *dnRow = dn->pixels(yMin); + TPixelCM32 *upBasePix = up->pixels(); + + // scorre le scanline di boundingBoxD + for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) { + // (1) equazione k-parametrica della y-esima scanline di boundingBoxD: + // (xMin, y) + k*(1, 0), k = 0, ..., (xMax - xMin) + + // (2) equazione k-parametrica dell'immagine mediante invAff di (1): + // invAff*(xMin, y) + k*(deltaXD, deltaYD), + // k = kMin, ..., kMax con 0 <= kMin <= kMax <= (xMax - xMin) + + // calcola kMin, kMax per la scanline corrente + // intersecando la (2) con i lati di up + + // il segmento [a, b] di up e' la controimmagine mediante aff della + // porzione di scanline [ (xMin, y), (xMax, y) ] di dn + + // TPointD b = invAff*TPointD(xMax, y); + TPointD a = invAff * TPointD(xMin, y); + + // (xL0, yL0) sono le coordinate di a (inizializzate per il round) + // in versione "TLonghizzata" + // 0 <= xL0 + k*deltaXL + // < up->getLx()*(1<getLy()*(1<getLx()*(1< + // 0 <= xL0 + k*deltaXL + // <= lxPred + // + // 0 <= yL0 + k*deltaYL + // < up->getLy()*(1< + // 0 <= yL0 + k*deltaYL + // <= lyPred + + // calcola kMinX, kMaxX + if (deltaXL == 0) { + // [a, b] verticale esterno ad up+(bordo destro/basso) + if ((xL0 < 0) || (lxPred < xL0)) continue; + // altrimenti usa solo + // kMinY, kMaxY ((deltaXL != 0) || (deltaYL != 0)) + } else if (deltaXL > 0) { + // [a, b] esterno ad up+(bordo destro/basso) + if (lxPred < xL0) continue; + + kMaxX = (lxPred - xL0) / deltaXL; // floor + if (xL0 < 0) { + kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil + } + } else // (deltaXL < 0) + { + // [a, b] esterno ad up+(bordo destro/basso) + if (xL0 < 0) continue; + + kMaxX = xL0 / (-deltaXL); // floor + if (lxPred < xL0) { + kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil + } + } + + // calcola kMinY, kMaxY + if (deltaYL == 0) { + // [a, b] orizzontale esterno ad up+(bordo destro/basso) + if ((yL0 < 0) || (lyPred < yL0)) continue; + // altrimenti usa solo + // kMinX, kMaxX ((deltaXL != 0) || (deltaYL != 0)) + } else if (deltaYL > 0) { + // [a, b] esterno ad up+(bordo destro/basso) + if (lyPred < yL0) continue; + + kMaxY = (lyPred - yL0) / deltaYL; // floor + if (yL0 < 0) { + kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil + } + } else // (deltaYL < 0) + { + // [a, b] esterno ad up+(bordo destro/basso) + if (yL0 < 0) continue; + + kMaxY = yL0 / (-deltaYL); // floor + if (lyPred < yL0) { + kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil + } + } + + // calcola kMin, kMax effettuando anche il clippind su dn + int kMin = std::max({kMinX, kMinY, (int)0}); + int kMax = std::min({kMaxX, kMaxY, xMax - xMin}); + + TPixel32 *dnPix = dnRow + xMin + kMin; + TPixel32 *dnEndPix = dnRow + xMin + kMax + 1; + + // (xL, yL) sono le coordinate (inizializzate per il round) + // in versione "TLonghizzata" del pixel corrente di up + int xL = xL0 + (kMin - 1) * deltaXL; // inizializza xL + int yL = yL0 + (kMin - 1) * deltaYL; // inizializza yL + + // scorre i pixel sulla y-esima scanline di boundingBoxD + for (; dnPix < dnEndPix; ++dnPix) { + xL += deltaXL; + yL += deltaYL; + + // il punto di up TPointD(xL/(1<> PADN; // round + int yI = yL >> PADN; // round + + assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) && + (yI <= up->getLy() - 1)); + + TPixelCM32 *upPix = upBasePix + (yI * upWrap + xI); + int t = upPix->getTone(); + int p = upPix->getPaint(); + + if (t == 0xff && p == 0) + continue; + else { + int i = upPix->getInk(); + TPixel32 colorUp; + if (inksOnly) switch (t) { + case 0: + colorUp = colors[i]; + break; + case 255: + colorUp = TPixel::Transparent; + break; + default: + colorUp = antialias(colors[i], 255 - t); + break; + } + else + switch (t) { + case 0: + colorUp = colors[i]; + break; + case 255: + colorUp = colors[p]; + break; + default: + colorUp = blend(colors[i], colors[p], t, TPixelCM32::getMaxTone()); + break; + } + + if (colorUp.m == 255) + *dnPix = colorUp; + else if (colorUp.m != 0) + *dnPix = quickOverPix(*dnPix, colorUp); + } + } + } + dn->unlock(); + up->unlock(); } //============================================================================= @@ -3275,757 +3200,735 @@ TPixel TransparencyCheckBlackBgInk = TPixel(255,255,255); //bg TPixel TransparencyCheckWhiteBgInk = TPixel(0,0,0); //ink TPixel TransparencyCheckPaint = TPixel(127,127,127); //paint*/ -void doQuickPutCmapped( - const TRaster32P &dn, - const TRasterCM32P &up, - const TPaletteP &palette, - const TAffine &aff, - const TRop::CmappedQuickputSettings &s) -/*const TPixel32& globalColorScale, - bool inksOnly, - bool transparencyCheck, - bool blackBgCheck, - int inkIndex, - int paintIndex)*/ +void doQuickPutCmapped(const TRaster32P &dn, const TRasterCM32P &up, + const TPaletteP &palette, const TAffine &aff, + const TRop::CmappedQuickputSettings &s) +/*const TPixel32& globalColorScale, + bool inksOnly, + bool transparencyCheck, + bool blackBgCheck, + int inkIndex, + int paintIndex)*/ { - if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) - return; - const int PADN = 16; - assert(std::max(up->getLx(), up->getLy()) < (1 << (8 * sizeof(int) - PADN - 1))); - TRectD boundingBoxD = TRectD(convert(dn->getBounds())) * - (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5)); - if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) - return; - int yMin = std::max(tfloor(boundingBoxD.y0), 0); - int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); - int xMin = std::max(tfloor(boundingBoxD.x0), 0); - int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); - TAffine invAff = inv(aff); - double deltaXD = invAff.a11; - double deltaYD = invAff.a21; - int deltaXL = tround(deltaXD * (1 << PADN)); - int deltaYL = tround(deltaYD * (1 << PADN)); - if ((deltaXL == 0) && (deltaYL == 0)) - return; - int lxPred = up->getLx() * (1 << PADN) - 1; - int lyPred = up->getLy() * (1 << PADN) - 1; - int dnWrap = dn->getWrap(); - int upWrap = up->getWrap(); - std::vector paints(palette->getStyleCount()); - std::vector inks(palette->getStyleCount()); - - if (s.m_transparencyCheck) - for (int i = 0; i < palette->getStyleCount(); i++) { - paints[i] = s.m_transpCheckPaint; - inks[i] = s.m_blackBgCheck ? s.m_transpCheckBg : s.m_transpCheckInk; - } - else if (s.m_globalColorScale == TPixel::Black) - for (int i = 0; i < palette->getStyleCount(); i++) - paints[i] = inks[i] = ::premultiply(palette->getStyle(i)->getAverageColor()); - else - for (int i = 0; i < palette->getStyleCount(); i++) - paints[i] = inks[i] = applyColorScaleCMapped(palette->getStyle(i)->getAverageColor(), s.m_globalColorScale); - - dn->lock(); - up->lock(); - - TPixel32 *dnRow = dn->pixels(yMin); - TPixelCM32 *upBasePix = up->pixels(); - for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) { - TPointD a = invAff * TPointD(xMin, y); - int xL0 = tround((a.x + 0.5) * (1 << PADN)); - int yL0 = tround((a.y + 0.5) * (1 << PADN)); - int kMinX = 0, kMaxX = xMax - xMin; - int kMinY = 0, kMaxY = xMax - xMin; - if (deltaXL == 0) { - if ((xL0 < 0) || (lxPred < xL0)) - continue; - } else if (deltaXL > 0) { - if (lxPred < xL0) - continue; - - kMaxX = (lxPred - xL0) / deltaXL; // floor - if (xL0 < 0) - kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil - } else { - if (xL0 < 0) - continue; - - kMaxX = xL0 / (-deltaXL); // floor - if (lxPred < xL0) - kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil - } - if (deltaYL == 0) { - if ((yL0 < 0) || (lyPred < yL0)) - continue; - } else if (deltaYL > 0) { - if (lyPred < yL0) - continue; - - kMaxY = (lyPred - yL0) / deltaYL; - if (yL0 < 0) - kMinY = ((-yL0) + deltaYL - 1) / deltaYL; - } else { - if (yL0 < 0) - continue; - kMaxY = yL0 / (-deltaYL); // floor - if (lyPred < yL0) - kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil - } - int kMin = std::max({kMinX, kMinY, (int)0}); - int kMax = std::min({kMaxX, kMaxY, xMax - xMin}); - - TPixel32 *dnPix = dnRow + xMin + kMin; - TPixel32 *dnEndPix = dnRow + xMin + kMax + 1; - int xL = xL0 + (kMin - 1) * deltaXL; - int yL = yL0 + (kMin - 1) * deltaYL; - for (; dnPix < dnEndPix; ++dnPix) { - xL += deltaXL; - yL += deltaYL; - int xI = xL >> PADN; - int yI = yL >> PADN; - assert((0 <= xI) && (xI <= up->getLx() - 1) && - (0 <= yI) && (yI <= up->getLy() - 1)); - TPixelCM32 *upPix = upBasePix + (yI * upWrap + xI); - int t = upPix->getTone(); - int p = upPix->getPaint(); - - if (t == 0xff && p == 0) - continue; - else { - int i = upPix->getInk(); - TPixel32 colorUp; - if (s.m_inksOnly) - switch (t) { - case 0: - colorUp = (i == s.m_inkIndex) ? TPixel::Red : inks[i]; - break; - case 255: - colorUp = TPixel::Transparent; - break; - default: { - TPixel inkColor; - if (i == s.m_inkIndex) { - inkColor = TPixel::Red; - if (p == 0) { - t = t / 2; // transparency check(for a bug!) darken semitrasparent pixels; ghibli likes it, and wants it also for ink checks... - // otherwise, ramps goes always from reds towards grey... - } - } else - inkColor = inks[i]; - - colorUp = antialias(inkColor, 255 - t); - break; - } - } - else - switch (t) { - case 0: - colorUp = (i == s.m_inkIndex) ? TPixel::Red : inks[i]; - break; - case 255: - colorUp = (p == s.m_paintIndex) ? TPixel::Red : paints[p]; - break; - default: { - TPixel paintColor = (p == s.m_paintIndex) ? TPixel::Red : paints[p]; - TPixel inkColor; - if (i == s.m_inkIndex) { - inkColor = TPixel::Red; - if (p == 0) { - paintColor = TPixel::Transparent; - } - } else - inkColor = inks[i]; - - if (s.m_transparencyCheck) - t = t / 2; - - colorUp = blend(inkColor, paintColor, t, TPixelCM32::getMaxTone()); - break; - } - } - - if (colorUp.m == 255) - *dnPix = colorUp; - else if (colorUp.m != 0) - *dnPix = quickOverPix(*dnPix, colorUp); - } - } - } - dn->unlock(); - up->unlock(); + if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) return; + const int PADN = 16; + assert(std::max(up->getLx(), up->getLy()) < + (1 << (8 * sizeof(int) - PADN - 1))); + TRectD boundingBoxD = + TRectD(convert(dn->getBounds())) * + (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5)); + if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) + return; + int yMin = std::max(tfloor(boundingBoxD.y0), 0); + int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); + int xMin = std::max(tfloor(boundingBoxD.x0), 0); + int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); + TAffine invAff = inv(aff); + double deltaXD = invAff.a11; + double deltaYD = invAff.a21; + int deltaXL = tround(deltaXD * (1 << PADN)); + int deltaYL = tround(deltaYD * (1 << PADN)); + if ((deltaXL == 0) && (deltaYL == 0)) return; + int lxPred = up->getLx() * (1 << PADN) - 1; + int lyPred = up->getLy() * (1 << PADN) - 1; + int dnWrap = dn->getWrap(); + int upWrap = up->getWrap(); + std::vector paints(palette->getStyleCount()); + std::vector inks(palette->getStyleCount()); + + if (s.m_transparencyCheck) + for (int i = 0; i < palette->getStyleCount(); i++) { + paints[i] = s.m_transpCheckPaint; + inks[i] = s.m_blackBgCheck ? s.m_transpCheckBg : s.m_transpCheckInk; + } + else if (s.m_globalColorScale == TPixel::Black) + for (int i = 0; i < palette->getStyleCount(); i++) + paints[i] = inks[i] = + ::premultiply(palette->getStyle(i)->getAverageColor()); + else + for (int i = 0; i < palette->getStyleCount(); i++) + paints[i] = inks[i] = applyColorScaleCMapped( + palette->getStyle(i)->getAverageColor(), s.m_globalColorScale); + + dn->lock(); + up->lock(); + + TPixel32 *dnRow = dn->pixels(yMin); + TPixelCM32 *upBasePix = up->pixels(); + for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) { + TPointD a = invAff * TPointD(xMin, y); + int xL0 = tround((a.x + 0.5) * (1 << PADN)); + int yL0 = tround((a.y + 0.5) * (1 << PADN)); + int kMinX = 0, kMaxX = xMax - xMin; + int kMinY = 0, kMaxY = xMax - xMin; + if (deltaXL == 0) { + if ((xL0 < 0) || (lxPred < xL0)) continue; + } else if (deltaXL > 0) { + if (lxPred < xL0) continue; + + kMaxX = (lxPred - xL0) / deltaXL; // floor + if (xL0 < 0) kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil + } else { + if (xL0 < 0) continue; + + kMaxX = xL0 / (-deltaXL); // floor + if (lxPred < xL0) + kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil + } + if (deltaYL == 0) { + if ((yL0 < 0) || (lyPred < yL0)) continue; + } else if (deltaYL > 0) { + if (lyPred < yL0) continue; + + kMaxY = (lyPred - yL0) / deltaYL; + if (yL0 < 0) kMinY = ((-yL0) + deltaYL - 1) / deltaYL; + } else { + if (yL0 < 0) continue; + kMaxY = yL0 / (-deltaYL); // floor + if (lyPred < yL0) + kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil + } + int kMin = std::max({kMinX, kMinY, (int)0}); + int kMax = std::min({kMaxX, kMaxY, xMax - xMin}); + + TPixel32 *dnPix = dnRow + xMin + kMin; + TPixel32 *dnEndPix = dnRow + xMin + kMax + 1; + int xL = xL0 + (kMin - 1) * deltaXL; + int yL = yL0 + (kMin - 1) * deltaYL; + for (; dnPix < dnEndPix; ++dnPix) { + xL += deltaXL; + yL += deltaYL; + int xI = xL >> PADN; + int yI = yL >> PADN; + assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) && + (yI <= up->getLy() - 1)); + TPixelCM32 *upPix = upBasePix + (yI * upWrap + xI); + int t = upPix->getTone(); + int p = upPix->getPaint(); + + if (t == 0xff && p == 0) + continue; + else { + int i = upPix->getInk(); + TPixel32 colorUp; + if (s.m_inksOnly) switch (t) { + case 0: + colorUp = (i == s.m_inkIndex) ? TPixel::Red : inks[i]; + break; + case 255: + colorUp = TPixel::Transparent; + break; + default: { + TPixel inkColor; + if (i == s.m_inkIndex) { + inkColor = TPixel::Red; + if (p == 0) { + t = t / 2; // transparency check(for a bug!) darken + // semitrasparent pixels; ghibli likes it, and wants + // it also for ink checks... + // otherwise, ramps goes always from reds towards grey... + } + } else + inkColor = inks[i]; + + colorUp = antialias(inkColor, 255 - t); + break; + } + } + else + switch (t) { + case 0: + colorUp = (i == s.m_inkIndex) ? TPixel::Red : inks[i]; + break; + case 255: + colorUp = (p == s.m_paintIndex) ? TPixel::Red : paints[p]; + break; + default: { + TPixel paintColor = (p == s.m_paintIndex) ? TPixel::Red : paints[p]; + TPixel inkColor; + if (i == s.m_inkIndex) { + inkColor = TPixel::Red; + if (p == 0) { + paintColor = TPixel::Transparent; + } + } else + inkColor = inks[i]; + + if (s.m_transparencyCheck) t = t / 2; + + colorUp = blend(inkColor, paintColor, t, TPixelCM32::getMaxTone()); + break; + } + } + + if (colorUp.m == 255) + *dnPix = colorUp; + else if (colorUp.m != 0) + *dnPix = quickOverPix(*dnPix, colorUp); + } + } + } + dn->unlock(); + up->unlock(); } //============================================================================= //============================================================================= -void doQuickPutCmapped( - const TRaster32P &dn, - const TRasterCM32P &up, - const TPaletteP &palette, - double sx, double sy, - double tx, double ty, - const TPixel32 &globalColorScale, - bool inksOnly) -{ - // se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine - // di up e' un segmento (o un punto) - if ((sx == 0) || (sy == 0)) - return; - - // contatore bit di shift - const int PADN = 16; - assert(std::max(up->getLx(), up->getLy()) < (1 << (8 * sizeof(int) - PADN - 1))); - // max dimensioni di up gestibili (limite imposto dal numero di bit - // disponibili per la parte intera di xL, yL) - - TAffine aff(sx, 0, tx, 0, sy, ty); - TRectD boundingBoxD = TRectD(convert(dn->getBounds())) * - (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5)); - - // clipping - if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) - return; - - // clipping y su dn - int yMin = std::max(tfloor(boundingBoxD.y0), 0); - - // clipping y su dn - int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); - - // clipping x su dn - int xMin = std::max(tfloor(boundingBoxD.x0), 0); - - // clipping x su dn - int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); - - TAffine invAff = inv(aff); // inversa di aff - - // nello scorrere le scanline di boundingBoxD, il passaggio alla scanline - // successiva comporta l'incremento (0, deltaYD) delle coordinate dei - // pixels corrispondenti di up - - // nel disegnare la y-esima scanline di dn, il passaggio al pixel - // successivo comporta l'incremento (deltaXD, 0) delle coordinate del - // pixel corrispondente di up - - double deltaXD = invAff.a11; - double deltaYD = invAff.a22; - - // deltaXD "TLonghizzato" (round) - int deltaXL = tround(deltaXD * (1 << PADN)); - - // deltaYD "TLonghizzato" (round) - int deltaYL = tround(deltaYD * (1 << PADN)); - - // se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un - // segmento (o un punto) - if ((deltaXL == 0) || (deltaYL == 0)) - return; - - // (1) equazione (kX, kY)-parametrica di boundingBoxD: - // (xMin, yMin) + kX*(1, 0) + kY*(0, 1), - // kX = 0, ..., (xMax - xMin), - // kY = 0, ..., (yMax - yMin) - - // (2) equazione (kX, kY)-parametrica dell'immagine - // mediante invAff di (1): - // invAff*(xMin, yMin) + kX*(deltaXD, 0) + kY*(0, deltaYD), - // kX = kMinX, ..., kMaxX - // con 0 <= kMinX <= kMaxX <= (xMax - xMin) - // - // kY = kMinY, ..., kMaxY - // con 0 <= kMinY <= kMaxY <= (yMax - yMin) - - // calcola kMinX, kMaxX, kMinY, kMaxY intersecando la (2) con i lati di up - - // il segmento [a, b] di up e' la controimmagine mediante aff della - // porzione di scanline [ (xMin, yMin), (xMax, yMin) ] di dn - - // TPointD b = invAff*TPointD(xMax, yMin); - TPointD a = invAff * TPointD(xMin, yMin); - - // (xL0, yL0) sono le coordinate di a (inizializzate per il round) - // in versione "TLonghizzata" - // 0 <= xL0 + kX*deltaXL - // < up->getLx()*(1<getLy()*(1<getLx() - int lxPred = up->getLx() * (1 << PADN) - 1; - - // TINT32 predecessore di up->getLy() - int lyPred = up->getLy() * (1 << PADN) - 1; - - // 0 <= xL0 + k*deltaXL < up->getLx()*(1< - // 0 <= xL0 + k*deltaXL <= lxPred - - // 0 <= yL0 + k*deltaYL < up->getLy()*(1< - // 0 <= yL0 + k*deltaYL <= lyPred - - // calcola kMinY, kMaxY intersecando la (2) con i lati - // (y = yMin) e (y = yMax) di up - if (deltaYL > 0) // (deltaYL != 0) - { - // [a, b] interno ad up+(bordo destro/basso) - assert(yL0 <= lyPred); - - kMaxY = (lyPred - yL0) / deltaYL; // floor - if (yL0 < 0) { - kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil - } - } else // (deltaYL < 0) - { - // [a, b] interno ad up+(bordo destro/basso) - assert(0 <= yL0); - - kMaxY = yL0 / (-deltaYL); // floor - if (lyPred < yL0) { - kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil - } - } - // calcola kMinY, kMaxY effettuando anche il clippind su dn - kMinY = std::max(kMinY, (int)0); - kMaxY = std::min(kMaxY, yMax - yMin); - - // calcola kMinX, kMaxX intersecando la (2) con i lati - // (x = xMin) e (x = xMax) di up - if (deltaXL > 0) // (deltaXL != 0) - { - // [a, b] interno ad up+(bordo destro/basso) - assert(xL0 <= lxPred); - - kMaxX = (lxPred - xL0) / deltaXL; // floor - if (xL0 < 0) { - kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil - } - } else // (deltaXL < 0) - { - // [a, b] interno ad up+(bordo destro/basso) - assert(0 <= xL0); - - kMaxX = xL0 / (-deltaXL); // floor - if (lxPred < xL0) { - kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil - } - } - // calcola kMinX, kMaxX effettuando anche il clippind su dn - kMinX = std::max(kMinX, (int)0); - kMaxX = std::min(kMaxX, xMax - xMin); - - int dnWrap = dn->getWrap(); - int upWrap = up->getWrap(); - - int count = std::max({palette->getStyleCount(), TPixelCM32::getMaxInk(), TPixelCM32::getMaxPaint()}); - - std::vector paints(count, TPixel32::Red); - std::vector inks(count, TPixel32::Red); - if (globalColorScale != TPixel::Black) - for (int i = 0; i < palette->getStyleCount(); i++) - paints[i] = inks[i] = applyColorScaleCMapped(palette->getStyle(i)->getAverageColor(), globalColorScale); - else - for (int i = 0; i < palette->getStyleCount(); i++) - paints[i] = inks[i] = ::premultiply(palette->getStyle(i)->getAverageColor()); - - dn->lock(); - up->lock(); - TPixelCM32 *upBasePix = up->pixels(); - TPixel32 *dnRow = dn->pixels(yMin + kMinY); - - // (xL, yL) sono le coordinate (inizializzate per il round) - // in versione "TLonghizzata" del pixel corrente di up - - // inizializza yL - int yL = yL0 + (kMinY - 1) * deltaYL; - - // scorre le scanline di boundingBoxD - for (int kY = kMinY; kY <= kMaxY; kY++, dnRow += dnWrap) { - // inizializza xL - int xL = xL0 + (kMinX - 1) * deltaXL; - yL += deltaYL; - - // il punto di up TPointD(xL/(1<> PADN; // round - - TPixel32 *dnPix = dnRow + xMin + kMinX; - TPixel32 *dnEndPix = dnRow + xMin + kMaxX + 1; - - // scorre i pixel sulla (yMin + kY)-esima scanline di dn - for (; dnPix < dnEndPix; ++dnPix) { - xL += deltaXL; - // il punto di up TPointD(xL/(1<> PADN; // round - - assert((0 <= xI) && (xI <= up->getLx() - 1) && - (0 <= yI) && (yI <= up->getLy() - 1)); - - TPixelCM32 *upPix = upBasePix + (yI * upWrap + xI); - int t = upPix->getTone(); - int p = upPix->getPaint(); - assert(0 <= t && t < 256); - assert(0 <= p && p < (int)paints.size()); - - if (t == 0xff && p == 0) - continue; - else { - int i = upPix->getInk(); - assert(0 <= i && i < (int)inks.size()); - TPixel32 colorUp; - if (inksOnly) - switch (t) { - case 0: - colorUp = inks[i]; - break; - case 255: - colorUp = TPixel::Transparent; - break; - default: - colorUp = antialias(inks[i], 255 - t); - break; - } - else - switch (t) { - case 0: - colorUp = inks[i]; - break; - case 255: - colorUp = paints[p]; - break; - default: - colorUp = blend(inks[i], paints[p], t, TPixelCM32::getMaxTone()); - break; - } - - if (colorUp.m == 255) - *dnPix = colorUp; - else if (colorUp.m != 0) - *dnPix = quickOverPix(*dnPix, colorUp); - } - } - } - dn->unlock(); - up->unlock(); +void doQuickPutCmapped(const TRaster32P &dn, const TRasterCM32P &up, + const TPaletteP &palette, double sx, double sy, + double tx, double ty, const TPixel32 &globalColorScale, + bool inksOnly) { + // se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine + // di up e' un segmento (o un punto) + if ((sx == 0) || (sy == 0)) return; + + // contatore bit di shift + const int PADN = 16; + assert(std::max(up->getLx(), up->getLy()) < + (1 << (8 * sizeof(int) - PADN - 1))); + // max dimensioni di up gestibili (limite imposto dal numero di bit + // disponibili per la parte intera di xL, yL) + + TAffine aff(sx, 0, tx, 0, sy, ty); + TRectD boundingBoxD = + TRectD(convert(dn->getBounds())) * + (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5)); + + // clipping + if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) + return; + + // clipping y su dn + int yMin = std::max(tfloor(boundingBoxD.y0), 0); + + // clipping y su dn + int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); + + // clipping x su dn + int xMin = std::max(tfloor(boundingBoxD.x0), 0); + + // clipping x su dn + int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); + + TAffine invAff = inv(aff); // inversa di aff + + // nello scorrere le scanline di boundingBoxD, il passaggio alla scanline + // successiva comporta l'incremento (0, deltaYD) delle coordinate dei + // pixels corrispondenti di up + + // nel disegnare la y-esima scanline di dn, il passaggio al pixel + // successivo comporta l'incremento (deltaXD, 0) delle coordinate del + // pixel corrispondente di up + + double deltaXD = invAff.a11; + double deltaYD = invAff.a22; + + // deltaXD "TLonghizzato" (round) + int deltaXL = tround(deltaXD * (1 << PADN)); + + // deltaYD "TLonghizzato" (round) + int deltaYL = tround(deltaYD * (1 << PADN)); + + // se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un + // segmento (o un punto) + if ((deltaXL == 0) || (deltaYL == 0)) return; + + // (1) equazione (kX, kY)-parametrica di boundingBoxD: + // (xMin, yMin) + kX*(1, 0) + kY*(0, 1), + // kX = 0, ..., (xMax - xMin), + // kY = 0, ..., (yMax - yMin) + + // (2) equazione (kX, kY)-parametrica dell'immagine + // mediante invAff di (1): + // invAff*(xMin, yMin) + kX*(deltaXD, 0) + kY*(0, deltaYD), + // kX = kMinX, ..., kMaxX + // con 0 <= kMinX <= kMaxX <= (xMax - xMin) + // + // kY = kMinY, ..., kMaxY + // con 0 <= kMinY <= kMaxY <= (yMax - yMin) + + // calcola kMinX, kMaxX, kMinY, kMaxY intersecando la (2) con i lati di up + + // il segmento [a, b] di up e' la controimmagine mediante aff della + // porzione di scanline [ (xMin, yMin), (xMax, yMin) ] di dn + + // TPointD b = invAff*TPointD(xMax, yMin); + TPointD a = invAff * TPointD(xMin, yMin); + + // (xL0, yL0) sono le coordinate di a (inizializzate per il round) + // in versione "TLonghizzata" + // 0 <= xL0 + kX*deltaXL + // < up->getLx()*(1<getLy()*(1<getLx() + int lxPred = up->getLx() * (1 << PADN) - 1; + + // TINT32 predecessore di up->getLy() + int lyPred = up->getLy() * (1 << PADN) - 1; + + // 0 <= xL0 + k*deltaXL < up->getLx()*(1< + // 0 <= xL0 + k*deltaXL <= lxPred + + // 0 <= yL0 + k*deltaYL < up->getLy()*(1< + // 0 <= yL0 + k*deltaYL <= lyPred + + // calcola kMinY, kMaxY intersecando la (2) con i lati + // (y = yMin) e (y = yMax) di up + if (deltaYL > 0) // (deltaYL != 0) + { + // [a, b] interno ad up+(bordo destro/basso) + assert(yL0 <= lyPred); + + kMaxY = (lyPred - yL0) / deltaYL; // floor + if (yL0 < 0) { + kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil + } + } else // (deltaYL < 0) + { + // [a, b] interno ad up+(bordo destro/basso) + assert(0 <= yL0); + + kMaxY = yL0 / (-deltaYL); // floor + if (lyPred < yL0) { + kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil + } + } + // calcola kMinY, kMaxY effettuando anche il clippind su dn + kMinY = std::max(kMinY, (int)0); + kMaxY = std::min(kMaxY, yMax - yMin); + + // calcola kMinX, kMaxX intersecando la (2) con i lati + // (x = xMin) e (x = xMax) di up + if (deltaXL > 0) // (deltaXL != 0) + { + // [a, b] interno ad up+(bordo destro/basso) + assert(xL0 <= lxPred); + + kMaxX = (lxPred - xL0) / deltaXL; // floor + if (xL0 < 0) { + kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil + } + } else // (deltaXL < 0) + { + // [a, b] interno ad up+(bordo destro/basso) + assert(0 <= xL0); + + kMaxX = xL0 / (-deltaXL); // floor + if (lxPred < xL0) { + kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil + } + } + // calcola kMinX, kMaxX effettuando anche il clippind su dn + kMinX = std::max(kMinX, (int)0); + kMaxX = std::min(kMaxX, xMax - xMin); + + int dnWrap = dn->getWrap(); + int upWrap = up->getWrap(); + + int count = std::max({palette->getStyleCount(), TPixelCM32::getMaxInk(), + TPixelCM32::getMaxPaint()}); + + std::vector paints(count, TPixel32::Red); + std::vector inks(count, TPixel32::Red); + if (globalColorScale != TPixel::Black) + for (int i = 0; i < palette->getStyleCount(); i++) + paints[i] = inks[i] = applyColorScaleCMapped( + palette->getStyle(i)->getAverageColor(), globalColorScale); + else + for (int i = 0; i < palette->getStyleCount(); i++) + paints[i] = inks[i] = + ::premultiply(palette->getStyle(i)->getAverageColor()); + + dn->lock(); + up->lock(); + TPixelCM32 *upBasePix = up->pixels(); + TPixel32 *dnRow = dn->pixels(yMin + kMinY); + + // (xL, yL) sono le coordinate (inizializzate per il round) + // in versione "TLonghizzata" del pixel corrente di up + + // inizializza yL + int yL = yL0 + (kMinY - 1) * deltaYL; + + // scorre le scanline di boundingBoxD + for (int kY = kMinY; kY <= kMaxY; kY++, dnRow += dnWrap) { + // inizializza xL + int xL = xL0 + (kMinX - 1) * deltaXL; + yL += deltaYL; + + // il punto di up TPointD(xL/(1<> PADN; // round + + TPixel32 *dnPix = dnRow + xMin + kMinX; + TPixel32 *dnEndPix = dnRow + xMin + kMaxX + 1; + + // scorre i pixel sulla (yMin + kY)-esima scanline di dn + for (; dnPix < dnEndPix; ++dnPix) { + xL += deltaXL; + // il punto di up TPointD(xL/(1<> PADN; // round + + assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) && + (yI <= up->getLy() - 1)); + + TPixelCM32 *upPix = upBasePix + (yI * upWrap + xI); + int t = upPix->getTone(); + int p = upPix->getPaint(); + assert(0 <= t && t < 256); + assert(0 <= p && p < (int)paints.size()); + + if (t == 0xff && p == 0) + continue; + else { + int i = upPix->getInk(); + assert(0 <= i && i < (int)inks.size()); + TPixel32 colorUp; + if (inksOnly) switch (t) { + case 0: + colorUp = inks[i]; + break; + case 255: + colorUp = TPixel::Transparent; + break; + default: + colorUp = antialias(inks[i], 255 - t); + break; + } + else + switch (t) { + case 0: + colorUp = inks[i]; + break; + case 255: + colorUp = paints[p]; + break; + default: + colorUp = blend(inks[i], paints[p], t, TPixelCM32::getMaxTone()); + break; + } + + if (colorUp.m == 255) + *dnPix = colorUp; + else if (colorUp.m != 0) + *dnPix = quickOverPix(*dnPix, colorUp); + } + } + } + dn->unlock(); + up->unlock(); } //============================================================================= //============================================================================= //============================================================================= -void doQuickResampleColorFilter( - const TRaster32P &dn, - const TRasterCM32P &up, - const TPaletteP &plt, - const TAffine &aff, - UCHAR colorMask) -{ - if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) - return; - const int PADN = 16; - - std::vector paints(plt->getStyleCount()); - std::vector inks(plt->getStyleCount()); - - for (int i = 0; i < plt->getStyleCount(); i++) - paints[i] = inks[i] = ::premultiply(plt->getStyle(i)->getAverageColor()); - - assert(std::max(up->getLx(), up->getLy()) < (1 << (8 * sizeof(int) - PADN - 1))); - - TRectD boundingBoxD = TRectD(convert(dn->getBounds())) * - (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5)); - - if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) - return; - - int yMin = std::max(tfloor(boundingBoxD.y0), 0); // clipping y su dn - int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); // clipping y su dn - int xMin = std::max(tfloor(boundingBoxD.x0), 0); // clipping x su dn - int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); // clipping x su dn - - TAffine invAff = inv(aff); // inversa di aff - - double deltaXD = invAff.a11; - double deltaYD = invAff.a21; - int deltaXL = tround(deltaXD * (1 << PADN)); // deltaXD "TLonghizzato" (round) - int deltaYL = tround(deltaYD * (1 << PADN)); // deltaYD "TLonghizzato" (round) - if ((deltaXL == 0) && (deltaYL == 0)) - return; - - int lxPred = up->getLx() * (1 << PADN) - 1; // TINT32 predecessore di up->getLx() - int lyPred = up->getLy() * (1 << PADN) - 1; // TINT32 predecessore di up->getLy() - - int dnWrap = dn->getWrap(); - int upWrap = up->getWrap(); - dn->lock(); - up->lock(); - - TPixel32 *dnRow = dn->pixels(yMin); - TPixelCM32 *upBasePix = up->pixels(); - - for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) { - TPointD a = invAff * TPointD(xMin, y); - int xL0 = tround((a.x + 0.5) * (1 << PADN)); - int yL0 = tround((a.y + 0.5) * (1 << PADN)); - int kMinX = 0, kMaxX = xMax - xMin; // clipping su dn - int kMinY = 0, kMaxY = xMax - xMin; // clipping su dn - if (deltaXL == 0) { - if ((xL0 < 0) || (lxPred < xL0)) - continue; - } else if (deltaXL > 0) { - if (lxPred < xL0) - continue; - - kMaxX = (lxPred - xL0) / deltaXL; // floor - if (xL0 < 0) - kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil - } else // (deltaXL < 0) - { - if (xL0 < 0) - continue; - kMaxX = xL0 / (-deltaXL); // floor - if (lxPred < xL0) - kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil - } - if (deltaYL == 0) { - if ((yL0 < 0) || (lyPred < yL0)) - continue; - } else if (deltaYL > 0) { - if (lyPred < yL0) - continue; - - kMaxY = (lyPred - yL0) / deltaYL; // floor - if (yL0 < 0) - kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil - } else // (deltaYL < 0) - { - if (yL0 < 0) - continue; - - kMaxY = yL0 / (-deltaYL); // floor - if (lyPred < yL0) - kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil - } - int kMin = std::max({kMinX, kMinY, (int)0}); - int kMax = std::min({kMaxX, kMaxY, xMax - xMin}); - TPixel32 *dnPix = dnRow + xMin + kMin; - TPixel32 *dnEndPix = dnRow + xMin + kMax + 1; - int xL = xL0 + (kMin - 1) * deltaXL; // inizializza xL - int yL = yL0 + (kMin - 1) * deltaYL; // inizializza yL - for (; dnPix < dnEndPix; ++dnPix) { - xL += deltaXL; - yL += deltaYL; - int xI = xL >> PADN; // round - int yI = yL >> PADN; // round - - assert((0 <= xI) && (xI <= up->getLx() - 1) && - (0 <= yI) && (yI <= up->getLy() - 1)); - - TPixelCM32 *upPix = upBasePix + (yI * upWrap + xI); - int t = upPix->getTone(); - int p = upPix->getPaint(); - int i = upPix->getInk(); - TPixel32 colorUp; - switch (t) { - case 0: - colorUp = inks[i]; - break; - case 255: - colorUp = paints[p]; - break; - default: - colorUp = blend(inks[i], paints[p], t, TPixelCM32::getMaxTone()); - break; - } - - if (colorMask == TRop::MChan) - dnPix->r = dnPix->g = dnPix->b = colorUp.m; - else { - dnPix->r = ((colorMask & TRop::RChan) ? colorUp.r : 0); - dnPix->g = ((colorMask & TRop::GChan) ? colorUp.g : 0); - dnPix->b = ((colorMask & TRop::BChan) ? colorUp.b : 0); - } - dnPix->m = 255; - } - } - dn->unlock(); - up->unlock(); +void doQuickResampleColorFilter(const TRaster32P &dn, const TRasterCM32P &up, + const TPaletteP &plt, const TAffine &aff, + UCHAR colorMask) { + if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) return; + const int PADN = 16; + + std::vector paints(plt->getStyleCount()); + std::vector inks(plt->getStyleCount()); + + for (int i = 0; i < plt->getStyleCount(); i++) + paints[i] = inks[i] = ::premultiply(plt->getStyle(i)->getAverageColor()); + + assert(std::max(up->getLx(), up->getLy()) < + (1 << (8 * sizeof(int) - PADN - 1))); + + TRectD boundingBoxD = + TRectD(convert(dn->getBounds())) * + (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5)); + + if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) + return; + + int yMin = std::max(tfloor(boundingBoxD.y0), 0); // clipping y su dn + int yMax = + std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); // clipping y su dn + int xMin = std::max(tfloor(boundingBoxD.x0), 0); // clipping x su dn + int xMax = + std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); // clipping x su dn + + TAffine invAff = inv(aff); // inversa di aff + + double deltaXD = invAff.a11; + double deltaYD = invAff.a21; + int deltaXL = + tround(deltaXD * (1 << PADN)); // deltaXD "TLonghizzato" (round) + int deltaYL = + tround(deltaYD * (1 << PADN)); // deltaYD "TLonghizzato" (round) + if ((deltaXL == 0) && (deltaYL == 0)) return; + + int lxPred = + up->getLx() * (1 << PADN) - 1; // TINT32 predecessore di up->getLx() + int lyPred = + up->getLy() * (1 << PADN) - 1; // TINT32 predecessore di up->getLy() + + int dnWrap = dn->getWrap(); + int upWrap = up->getWrap(); + dn->lock(); + up->lock(); + + TPixel32 *dnRow = dn->pixels(yMin); + TPixelCM32 *upBasePix = up->pixels(); + + for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) { + TPointD a = invAff * TPointD(xMin, y); + int xL0 = tround((a.x + 0.5) * (1 << PADN)); + int yL0 = tround((a.y + 0.5) * (1 << PADN)); + int kMinX = 0, kMaxX = xMax - xMin; // clipping su dn + int kMinY = 0, kMaxY = xMax - xMin; // clipping su dn + if (deltaXL == 0) { + if ((xL0 < 0) || (lxPred < xL0)) continue; + } else if (deltaXL > 0) { + if (lxPred < xL0) continue; + + kMaxX = (lxPred - xL0) / deltaXL; // floor + if (xL0 < 0) kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil + } else // (deltaXL < 0) + { + if (xL0 < 0) continue; + kMaxX = xL0 / (-deltaXL); // floor + if (lxPred < xL0) + kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil + } + if (deltaYL == 0) { + if ((yL0 < 0) || (lyPred < yL0)) continue; + } else if (deltaYL > 0) { + if (lyPred < yL0) continue; + + kMaxY = (lyPred - yL0) / deltaYL; // floor + if (yL0 < 0) kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil + } else // (deltaYL < 0) + { + if (yL0 < 0) continue; + + kMaxY = yL0 / (-deltaYL); // floor + if (lyPred < yL0) + kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil + } + int kMin = std::max({kMinX, kMinY, (int)0}); + int kMax = std::min({kMaxX, kMaxY, xMax - xMin}); + TPixel32 *dnPix = dnRow + xMin + kMin; + TPixel32 *dnEndPix = dnRow + xMin + kMax + 1; + int xL = xL0 + (kMin - 1) * deltaXL; // inizializza xL + int yL = yL0 + (kMin - 1) * deltaYL; // inizializza yL + for (; dnPix < dnEndPix; ++dnPix) { + xL += deltaXL; + yL += deltaYL; + int xI = xL >> PADN; // round + int yI = yL >> PADN; // round + + assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) && + (yI <= up->getLy() - 1)); + + TPixelCM32 *upPix = upBasePix + (yI * upWrap + xI); + int t = upPix->getTone(); + int p = upPix->getPaint(); + int i = upPix->getInk(); + TPixel32 colorUp; + switch (t) { + case 0: + colorUp = inks[i]; + break; + case 255: + colorUp = paints[p]; + break; + default: + colorUp = blend(inks[i], paints[p], t, TPixelCM32::getMaxTone()); + break; + } + + if (colorMask == TRop::MChan) + dnPix->r = dnPix->g = dnPix->b = colorUp.m; + else { + dnPix->r = ((colorMask & TRop::RChan) ? colorUp.r : 0); + dnPix->g = ((colorMask & TRop::GChan) ? colorUp.g : 0); + dnPix->b = ((colorMask & TRop::BChan) ? colorUp.b : 0); + } + dnPix->m = 255; + } + } + dn->unlock(); + up->unlock(); } //========================================================== -#endif //TNZCORE_LIGHT +#endif // TNZCORE_LIGHT #ifdef OPTIMIZE_FOR_LP64 -void doQuickResampleFilter_optimized( - const TRaster32P &dn, - const TRaster32P &up, - const TAffine &aff) -{ - // se aff e' degenere la controimmagine di up e' un segmento (o un punto) - if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) - return; - - // contatore bit di shift - const int PADN = 16; +void doQuickResampleFilter_optimized(const TRaster32P &dn, const TRaster32P &up, + const TAffine &aff) { + // se aff e' degenere la controimmagine di up e' un segmento (o un punto) + if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) return; - // maschera del filtro bilineare - const int MASKN = (1 << PADN) - 1; - assert(std::max(up->getLx(), up->getLy()) < (1 << (8 * sizeof(int) - PADN - 1))); - // max dimensioni di up gestibili (limite imposto dal numero di bit - // disponibili per la parte intera di xL, yL) + // contatore bit di shift + const int PADN = 16; - TRectD boundingBoxD = TRectD(convert(dn->getSize())) * - (aff * TRectD(0, 0, up->getLx() - 2, up->getLy() - 2)); + // maschera del filtro bilineare + const int MASKN = (1 << PADN) - 1; + assert(std::max(up->getLx(), up->getLy()) < + (1 << (8 * sizeof(int) - PADN - 1))); + // max dimensioni di up gestibili (limite imposto dal numero di bit + // disponibili per la parte intera di xL, yL) - // clipping - if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) - return; + TRectD boundingBoxD = TRectD(convert(dn->getSize())) * + (aff * TRectD(0, 0, up->getLx() - 2, up->getLy() - 2)); - // clipping y su dn - int yMin = std::max(tfloor(boundingBoxD.y0), 0); + // clipping + if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) + return; - // clipping y su dn - int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); - - // clipping x su dn - int xMin = std::max(tfloor(boundingBoxD.x0), 0); - - // clipping x su dn - int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); - - TAffine invAff = inv(aff); // inversa di aff - - // nel disegnare la y-esima scanline di dn, il passaggio al pixel - // successivo comporta l'incremento (deltaXD, deltaYD) delle coordinate - // del pixel corrispondente di up - double deltaXD = invAff.a11; - double deltaYD = invAff.a21; - - // deltaXD "TLonghizzato" (round) - int deltaXL = tround(deltaXD * (1 << PADN)); - - // deltaYD "TLonghizzato" (round) - int deltaYL = tround(deltaYD * (1 << PADN)); - - // se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un - // segmento (o un punto) - if ((deltaXL == 0) && (deltaYL == 0)) - return; - - // naturale predecessore di up->getLx() - 1 - int lxPred = (up->getLx() - 2) * (1 << PADN); - - // naturale predecessore di up->getLy() - 1 - int lyPred = (up->getLy() - 2) * (1 << PADN); - - int dnWrap = dn->getWrap(); - int upWrap = up->getWrap(); - dn->lock(); - up->lock(); - - TPixel32 *dnRow = dn->pixels(yMin); - TPixel32 *upBasePix = up->pixels(); - - long c1; - long c2; - - long c3; - long c4; - - long c5; - long c6; - - long s_rg; - long s_br; - long s_gb; - - UINT32 rColDownTmp; - UINT32 gColDownTmp; - UINT32 bColDownTmp; - - UINT32 rColUpTmp; - UINT32 gColUpTmp; - UINT32 bColUpTmp; - - unsigned char rCol; - unsigned char gCol; - unsigned char bCol; - - int xI; - int yI; - - int xWeight1; - int xWeight0; - int yWeight1; - int yWeight0; - - TPixel32 *upPix00; - TPixel32 *upPix10; - TPixel32 *upPix01; - TPixel32 *upPix11; - - TPointD a; - int xL0; - int yL0; - int kMinX; - int kMaxX; - int kMinY; - int kMaxY; - - int kMin; - int kMax; - TPixel32 *dnPix; - TPixel32 *dnEndPix; - int xL; - int yL; - - int y = yMin; - ++yMax; - // scorre le scanline di boundingBoxD - for (; y < yMax - 32; ++y, dnRow += dnWrap) { - EXTERNAL_LOOP_THE_FIRST_X_32 - } - for (; y < yMax - 16; ++y, dnRow += dnWrap) { - EXTERNAL_LOOP_THE_FIRST_X_16 - } - for (; y < yMax - 8; ++y, dnRow += dnWrap) { - EXTERNAL_LOOP_THE_FIRST_X_8 - } - for (; y < yMax - 4; ++y, dnRow += dnWrap) { - EXTERNAL_LOOP_THE_FIRST_X_4 - } - for (; y < yMax - 2; ++y, dnRow += dnWrap) { - EXTERNAL_LOOP_THE_FIRST_X_2 - } - for (; y < yMax; ++y, dnRow += dnWrap) { - EXTERNAL_LOOP_THE_FIRST - } - dn->unlock(); - up->unlock(); + // clipping y su dn + int yMin = std::max(tfloor(boundingBoxD.y0), 0); + + // clipping y su dn + int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); + + // clipping x su dn + int xMin = std::max(tfloor(boundingBoxD.x0), 0); + + // clipping x su dn + int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); + + TAffine invAff = inv(aff); // inversa di aff + + // nel disegnare la y-esima scanline di dn, il passaggio al pixel + // successivo comporta l'incremento (deltaXD, deltaYD) delle coordinate + // del pixel corrispondente di up + double deltaXD = invAff.a11; + double deltaYD = invAff.a21; + + // deltaXD "TLonghizzato" (round) + int deltaXL = tround(deltaXD * (1 << PADN)); + + // deltaYD "TLonghizzato" (round) + int deltaYL = tround(deltaYD * (1 << PADN)); + + // se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' un + // segmento (o un punto) + if ((deltaXL == 0) && (deltaYL == 0)) return; + + // naturale predecessore di up->getLx() - 1 + int lxPred = (up->getLx() - 2) * (1 << PADN); + + // naturale predecessore di up->getLy() - 1 + int lyPred = (up->getLy() - 2) * (1 << PADN); + + int dnWrap = dn->getWrap(); + int upWrap = up->getWrap(); + dn->lock(); + up->lock(); + + TPixel32 *dnRow = dn->pixels(yMin); + TPixel32 *upBasePix = up->pixels(); + + long c1; + long c2; + + long c3; + long c4; + + long c5; + long c6; + + long s_rg; + long s_br; + long s_gb; + + UINT32 rColDownTmp; + UINT32 gColDownTmp; + UINT32 bColDownTmp; + + UINT32 rColUpTmp; + UINT32 gColUpTmp; + UINT32 bColUpTmp; + + unsigned char rCol; + unsigned char gCol; + unsigned char bCol; + + int xI; + int yI; + + int xWeight1; + int xWeight0; + int yWeight1; + int yWeight0; + + TPixel32 *upPix00; + TPixel32 *upPix10; + TPixel32 *upPix01; + TPixel32 *upPix11; + + TPointD a; + int xL0; + int yL0; + int kMinX; + int kMaxX; + int kMinY; + int kMaxY; + + int kMin; + int kMax; + TPixel32 *dnPix; + TPixel32 *dnEndPix; + int xL; + int yL; + + int y = yMin; + ++yMax; + // scorre le scanline di boundingBoxD + for (; y < yMax - 32; ++y, dnRow += dnWrap) { + EXTERNAL_LOOP_THE_FIRST_X_32 + } + for (; y < yMax - 16; ++y, dnRow += dnWrap) { + EXTERNAL_LOOP_THE_FIRST_X_16 + } + for (; y < yMax - 8; ++y, dnRow += dnWrap) { + EXTERNAL_LOOP_THE_FIRST_X_8 + } + for (; y < yMax - 4; ++y, dnRow += dnWrap) { + EXTERNAL_LOOP_THE_FIRST_X_4 + } + for (; y < yMax - 2; ++y, dnRow += dnWrap) { + EXTERNAL_LOOP_THE_FIRST_X_2 + } + for (; y < yMax; ++y, dnRow += dnWrap) { + EXTERNAL_LOOP_THE_FIRST + } + dn->unlock(); + up->unlock(); } #endif @@ -4035,244 +3938,242 @@ void doQuickResampleFilter_optimized( #ifdef OPTIMIZE_FOR_LP64 -void doQuickResampleFilter_optimized( - const TRaster32P &dn, - const TRaster32P &up, - double sx, double sy, - double tx, double ty) -{ - // se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine - // di up e' un segmento (o un punto) - if ((sx == 0) || (sy == 0)) - return; +void doQuickResampleFilter_optimized(const TRaster32P &dn, const TRaster32P &up, + double sx, double sy, double tx, + double ty) { + // se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine + // di up e' un segmento (o un punto) + if ((sx == 0) || (sy == 0)) return; - // contatore bit di shift - const int PADN = 16; + // contatore bit di shift + const int PADN = 16; - // maschera del filtro bilineare - const int MASKN = (1 << PADN) - 1; + // maschera del filtro bilineare + const int MASKN = (1 << PADN) - 1; - // max dimensioni di up gestibili (limite imposto dal numero di bit - // disponibili per la parte intera di xL, yL) - assert(std::max(up->getLx(), up->getLy()) < (1 << (8 * sizeof(int) - PADN - 1))); + // max dimensioni di up gestibili (limite imposto dal numero di bit + // disponibili per la parte intera di xL, yL) + assert(std::max(up->getLx(), up->getLy()) < + (1 << (8 * sizeof(int) - PADN - 1))); - TAffine aff(sx, 0, tx, 0, sy, ty); - TRectD boundingBoxD = TRectD(convert(dn->getSize())) * - (aff * TRectD(0, 0, up->getLx() - 2, up->getLy() - 2)); - - // clipping - if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) - return; - - // clipping y su dn - int yMin = std::max(tfloor(boundingBoxD.y0), 0); - - // clipping y su dn - int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); - - // clipping x su dn - int xMin = std::max(tfloor(boundingBoxD.x0), 0); - - // clipping x su dn - int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); - - // inversa di aff - TAffine invAff = inv(aff); - - // nello scorrere le scanline di boundingBoxD, il passaggio alla scanline - // successiva comporta l'incremento (0, deltaYD) delle coordinate dei - // pixels corrispondenti di up - - // nel disegnare la y-esima scanline di dn, il passaggio al pixel - // successivo comporta l'incremento (deltaXD, 0) delle coordinate del - // pixel corrispondente di up - - double deltaXD = invAff.a11; - double deltaYD = invAff.a22; - int deltaXL = tround(deltaXD * (1 << PADN)); // deltaXD "TLonghizzato" (round) - int deltaYL = tround(deltaYD * (1 << PADN)); // deltaYD "TLonghizzato" (round) - - // se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' - // un segmento (o un punto) - if ((deltaXL == 0) || (deltaYL == 0)) - return; - - // (1) equazione (kX, kY)-parametrica di boundingBoxD: - // (xMin, yMin) + kX*(1, 0) + kY*(0, 1), - // kX = 0, ..., (xMax - xMin), - // kY = 0, ..., (yMax - yMin) - - // (2) equazione (kX, kY)-parametrica dell'immagine mediante invAff di (1): - // invAff*(xMin, yMin) + kX*(deltaXD, 0) + kY*(0, deltaYD), - // kX = kMinX, ..., kMaxX - // con 0 <= kMinX <= kMaxX <= (xMax - xMin) - // - // kY = kMinY, ..., kMaxY - // con 0 <= kMinY <= kMaxY <= (yMax - yMin) - - // calcola kMinX, kMaxX, kMinY, kMaxY intersecando la (2) con i lati di up - - // il segmento [a, b] di up (con gli estremi eventualmente invertiti) e' - // la controimmagine mediante aff della porzione di scanline - // [ (xMin, yMin), (xMax, yMin) ] di dn - - // TPointD b = invAff*TPointD(xMax, yMin); - TPointD a = invAff * TPointD(xMin, yMin); - - // (xL0, yL0) sono le coordinate di a (inizializzate per il round) - // in versione "TLonghizzata" - // 0 <= xL0 + kX*deltaXL <= (up->getLx() - 2)*(1<getLy() - 2)*(1<getLx() - 1) - int lxPred = (up->getLx() - 2) * (1 << PADN); - - // TINT32 predecessore di (up->getLy() - 1) - int lyPred = (up->getLy() - 2) * (1 << PADN); - - // 0 <= xL0 + k*deltaXL <= (up->getLx() - 2)*(1< - // 0 <= xL0 + k*deltaXL <= lxPred - - // 0 <= yL0 + k*deltaYL <= (up->getLy() - 2)*(1< - // 0 <= yL0 + k*deltaYL <= lyPred - - // calcola kMinY, kMaxY intersecando la (2) con i lati - // (y = yMin) e (y = yMax) di up - if (deltaYL > 0) // (deltaYL != 0) - { - // [a, b] interno ad up contratto - assert(yL0 <= lyPred); - - kMaxY = (lyPred - yL0) / deltaYL; // floor - if (yL0 < 0) { - kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil - } - } else // (deltaYL < 0) - { - // [a, b] interno ad up contratto - assert(0 <= yL0); - - kMaxY = yL0 / (-deltaYL); // floor - if (lyPred < yL0) { - kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil - } - } - // calcola kMinY, kMaxY effettuando anche il clippind su dn - kMinY = std::max(kMinY, (int)0); - kMaxY = std::min(kMaxY, yMax - yMin); - - // calcola kMinX, kMaxX intersecando la (2) con i lati - // (x = xMin) e (x = xMax) di up - if (deltaXL > 0) // (deltaXL != 0) - { - // [a, b] interno ad up contratto - assert(xL0 <= lxPred); - - kMaxX = (lxPred - xL0) / deltaXL; // floor - if (xL0 < 0) { - kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil - } - } else // (deltaXL < 0) - { - // [a, b] interno ad up contratto - assert(0 <= xL0); - - kMaxX = xL0 / (-deltaXL); // floor - if (lxPred < xL0) { - kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil - } - } - // calcola kMinX, kMaxX effettuando anche il clippind su dn - kMinX = std::max(kMinX, (int)0); - kMaxX = std::min(kMaxX, xMax - xMin); - - int dnWrap = dn->getWrap(); - int upWrap = up->getWrap(); - dn->lock(); - up->lock(); - - TPixel32 *upBasePix = up->pixels(); - TPixel32 *dnRow = dn->pixels(yMin + kMinY); - - // (xL, yL) sono le coordinate (inizializzate per il round) - // in versione "TLonghizzata" - // del pixel corrente di up - int yL = yL0 + (kMinY - 1) * deltaYL; // inizializza yL - - long c1; - long c2; - - long c3; - long c4; - - long c5; - long c6; - - long s_rg; - long s_br; - long s_gb; - - UINT32 rColDownTmp; - UINT32 gColDownTmp; - UINT32 bColDownTmp; - - UINT32 rColUpTmp; - UINT32 gColUpTmp; - UINT32 bColUpTmp; - - int xI; - TPixel32 *upPix00; - TPixel32 *upPix10; - TPixel32 *upPix01; - TPixel32 *upPix11; - int xWeight1; - int xWeight0; - - unsigned char rCol; - unsigned char gCol; - unsigned char bCol; - - int xL; - int yI; - int yWeight1; - int yWeight0; - TPixel32 *dnPix; - TPixel32 *dnEndPix; - int kY = kMinY; - ++kMaxY; - - // scorre le scanline di boundingBoxD - for (; kY < kMaxY - 32; kY++, dnRow += dnWrap) { - EXTERNAL_LOOP_THE_SECOND_X_32 - } - for (; kY < kMaxY - 16; kY++, dnRow += dnWrap) { - EXTERNAL_LOOP_THE_SECOND_X_16 - } - for (; kY < kMaxY - 8; kY++, dnRow += dnWrap) { - EXTERNAL_LOOP_THE_SECOND_X_8 - } - for (; kY < kMaxY - 4; kY++, dnRow += dnWrap) { - EXTERNAL_LOOP_THE_SECOND_X_4 - } - for (; kY < kMaxY - 2; kY++, dnRow += dnWrap) { - EXTERNAL_LOOP_THE_SECOND_X_2 - } - for (; kY < kMaxY; kY++, dnRow += dnWrap) { - EXTERNAL_LOOP_THE_SECOND - } - dn->unlock(); - up->unlock(); + TAffine aff(sx, 0, tx, 0, sy, ty); + TRectD boundingBoxD = TRectD(convert(dn->getSize())) * + (aff * TRectD(0, 0, up->getLx() - 2, up->getLy() - 2)); + + // clipping + if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) + return; + + // clipping y su dn + int yMin = std::max(tfloor(boundingBoxD.y0), 0); + + // clipping y su dn + int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); + + // clipping x su dn + int xMin = std::max(tfloor(boundingBoxD.x0), 0); + + // clipping x su dn + int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); + + // inversa di aff + TAffine invAff = inv(aff); + + // nello scorrere le scanline di boundingBoxD, il passaggio alla scanline + // successiva comporta l'incremento (0, deltaYD) delle coordinate dei + // pixels corrispondenti di up + + // nel disegnare la y-esima scanline di dn, il passaggio al pixel + // successivo comporta l'incremento (deltaXD, 0) delle coordinate del + // pixel corrispondente di up + + double deltaXD = invAff.a11; + double deltaYD = invAff.a22; + int deltaXL = + tround(deltaXD * (1 << PADN)); // deltaXD "TLonghizzato" (round) + int deltaYL = + tround(deltaYD * (1 << PADN)); // deltaYD "TLonghizzato" (round) + + // se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' + // un segmento (o un punto) + if ((deltaXL == 0) || (deltaYL == 0)) return; + + // (1) equazione (kX, kY)-parametrica di boundingBoxD: + // (xMin, yMin) + kX*(1, 0) + kY*(0, 1), + // kX = 0, ..., (xMax - xMin), + // kY = 0, ..., (yMax - yMin) + + // (2) equazione (kX, kY)-parametrica dell'immagine mediante invAff di (1): + // invAff*(xMin, yMin) + kX*(deltaXD, 0) + kY*(0, deltaYD), + // kX = kMinX, ..., kMaxX + // con 0 <= kMinX <= kMaxX <= (xMax - xMin) + // + // kY = kMinY, ..., kMaxY + // con 0 <= kMinY <= kMaxY <= (yMax - yMin) + + // calcola kMinX, kMaxX, kMinY, kMaxY intersecando la (2) con i lati di up + + // il segmento [a, b] di up (con gli estremi eventualmente invertiti) e' + // la controimmagine mediante aff della porzione di scanline + // [ (xMin, yMin), (xMax, yMin) ] di dn + + // TPointD b = invAff*TPointD(xMax, yMin); + TPointD a = invAff * TPointD(xMin, yMin); + + // (xL0, yL0) sono le coordinate di a (inizializzate per il round) + // in versione "TLonghizzata" + // 0 <= xL0 + kX*deltaXL <= (up->getLx() - 2)*(1<getLy() - 2)*(1<getLx() - 1) + int lxPred = (up->getLx() - 2) * (1 << PADN); + + // TINT32 predecessore di (up->getLy() - 1) + int lyPred = (up->getLy() - 2) * (1 << PADN); + + // 0 <= xL0 + k*deltaXL <= (up->getLx() - 2)*(1< + // 0 <= xL0 + k*deltaXL <= lxPred + + // 0 <= yL0 + k*deltaYL <= (up->getLy() - 2)*(1< + // 0 <= yL0 + k*deltaYL <= lyPred + + // calcola kMinY, kMaxY intersecando la (2) con i lati + // (y = yMin) e (y = yMax) di up + if (deltaYL > 0) // (deltaYL != 0) + { + // [a, b] interno ad up contratto + assert(yL0 <= lyPred); + + kMaxY = (lyPred - yL0) / deltaYL; // floor + if (yL0 < 0) { + kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil + } + } else // (deltaYL < 0) + { + // [a, b] interno ad up contratto + assert(0 <= yL0); + + kMaxY = yL0 / (-deltaYL); // floor + if (lyPred < yL0) { + kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil + } + } + // calcola kMinY, kMaxY effettuando anche il clippind su dn + kMinY = std::max(kMinY, (int)0); + kMaxY = std::min(kMaxY, yMax - yMin); + + // calcola kMinX, kMaxX intersecando la (2) con i lati + // (x = xMin) e (x = xMax) di up + if (deltaXL > 0) // (deltaXL != 0) + { + // [a, b] interno ad up contratto + assert(xL0 <= lxPred); + + kMaxX = (lxPred - xL0) / deltaXL; // floor + if (xL0 < 0) { + kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil + } + } else // (deltaXL < 0) + { + // [a, b] interno ad up contratto + assert(0 <= xL0); + + kMaxX = xL0 / (-deltaXL); // floor + if (lxPred < xL0) { + kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil + } + } + // calcola kMinX, kMaxX effettuando anche il clippind su dn + kMinX = std::max(kMinX, (int)0); + kMaxX = std::min(kMaxX, xMax - xMin); + + int dnWrap = dn->getWrap(); + int upWrap = up->getWrap(); + dn->lock(); + up->lock(); + + TPixel32 *upBasePix = up->pixels(); + TPixel32 *dnRow = dn->pixels(yMin + kMinY); + + // (xL, yL) sono le coordinate (inizializzate per il round) + // in versione "TLonghizzata" + // del pixel corrente di up + int yL = yL0 + (kMinY - 1) * deltaYL; // inizializza yL + + long c1; + long c2; + + long c3; + long c4; + + long c5; + long c6; + + long s_rg; + long s_br; + long s_gb; + + UINT32 rColDownTmp; + UINT32 gColDownTmp; + UINT32 bColDownTmp; + + UINT32 rColUpTmp; + UINT32 gColUpTmp; + UINT32 bColUpTmp; + + int xI; + TPixel32 *upPix00; + TPixel32 *upPix10; + TPixel32 *upPix01; + TPixel32 *upPix11; + int xWeight1; + int xWeight0; + + unsigned char rCol; + unsigned char gCol; + unsigned char bCol; + + int xL; + int yI; + int yWeight1; + int yWeight0; + TPixel32 *dnPix; + TPixel32 *dnEndPix; + int kY = kMinY; + ++kMaxY; + + // scorre le scanline di boundingBoxD + for (; kY < kMaxY - 32; kY++, dnRow += dnWrap) { + EXTERNAL_LOOP_THE_SECOND_X_32 + } + for (; kY < kMaxY - 16; kY++, dnRow += dnWrap) { + EXTERNAL_LOOP_THE_SECOND_X_16 + } + for (; kY < kMaxY - 8; kY++, dnRow += dnWrap) { + EXTERNAL_LOOP_THE_SECOND_X_8 + } + for (; kY < kMaxY - 4; kY++, dnRow += dnWrap) { + EXTERNAL_LOOP_THE_SECOND_X_4 + } + for (; kY < kMaxY - 2; kY++, dnRow += dnWrap) { + EXTERNAL_LOOP_THE_SECOND_X_2 + } + for (; kY < kMaxY; kY++, dnRow += dnWrap) { + EXTERNAL_LOOP_THE_SECOND + } + dn->unlock(); + up->unlock(); } #endif @@ -4286,18 +4187,18 @@ void doQuickResampleFilter_optimized( // //============================================================================= -void TRop::quickPut(const TRasterP &dn, - const TRasterCM32P &upCM32, const TPaletteP &plt, - const TAffine &aff, const TPixel32 &globalColorScale, bool inksOnly) -{ - TRaster32P dn32 = dn; - if (dn32 && upCM32) - if (areAlmostEqual(aff.a12, 0) && areAlmostEqual(aff.a21, 0)) - doQuickPutCmapped(dn32, upCM32, plt, aff.a11, aff.a22, aff.a13, aff.a23, globalColorScale, inksOnly); - else - doQuickPutCmapped(dn32, upCM32, plt, aff, globalColorScale, inksOnly); - else - throw TRopException("raster type mismatch"); +void TRop::quickPut(const TRasterP &dn, const TRasterCM32P &upCM32, + const TPaletteP &plt, const TAffine &aff, + const TPixel32 &globalColorScale, bool inksOnly) { + TRaster32P dn32 = dn; + if (dn32 && upCM32) + if (areAlmostEqual(aff.a12, 0) && areAlmostEqual(aff.a21, 0)) + doQuickPutCmapped(dn32, upCM32, plt, aff.a11, aff.a22, aff.a13, aff.a23, + globalColorScale, inksOnly); + else + doQuickPutCmapped(dn32, upCM32, plt, aff, globalColorScale, inksOnly); + else + throw TRopException("raster type mismatch"); } //============================================================================= @@ -4306,42 +4207,46 @@ void TRop::quickPut(const TRasterP &dn, // //============================================================================= -void TRop::quickPut(const TRasterP &dn, - const TRasterCM32P &upCM32, const TPaletteP &plt, const TAffine &aff, - const CmappedQuickputSettings &settings) //const TPixel32& globalColorScale, bool inksOnly, bool transparencyCheck, bool blackBgCheck, int inkIndex, int paintIndex) +void TRop::quickPut( + const TRasterP &dn, const TRasterCM32P &upCM32, const TPaletteP &plt, + const TAffine &aff, + const CmappedQuickputSettings &settings) // const TPixel32& + // globalColorScale, bool + // inksOnly, bool + // transparencyCheck, bool + // blackBgCheck, int inkIndex, int + // paintIndex) { - TRaster32P dn32 = dn; - if (dn32 && upCM32) - doQuickPutCmapped(dn32, upCM32, plt, aff, settings); //globalColorScale, inksOnly, transparencyCheck, blackBgCheck, inkIndex, paintIndex); - else - throw TRopException("raster type mismatch"); + TRaster32P dn32 = dn; + if (dn32 && upCM32) + doQuickPutCmapped(dn32, upCM32, plt, aff, + settings); // globalColorScale, inksOnly, + // transparencyCheck, blackBgCheck, inkIndex, + // paintIndex); + else + throw TRopException("raster type mismatch"); } -void TRop::quickResampleColorFilter( - const TRasterP &dn, - const TRasterP &up, - const TAffine &aff, - const TPaletteP &plt, - UCHAR colorMask) -{ - - TRaster32P dn32 = dn; - TRaster32P up32 = up; - TRaster64P up64 = up; - TRasterCM32P upCM32 = up; - if (dn32 && up32) - doQuickResampleColorFilter(dn32, up32, aff, colorMask); - else if (dn32 && upCM32) - doQuickResampleColorFilter(dn32, upCM32, plt, aff, colorMask); - else if (dn32 && up64) - doQuickResampleColorFilter(dn32, up64, aff, colorMask); - //else if (dn32 && upCM32) - // doQuickResampleColorFilter(dn32, upCM32, aff, plt, colorMask); - else - throw TRopException("raster type mismatch"); +void TRop::quickResampleColorFilter(const TRasterP &dn, const TRasterP &up, + const TAffine &aff, const TPaletteP &plt, + UCHAR colorMask) { + TRaster32P dn32 = dn; + TRaster32P up32 = up; + TRaster64P up64 = up; + TRasterCM32P upCM32 = up; + if (dn32 && up32) + doQuickResampleColorFilter(dn32, up32, aff, colorMask); + else if (dn32 && upCM32) + doQuickResampleColorFilter(dn32, upCM32, plt, aff, colorMask); + else if (dn32 && up64) + doQuickResampleColorFilter(dn32, up64, aff, colorMask); + // else if (dn32 && upCM32) + // doQuickResampleColorFilter(dn32, upCM32, aff, plt, colorMask); + else + throw TRopException("raster type mismatch"); } -#endif //TNZCORE_LIGHT +#endif // TNZCORE_LIGHT //============================================================================= //============================================================================= @@ -4350,337 +4255,322 @@ void TRop::quickResampleColorFilter( // //============================================================================= -void quickPut( - const TRasterP &dn, - const TRasterP &up, - const TAffine &aff, - TRop::ResampleFilterType filterType, - const TPixel32 &colorScale, - bool doPremultiply, bool whiteTransp, bool firstColumn, - bool doRasterDarkenBlendedView) -{ - assert(filterType == TRop::Bilinear || - filterType == TRop::ClosestPixel); - - bool bilinear = filterType == TRop::Bilinear; - - TRaster32P dn32 = dn; - TRaster32P up32 = up; - TRasterGR8P dn8 = dn; - TRasterGR8P up8 = up; - TRaster64P up64 = up; - - if (up8 && dn32) { - assert(filterType == TRop::ClosestPixel); - if (areAlmostEqual(aff.a12, 0) && areAlmostEqual(aff.a21, 0)) - doQuickPutNoFilter(dn32, up8, aff.a11, aff.a22, aff.a13, aff.a23, colorScale); - else - doQuickPutNoFilter(dn32, up8, aff, colorScale); - } else if (dn32 && up32) { - if (areAlmostEqual(aff.a12, 0) && areAlmostEqual(aff.a21, 0)) - if (bilinear) - doQuickPutFilter(dn32, up32, aff.a11, aff.a22, aff.a13, aff.a23); - else - doQuickPutNoFilter(dn32, up32, aff.a11, aff.a22, aff.a13, aff.a23, colorScale, doPremultiply, whiteTransp, firstColumn, doRasterDarkenBlendedView); - else if (bilinear) - doQuickPutFilter(dn32, up32, aff); - else - doQuickPutNoFilter(dn32, up32, aff, colorScale, doPremultiply, whiteTransp, firstColumn, doRasterDarkenBlendedView); - } else if (dn32 && up64) - doQuickPutNoFilter(dn32, up64, aff, doPremultiply, firstColumn); - else - throw TRopException("raster type mismatch"); +void quickPut(const TRasterP &dn, const TRasterP &up, const TAffine &aff, + TRop::ResampleFilterType filterType, const TPixel32 &colorScale, + bool doPremultiply, bool whiteTransp, bool firstColumn, + bool doRasterDarkenBlendedView) { + assert(filterType == TRop::Bilinear || filterType == TRop::ClosestPixel); + + bool bilinear = filterType == TRop::Bilinear; + + TRaster32P dn32 = dn; + TRaster32P up32 = up; + TRasterGR8P dn8 = dn; + TRasterGR8P up8 = up; + TRaster64P up64 = up; + + if (up8 && dn32) { + assert(filterType == TRop::ClosestPixel); + if (areAlmostEqual(aff.a12, 0) && areAlmostEqual(aff.a21, 0)) + doQuickPutNoFilter(dn32, up8, aff.a11, aff.a22, aff.a13, aff.a23, + colorScale); + else + doQuickPutNoFilter(dn32, up8, aff, colorScale); + } else if (dn32 && up32) { + if (areAlmostEqual(aff.a12, 0) && areAlmostEqual(aff.a21, 0)) + if (bilinear) + doQuickPutFilter(dn32, up32, aff.a11, aff.a22, aff.a13, aff.a23); + else + doQuickPutNoFilter(dn32, up32, aff.a11, aff.a22, aff.a13, aff.a23, + colorScale, doPremultiply, whiteTransp, firstColumn, + doRasterDarkenBlendedView); + else if (bilinear) + doQuickPutFilter(dn32, up32, aff); + else + doQuickPutNoFilter(dn32, up32, aff, colorScale, doPremultiply, + whiteTransp, firstColumn, doRasterDarkenBlendedView); + } else if (dn32 && up64) + doQuickPutNoFilter(dn32, up64, aff, doPremultiply, firstColumn); + else + throw TRopException("raster type mismatch"); } //============================================================================= template -void doQuickResampleNoFilter( - const TRasterPT &dn, - const TRasterPT &up, - const TAffine &aff) -{ - // se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine - // di up e' un segmento (o un punto) - if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) - return; - - // contatore bit di shift - const int PADN = 16; - - // max dimensioni di up gestibili (limite imposto dal numero di bit - // disponibili per la parte intera di xL, yL) - assert(std::max(up->getLx(), up->getLy()) < (1 << (8 * sizeof(int) - PADN - 1))); - - TRectD boundingBoxD = TRectD(convert(dn->getBounds())) * - (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5)); - // clipping - if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) - return; - - int yMin = std::max(tfloor(boundingBoxD.y0), 0); // clipping y su dn - int yMax = std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); // clipping y su dn - int xMin = std::max(tfloor(boundingBoxD.x0), 0); // clipping x su dn - int xMax = std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); // clipping x su dn - - TAffine invAff = inv(aff); // inversa di aff - - // nel disegnare la y-esima scanline di dn, il passaggio al pixel - // successivo comporta l'incremento (deltaXD, deltaYD) delle coordinate - // del pixel corrispondente di up - double deltaXD = invAff.a11; - double deltaYD = invAff.a21; - int deltaXL = tround(deltaXD * (1 << PADN)); // deltaXD "TLonghizzato" (round) - int deltaYL = tround(deltaYD * (1 << PADN)); // deltaYD "TLonghizzato" (round) - - // se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' - // un segmento (o un punto) - if ((deltaXL == 0) && (deltaYL == 0)) - return; - - int lxPred = up->getLx() * (1 << PADN) - 1; // TINT32 predecessore di up->getLx() - int lyPred = up->getLy() * (1 << PADN) - 1; // TINT32 predecessore di up->getLy() - - int dnWrap = dn->getWrap(); - int upWrap = up->getWrap(); - dn->lock(); - up->lock(); - - PIX *dnRow = dn->pixels(yMin); - PIX *upBasePix = up->pixels(); - - // scorre le scanline di boundingBoxD - for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) { - // (1) equazione k-parametrica della y-esima scanline di boundingBoxD: - // (xMin, y) + k*(1, 0), - // k = 0, ..., (xMax - xMin) - - // (2) equazione k-parametrica dell'immagine mediante invAff di (1): - // invAff*(xMin, y) + k*(deltaXD, deltaYD), - // k = kMin, ..., kMax - // con 0 <= kMin <= kMax <= (xMax - xMin) - - // calcola kMin, kMax per la scanline corrente intersecando - // la (2) con i lati di up - - // il segmento [a, b] di up e' la controimmagine mediante aff della - // porzione di scanline [ (xMin, y), (xMax, y) ] di dn - - // TPointD b = invAff*TPointD(xMax, y); - TPointD a = invAff * TPointD(xMin, y); - - // (xL0, yL0) sono le coordinate di a (inizializzate per il round) - // in versione "TLonghizzata" - // 0 <= xL0 + k*deltaXL < up->getLx()*(1<getLy()*(1<getLx()*(1< - // 0 <= xL0 + k*eltaXL <= lxPred - - // 0 <= yL0 + k*deltaYL < up->getLy()*(1< - // 0 <= yL0 + k*deltaYL <= lyPred - - // calcola kMinX, kMaxX - if (deltaXL == 0) { - // [a, b] verticale esterno ad up+(bordo destro/basso) - if ((xL0 < 0) || (lxPred < xL0)) - continue; - // altrimenti usa solo - // kMinY, kMaxY ((deltaXL != 0) || (deltaYL != 0)) - } else if (deltaXL > 0) { - // [a, b] esterno ad up+(bordo destro/basso) - if (lxPred < xL0) - continue; - - kMaxX = (lxPred - xL0) / deltaXL; // floor - if (xL0 < 0) { - kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil - } - } else // (deltaXL < 0) - { - // [a, b] esterno ad up+(bordo destro/basso) - if (xL0 < 0) - continue; - - kMaxX = xL0 / (-deltaXL); // floor - if (lxPred < xL0) { - kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil - } - } - - // calcola kMinY, kMaxY - if (deltaYL == 0) { - // [a, b] orizzontale esterno ad up+(bordo destro/basso) - if ((yL0 < 0) || (lyPred < yL0)) - continue; - // altrimenti usa solo - // kMinX, kMaxX ((deltaXL != 0) || (deltaYL != 0)) - } else if (deltaYL > 0) { - // [a, b] esterno ad up+(bordo destro/basso) - if (lyPred < yL0) - continue; - - kMaxY = (lyPred - yL0) / deltaYL; // floor - if (yL0 < 0) { - kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil - } - } else // (deltaYL < 0) - { - // [a, b] esterno ad up+(bordo destro/basso) - if (yL0 < 0) - continue; - - kMaxY = yL0 / (-deltaYL); // floor - if (lyPred < yL0) { - kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil - } - } - - // calcola kMin, kMax effettuando anche il clippind su dn - int kMin = std::max({kMinX, kMinY, (int)0}); - int kMax = std::min({kMaxX, kMaxY, xMax - xMin}); - - PIX *dnPix = dnRow + xMin + kMin; - PIX *dnEndPix = dnRow + xMin + kMax + 1; - - // (xL, yL) sono le coordinate (inizializzate per il round) - // in versione "TLonghizzata" del pixel corrente di up - int xL = xL0 + (kMin - 1) * deltaXL; // inizializza xL - int yL = yL0 + (kMin - 1) * deltaYL; // inizializza yL - - // scorre i pixel sulla y-esima scanline di boundingBoxD - for (; dnPix < dnEndPix; ++dnPix) { - xL += deltaXL; - yL += deltaYL; - // il punto di up TPointD(xL/(1<> PADN; // round - int yI = yL >> PADN; // round - - assert((0 <= xI) && (xI <= up->getLx() - 1) && - (0 <= yI) && (yI <= up->getLy() - 1)); - - *dnPix = *(upBasePix + (yI * upWrap + xI)); - } - } - dn->unlock(); - up->unlock(); +void doQuickResampleNoFilter(const TRasterPT &dn, const TRasterPT &up, + const TAffine &aff) { + // se aff := TAffine(sx, 0, tx, 0, sy, ty) e' degenere la controimmagine + // di up e' un segmento (o un punto) + if ((aff.a11 * aff.a22 - aff.a12 * aff.a21) == 0) return; + + // contatore bit di shift + const int PADN = 16; + + // max dimensioni di up gestibili (limite imposto dal numero di bit + // disponibili per la parte intera di xL, yL) + assert(std::max(up->getLx(), up->getLy()) < + (1 << (8 * sizeof(int) - PADN - 1))); + + TRectD boundingBoxD = + TRectD(convert(dn->getBounds())) * + (aff * TRectD(-0.5, -0.5, up->getLx() - 0.5, up->getLy() - 0.5)); + // clipping + if (boundingBoxD.x0 >= boundingBoxD.x1 || boundingBoxD.y0 >= boundingBoxD.y1) + return; + + int yMin = std::max(tfloor(boundingBoxD.y0), 0); // clipping y su dn + int yMax = + std::min(tceil(boundingBoxD.y1), dn->getLy() - 1); // clipping y su dn + int xMin = std::max(tfloor(boundingBoxD.x0), 0); // clipping x su dn + int xMax = + std::min(tceil(boundingBoxD.x1), dn->getLx() - 1); // clipping x su dn + + TAffine invAff = inv(aff); // inversa di aff + + // nel disegnare la y-esima scanline di dn, il passaggio al pixel + // successivo comporta l'incremento (deltaXD, deltaYD) delle coordinate + // del pixel corrispondente di up + double deltaXD = invAff.a11; + double deltaYD = invAff.a21; + int deltaXL = + tround(deltaXD * (1 << PADN)); // deltaXD "TLonghizzato" (round) + int deltaYL = + tround(deltaYD * (1 << PADN)); // deltaYD "TLonghizzato" (round) + + // se aff "TLonghizzata" (round) e' degenere la controimmagine di up e' + // un segmento (o un punto) + if ((deltaXL == 0) && (deltaYL == 0)) return; + + int lxPred = + up->getLx() * (1 << PADN) - 1; // TINT32 predecessore di up->getLx() + int lyPred = + up->getLy() * (1 << PADN) - 1; // TINT32 predecessore di up->getLy() + + int dnWrap = dn->getWrap(); + int upWrap = up->getWrap(); + dn->lock(); + up->lock(); + + PIX *dnRow = dn->pixels(yMin); + PIX *upBasePix = up->pixels(); + + // scorre le scanline di boundingBoxD + for (int y = yMin; y <= yMax; y++, dnRow += dnWrap) { + // (1) equazione k-parametrica della y-esima scanline di boundingBoxD: + // (xMin, y) + k*(1, 0), + // k = 0, ..., (xMax - xMin) + + // (2) equazione k-parametrica dell'immagine mediante invAff di (1): + // invAff*(xMin, y) + k*(deltaXD, deltaYD), + // k = kMin, ..., kMax + // con 0 <= kMin <= kMax <= (xMax - xMin) + + // calcola kMin, kMax per la scanline corrente intersecando + // la (2) con i lati di up + + // il segmento [a, b] di up e' la controimmagine mediante aff della + // porzione di scanline [ (xMin, y), (xMax, y) ] di dn + + // TPointD b = invAff*TPointD(xMax, y); + TPointD a = invAff * TPointD(xMin, y); + + // (xL0, yL0) sono le coordinate di a (inizializzate per il round) + // in versione "TLonghizzata" + // 0 <= xL0 + k*deltaXL < up->getLx()*(1<getLy()*(1<getLx()*(1< + // 0 <= xL0 + k*eltaXL <= lxPred + + // 0 <= yL0 + k*deltaYL < up->getLy()*(1< + // 0 <= yL0 + k*deltaYL <= lyPred + + // calcola kMinX, kMaxX + if (deltaXL == 0) { + // [a, b] verticale esterno ad up+(bordo destro/basso) + if ((xL0 < 0) || (lxPred < xL0)) continue; + // altrimenti usa solo + // kMinY, kMaxY ((deltaXL != 0) || (deltaYL != 0)) + } else if (deltaXL > 0) { + // [a, b] esterno ad up+(bordo destro/basso) + if (lxPred < xL0) continue; + + kMaxX = (lxPred - xL0) / deltaXL; // floor + if (xL0 < 0) { + kMinX = ((-xL0) + deltaXL - 1) / deltaXL; // ceil + } + } else // (deltaXL < 0) + { + // [a, b] esterno ad up+(bordo destro/basso) + if (xL0 < 0) continue; + + kMaxX = xL0 / (-deltaXL); // floor + if (lxPred < xL0) { + kMinX = (xL0 - lxPred - deltaXL - 1) / (-deltaXL); // ceil + } + } + + // calcola kMinY, kMaxY + if (deltaYL == 0) { + // [a, b] orizzontale esterno ad up+(bordo destro/basso) + if ((yL0 < 0) || (lyPred < yL0)) continue; + // altrimenti usa solo + // kMinX, kMaxX ((deltaXL != 0) || (deltaYL != 0)) + } else if (deltaYL > 0) { + // [a, b] esterno ad up+(bordo destro/basso) + if (lyPred < yL0) continue; + + kMaxY = (lyPred - yL0) / deltaYL; // floor + if (yL0 < 0) { + kMinY = ((-yL0) + deltaYL - 1) / deltaYL; // ceil + } + } else // (deltaYL < 0) + { + // [a, b] esterno ad up+(bordo destro/basso) + if (yL0 < 0) continue; + + kMaxY = yL0 / (-deltaYL); // floor + if (lyPred < yL0) { + kMinY = (yL0 - lyPred - deltaYL - 1) / (-deltaYL); // ceil + } + } + + // calcola kMin, kMax effettuando anche il clippind su dn + int kMin = std::max({kMinX, kMinY, (int)0}); + int kMax = std::min({kMaxX, kMaxY, xMax - xMin}); + + PIX *dnPix = dnRow + xMin + kMin; + PIX *dnEndPix = dnRow + xMin + kMax + 1; + + // (xL, yL) sono le coordinate (inizializzate per il round) + // in versione "TLonghizzata" del pixel corrente di up + int xL = xL0 + (kMin - 1) * deltaXL; // inizializza xL + int yL = yL0 + (kMin - 1) * deltaYL; // inizializza yL + + // scorre i pixel sulla y-esima scanline di boundingBoxD + for (; dnPix < dnEndPix; ++dnPix) { + xL += deltaXL; + yL += deltaYL; + // il punto di up TPointD(xL/(1<> PADN; // round + int yI = yL >> PADN; // round + + assert((0 <= xI) && (xI <= up->getLx() - 1) && (0 <= yI) && + (yI <= up->getLy() - 1)); + + *dnPix = *(upBasePix + (yI * upWrap + xI)); + } + } + dn->unlock(); + up->unlock(); } //============================================================================= #ifdef OPTIMIZE_FOR_LP64 -void quickResample_optimized( - const TRasterP &dn, - const TRasterP &up, - const TAffine &aff, - TRop::ResampleFilterType filterType) -{ - assert(filterType == TRop::Bilinear || - filterType == TRop::ClosestPixel); - - bool bilinear = filterType == TRop::Bilinear; - - TRaster32P dn32 = dn; - TRaster32P up32 = up; - TRasterGR8P dn8 = dn; - TRasterGR8P up8 = up; - if (dn32 && up32) - if (areAlmostEqual(aff.a12, 0) && areAlmostEqual(aff.a21, 0)) - if (bilinear) - doQuickResampleFilter_optimized(dn32, up32, - aff.a11, aff.a22, aff.a13, aff.a23); - else - doQuickResampleNoFilter(dn32, up32, aff.a11, aff.a22, aff.a13, - aff.a23); - else if (bilinear) - doQuickResampleFilter_optimized(dn32, up32, aff); - else - doQuickResampleNoFilter(dn32, up32, aff); - else - throw TRopException("raster type mismatch"); +void quickResample_optimized(const TRasterP &dn, const TRasterP &up, + const TAffine &aff, + TRop::ResampleFilterType filterType) { + assert(filterType == TRop::Bilinear || filterType == TRop::ClosestPixel); + + bool bilinear = filterType == TRop::Bilinear; + + TRaster32P dn32 = dn; + TRaster32P up32 = up; + TRasterGR8P dn8 = dn; + TRasterGR8P up8 = up; + if (dn32 && up32) + if (areAlmostEqual(aff.a12, 0) && areAlmostEqual(aff.a21, 0)) + if (bilinear) + doQuickResampleFilter_optimized(dn32, up32, aff.a11, aff.a22, aff.a13, + aff.a23); + else + doQuickResampleNoFilter(dn32, up32, aff.a11, aff.a22, aff.a13, aff.a23); + else if (bilinear) + doQuickResampleFilter_optimized(dn32, up32, aff); + else + doQuickResampleNoFilter(dn32, up32, aff); + else + throw TRopException("raster type mismatch"); } #endif //============================================================================= -void quickResample( - const TRasterP &dn, - const TRasterP &up, - const TAffine &aff, - TRop::ResampleFilterType filterType) -{ - +void quickResample(const TRasterP &dn, const TRasterP &up, const TAffine &aff, + TRop::ResampleFilterType filterType) { #ifdef OPTIMIZE_FOR_LP64 - quickResample_optimized(dn, up, aff, filterType); + quickResample_optimized(dn, up, aff, filterType); #else - assert(filterType == TRop::Bilinear || - filterType == TRop::ClosestPixel); - - bool bilinear = filterType == TRop::Bilinear; - - TRaster32P dn32 = dn; - TRaster32P up32 = up; - TRasterCM32P dnCM32 = dn; - TRasterCM32P upCM32 = up; - TRasterGR8P dn8 = dn; - TRasterGR8P up8 = up; - dn->clear(); - - if (bilinear) { - if (dn32 && up32) { - if (areAlmostEqual(aff.a12, 0) && areAlmostEqual(aff.a21, 0)) - doQuickResampleFilter(dn32, up32, aff.a11, aff.a22, aff.a13, aff.a23); - else - doQuickResampleFilter(dn32, up32, aff); - } else if (dn32 && up8) { - if (areAlmostEqual(aff.a12, 0) && areAlmostEqual(aff.a21, 0)) - doQuickResampleFilter(dn32, up8, aff.a11, aff.a22, aff.a13, aff.a23); - else - doQuickResampleFilter(dn32, up8, aff); - } else - throw TRopException("raster type mismatch"); - } else { - if (dn32 && up32) { - if (areAlmostEqual(aff.a12, 0) && areAlmostEqual(aff.a21, 0)) - doQuickResampleNoFilter(dn32, up32, aff.a11, aff.a22, aff.a13, aff.a23); - else - doQuickResampleNoFilter(dn32, up32, aff); - - } else if (dnCM32 && upCM32) { - if (areAlmostEqual(aff.a12, 0) && areAlmostEqual(aff.a21, 0)) - doQuickResampleNoFilter(dnCM32, upCM32, aff.a11, aff.a22, aff.a13, aff.a23); - else - doQuickResampleNoFilter(dnCM32, upCM32, aff); - } else if (dn8 && up8) { - if (areAlmostEqual(aff.a12, 0) && areAlmostEqual(aff.a21, 0)) - doQuickResampleNoFilter(dn8, up8, aff.a11, aff.a22, aff.a13, aff.a23); - else - doQuickResampleNoFilter(dn8, up8, aff); - } else - throw TRopException("raster type mismatch"); - } + assert(filterType == TRop::Bilinear || filterType == TRop::ClosestPixel); + + bool bilinear = filterType == TRop::Bilinear; + + TRaster32P dn32 = dn; + TRaster32P up32 = up; + TRasterCM32P dnCM32 = dn; + TRasterCM32P upCM32 = up; + TRasterGR8P dn8 = dn; + TRasterGR8P up8 = up; + dn->clear(); + + if (bilinear) { + if (dn32 && up32) { + if (areAlmostEqual(aff.a12, 0) && areAlmostEqual(aff.a21, 0)) + doQuickResampleFilter(dn32, up32, aff.a11, aff.a22, aff.a13, aff.a23); + else + doQuickResampleFilter(dn32, up32, aff); + } else if (dn32 && up8) { + if (areAlmostEqual(aff.a12, 0) && areAlmostEqual(aff.a21, 0)) + doQuickResampleFilter(dn32, up8, aff.a11, aff.a22, aff.a13, aff.a23); + else + doQuickResampleFilter(dn32, up8, aff); + } else + throw TRopException("raster type mismatch"); + } else { + if (dn32 && up32) { + if (areAlmostEqual(aff.a12, 0) && areAlmostEqual(aff.a21, 0)) + doQuickResampleNoFilter(dn32, up32, aff.a11, aff.a22, aff.a13, aff.a23); + else + doQuickResampleNoFilter(dn32, up32, aff); + + } else if (dnCM32 && upCM32) { + if (areAlmostEqual(aff.a12, 0) && areAlmostEqual(aff.a21, 0)) + doQuickResampleNoFilter(dnCM32, upCM32, aff.a11, aff.a22, aff.a13, + aff.a23); + else + doQuickResampleNoFilter(dnCM32, upCM32, aff); + } else if (dn8 && up8) { + if (areAlmostEqual(aff.a12, 0) && areAlmostEqual(aff.a21, 0)) + doQuickResampleNoFilter(dn8, up8, aff.a11, aff.a22, aff.a13, aff.a23); + else + doQuickResampleNoFilter(dn8, up8, aff); + } else + throw TRopException("raster type mismatch"); + } #endif } void quickPut(const TRasterP &out, const TRasterCM32P &up, const TAffine &aff, - const TPixel32 &inkCol, const TPixel32 &paintCol); + const TPixel32 &inkCol, const TPixel32 &paintCol); diff --git a/toonz/sources/common/trop/quickputP.h b/toonz/sources/common/trop/quickputP.h index 9352af9..a0ce3e0 100644 --- a/toonz/sources/common/trop/quickputP.h +++ b/toonz/sources/common/trop/quickputP.h @@ -5,22 +5,22 @@ #include "trop.h" -void quickPut(const TRasterP &dn, const TRasterP &up, - const TAffine &aff, TRop::ResampleFilterType filterType, - const TPixel32 &colorScale = TPixel32::Black, bool doPremultiply = false, bool whiteTransp = false, bool firstColumn = false, - bool doRasterDarkenBlendedView = false); +void quickPut(const TRasterP &dn, const TRasterP &up, const TAffine &aff, + TRop::ResampleFilterType filterType, + const TPixel32 &colorScale = TPixel32::Black, + bool doPremultiply = false, bool whiteTransp = false, + bool firstColumn = false, bool doRasterDarkenBlendedView = false); -void quickResample(const TRasterP &dn, const TRasterP &up, - const TAffine &aff, TRop::ResampleFilterType filterType); +void quickResample(const TRasterP &dn, const TRasterP &up, const TAffine &aff, + TRop::ResampleFilterType filterType); -void quickPutCmapped(const TRasterP &out, - const TRasterCM32P &up, const TPaletteP &plt, - const TAffine &aff); +void quickPutCmapped(const TRasterP &out, const TRasterCM32P &up, + const TPaletteP &plt, const TAffine &aff); #ifdef __LP64__ void quickResample_optimized(const TRasterP &dn, const TRasterP &up, - const TAffine &aff, - TRop::ResampleFilterType filterType); + const TAffine &aff, + TRop::ResampleFilterType filterType); #endif #endif diff --git a/toonz/sources/common/trop/raster_edge_evaluator.h b/toonz/sources/common/trop/raster_edge_evaluator.h index 97d1faf..e8bba16 100644 --- a/toonz/sources/common/trop/raster_edge_evaluator.h +++ b/toonz/sources/common/trop/raster_edge_evaluator.h @@ -11,34 +11,40 @@ //************************************************************************* /*! - \brief This class implements an evaluator for tcg's sequential reduction algorithm + \brief This class implements an evaluator for tcg's sequential reduction +algorithm that can be used to simplify the borders extracted from a raster image under - a specified tolerance factor. This is typically used as a step in polygonal-based + a specified tolerance factor. This is typically used as a step in +polygonal-based image vectorization processes. \sa The tcg::sequence_ops::minimalPath() function. */ template -class RasterEdgeEvaluator : public tcg::polyline_ops::StandardDeviationEvaluator -{ - double m_tolerance; //!< Maximal distance of an edge from one of the - //!< points it approximates, in the Manhattan metric - double m_maxLength; //!< Maximal length of an acceptable edge length, - //!< in the standard metric +class RasterEdgeEvaluator + : public tcg::polyline_ops::StandardDeviationEvaluator { + double m_tolerance; //!< Maximal distance of an edge from one of the + //!< points it approximates, in the Manhattan metric + double m_maxLength; //!< Maximal length of an acceptable edge length, + //!< in the standard metric public: - typedef typename tcg::polyline_ops::StandardDeviationEvaluator::iterator_type iterator_type; - typedef typename tcg::polyline_ops::StandardDeviationEvaluator::point_type point_type; - typedef typename tcg::polyline_ops::StandardDeviationEvaluator::penalty_type penalty_type; + typedef typename tcg::polyline_ops::StandardDeviationEvaluator< + RanIt>::iterator_type iterator_type; + typedef + typename tcg::polyline_ops::StandardDeviationEvaluator::point_type + point_type; + typedef typename tcg::polyline_ops::StandardDeviationEvaluator< + RanIt>::penalty_type penalty_type; public: - RasterEdgeEvaluator(const iterator_type &begin, const iterator_type &end, - double tolerance, double maxLength); + RasterEdgeEvaluator(const iterator_type &begin, const iterator_type &end, + double tolerance, double maxLength); - iterator_type furthestFrom(const iterator_type &it); - penalty_type penalty(const iterator_type &a, const iterator_type &b); + iterator_type furthestFrom(const iterator_type &it); + penalty_type penalty(const iterator_type &a, const iterator_type &b); }; -#endif //RASTER_EDGE_EVALUATOR_H +#endif // RASTER_EDGE_EVALUATOR_H #ifdef INCLUDE_HPP #include "raster_edge_evaluator.hpp" diff --git a/toonz/sources/common/trop/raster_edge_evaluator.hpp b/toonz/sources/common/trop/raster_edge_evaluator.hpp index 028c1ff..141c000 100644 --- a/toonz/sources/common/trop/raster_edge_evaluator.hpp +++ b/toonz/sources/common/trop/raster_edge_evaluator.hpp @@ -10,108 +10,113 @@ //******************************************************************************* template -RasterEdgeEvaluator::RasterEdgeEvaluator( - const iterator_type &begin, const iterator_type &end, - double tolerance, double maxLength) - : tcg::polyline_ops::StandardDeviationEvaluator(begin, end), m_tolerance(tolerance), m_maxLength(maxLength) -{ -} +RasterEdgeEvaluator::RasterEdgeEvaluator(const iterator_type &begin, + const iterator_type &end, + double tolerance, + double maxLength) + : tcg::polyline_ops::StandardDeviationEvaluator(begin, end) + , m_tolerance(tolerance) + , m_maxLength(maxLength) {} //-------------------------------------------------------------------------- template typename RasterEdgeEvaluator::penalty_type -RasterEdgeEvaluator::penalty(const iterator_type &a, const iterator_type &b) -{ - return tcg::point_ops::norm(*b - *a) * tcg::polyline_ops::StandardDeviationEvaluator::penalty(a, b); +RasterEdgeEvaluator::penalty(const iterator_type &a, + const iterator_type &b) { + return tcg::point_ops::norm(*b - *a) * + tcg::polyline_ops::StandardDeviationEvaluator::penalty(a, b); } //-------------------------------------------------------------------------- template typename RasterEdgeEvaluator::iterator_type -RasterEdgeEvaluator::furthestFrom(const iterator_type &start) -{ - //Build the furthest possible forward difference for every vertex between begin and end. - point_type displace, oldDisplace; - point_type leftConstraint, rightConstraint; - point_type newLeftConstraint, newRightConstraint; - point_type leftDirConstr, rightDirConstr, dir, oldDir; - iterator_type it = start, jt; - - const double sqMaxLength = sq(m_maxLength); - - //Initialize search - leftConstraint = rightConstraint = point_type(); - leftDirConstr = rightDirConstr = point_type(); - oldDir = oldDisplace = point_type(); - - if (it != this->m_begin) - --it; //Chop left - - jt = it; - for (++jt; jt != this->m_end; ++jt) { - //Retrieve displacement from *it - displace = point_type(jt->x - it->x, jt->y - it->y); - dir = point_type(displace.x - oldDisplace.x, displace.y - oldDisplace.y); - - //Max length - if (oldDir.x != 0 || oldDir.y != 0) { - if (sq(displace.x) + sq(displace.y) > sqMaxLength) - break; - } else - leftDirConstr = rightDirConstr = dir; - - //Test displacement against the oldDisplacement. If it's reversing the - //direction, make it invalid. - - if (cross(oldDir, dir) > 0) - leftDirConstr = dir; - - if (cross(oldDir, dir) < 0) - rightDirConstr = dir; - - //Test constraints - - /*if(cross(rightDirConstr, leftDirConstr) <= 0 && - leftDirConstr * rightDirConstr < 0) - break;*/ - if (cross(rightDirConstr, leftDirConstr) < 0) - break; - - if (cross(displace, leftConstraint) < 0) - break; - if (cross(displace, rightConstraint) > 0) - break; - - if (std::max({displace.x, -displace.x, displace.y, -displace.y}) > m_tolerance) { - //Update m_tolerance constraints - newLeftConstraint.x = displace.x + - (displace.y < 0 || (displace.y == 0 && displace.x < 0) ? m_tolerance : -m_tolerance); - newLeftConstraint.y = displace.y + - (displace.x > 0 || (displace.x == 0 && displace.y < 0) ? m_tolerance : -m_tolerance); - - if (cross(newLeftConstraint, leftConstraint) >= 0) - leftConstraint = newLeftConstraint; - - newRightConstraint.x = displace.x + - (displace.y > 0 || (displace.y == 0 && displace.x < 0) ? m_tolerance : -m_tolerance); - - newRightConstraint.y = displace.y + - (displace.x < 0 || (displace.x == 0 && displace.y < 0) ? m_tolerance : -m_tolerance); - - if (cross(newRightConstraint, rightConstraint) <= 0) - rightConstraint = newRightConstraint; - } - - oldDisplace = displace; - oldDir = dir; - } - - if (jt != this->m_end) - --jt; //Chop Right - - return start + std::max((int)std::min(jt - start - 1, this->m_end - this->m_begin - 2), 1); +RasterEdgeEvaluator::furthestFrom(const iterator_type &start) { + // Build the furthest possible forward difference for every vertex between + // begin and end. + point_type displace, oldDisplace; + point_type leftConstraint, rightConstraint; + point_type newLeftConstraint, newRightConstraint; + point_type leftDirConstr, rightDirConstr, dir, oldDir; + iterator_type it = start, jt; + + const double sqMaxLength = sq(m_maxLength); + + // Initialize search + leftConstraint = rightConstraint = point_type(); + leftDirConstr = rightDirConstr = point_type(); + oldDir = oldDisplace = point_type(); + + if (it != this->m_begin) --it; // Chop left + + jt = it; + for (++jt; jt != this->m_end; ++jt) { + // Retrieve displacement from *it + displace = point_type(jt->x - it->x, jt->y - it->y); + dir = point_type(displace.x - oldDisplace.x, displace.y - oldDisplace.y); + + // Max length + if (oldDir.x != 0 || oldDir.y != 0) { + if (sq(displace.x) + sq(displace.y) > sqMaxLength) break; + } else + leftDirConstr = rightDirConstr = dir; + + // Test displacement against the oldDisplacement. If it's reversing the + // direction, make it invalid. + + if (cross(oldDir, dir) > 0) leftDirConstr = dir; + + if (cross(oldDir, dir) < 0) rightDirConstr = dir; + + // Test constraints + + /*if(cross(rightDirConstr, leftDirConstr) <= 0 && +leftDirConstr * rightDirConstr < 0) +break;*/ + if (cross(rightDirConstr, leftDirConstr) < 0) break; + + if (cross(displace, leftConstraint) < 0) break; + if (cross(displace, rightConstraint) > 0) break; + + if (std::max({displace.x, -displace.x, displace.y, -displace.y}) > + m_tolerance) { + // Update m_tolerance constraints + newLeftConstraint.x = + displace.x + (displace.y < 0 || (displace.y == 0 && displace.x < 0) + ? m_tolerance + : -m_tolerance); + newLeftConstraint.y = + displace.y + (displace.x > 0 || (displace.x == 0 && displace.y < 0) + ? m_tolerance + : -m_tolerance); + + if (cross(newLeftConstraint, leftConstraint) >= 0) + leftConstraint = newLeftConstraint; + + newRightConstraint.x = + displace.x + (displace.y > 0 || (displace.y == 0 && displace.x < 0) + ? m_tolerance + : -m_tolerance); + + newRightConstraint.y = + displace.y + (displace.x < 0 || (displace.x == 0 && displace.y < 0) + ? m_tolerance + : -m_tolerance); + + if (cross(newRightConstraint, rightConstraint) <= 0) + rightConstraint = newRightConstraint; + } + + oldDisplace = displace; + oldDir = dir; + } + + if (jt != this->m_end) --jt; // Chop Right + + return start + + std::max( + (int)std::min(jt - start - 1, this->m_end - this->m_begin - 2), 1); } -#endif // RASTER_EDGE_EVALUATOR_HPP +#endif // RASTER_EDGE_EVALUATOR_HPP diff --git a/toonz/sources/common/trop/raster_edge_iterator.h b/toonz/sources/common/trop/raster_edge_iterator.h index b020284..aaa857a 100644 --- a/toonz/sources/common/trop/raster_edge_iterator.h +++ b/toonz/sources/common/trop/raster_edge_iterator.h @@ -5,113 +5,121 @@ #include "traster.h" -namespace TRop -{ -namespace borders -{ +namespace TRop { +namespace borders { //********************************************************************************************************* // RasterEdgeIterator class //********************************************************************************************************* /*! - The RasterEdgeIterator class models a forward iterator traversing a border of a + The RasterEdgeIterator class models a forward iterator traversing a border of + a raster image. */ template -class RasterEdgeIterator -{ +class RasterEdgeIterator { public: - typedef PixelSelector selector_type; - typedef typename PixelSelector::pixel_type pixel_type; - typedef typename PixelSelector::value_type value_type; - typedef TRasterT raster_type; - typedef TRasterPT raster_typeP; - - enum { STRAIGHT = 0x0, - LEFT = 0x1, - RIGHT = 0x2, - AMBIGUOUS = 0x4, - AMBIGUOUS_LEFT = LEFT | AMBIGUOUS, - AMBIGUOUS_RIGHT = RIGHT | AMBIGUOUS, - UNKNOWN = 0x8 }; + typedef PixelSelector selector_type; + typedef typename PixelSelector::pixel_type pixel_type; + typedef typename PixelSelector::value_type value_type; + typedef TRasterT raster_type; + typedef TRasterPT raster_typeP; + + enum { + STRAIGHT = 0x0, + LEFT = 0x1, + RIGHT = 0x2, + AMBIGUOUS = 0x4, + AMBIGUOUS_LEFT = LEFT | AMBIGUOUS, + AMBIGUOUS_RIGHT = RIGHT | AMBIGUOUS, + UNKNOWN = 0x8 + }; private: - raster_typeP m_ras; - selector_type m_selector; + raster_typeP m_ras; + selector_type m_selector; - int m_lx_1, m_ly_1, m_wrap; + int m_lx_1, m_ly_1, m_wrap; - value_type m_leftColor, m_rightColor, m_elbowColor; - pixel_type *m_leftPix, *m_rightPix; + value_type m_leftColor, m_rightColor, m_elbowColor; + pixel_type *m_leftPix, *m_rightPix; - bool m_rightSide; - int m_turn; + bool m_rightSide; + int m_turn; - TPoint m_pos, m_dir; + TPoint m_pos, m_dir; public: - RasterEdgeIterator(const raster_typeP &rin, const selector_type &selector, - const TPoint &pos, const TPoint &dir, int adherence = RIGHT); + RasterEdgeIterator(const raster_typeP &rin, const selector_type &selector, + const TPoint &pos, const TPoint &dir, + int adherence = RIGHT); - void setEdge(const TPoint &pos, const TPoint &dir); + void setEdge(const TPoint &pos, const TPoint &dir); - const raster_typeP &raster() const { return m_ras; } - const selector_type &selector() const { return m_selector; } + const raster_typeP &raster() const { return m_ras; } + const selector_type &selector() const { return m_selector; } - const TPoint &pos() const { return m_pos; } - const TPoint &dir() const { return m_dir; } + const TPoint &pos() const { return m_pos; } + const TPoint &dir() const { return m_dir; } - const value_type &leftColor() const { return m_leftColor; } - const value_type &rightColor() const { return m_rightColor; } + const value_type &leftColor() const { return m_leftColor; } + const value_type &rightColor() const { return m_rightColor; } - const value_type &color() const { return m_rightSide ? m_rightColor : m_leftColor; } - const value_type &otherColor() const { return m_rightSide ? m_leftColor : m_rightColor; } - const value_type &elbowColor() const { return m_elbowColor; } + const value_type &color() const { + return m_rightSide ? m_rightColor : m_leftColor; + } + const value_type &otherColor() const { + return m_rightSide ? m_leftColor : m_rightColor; + } + const value_type &elbowColor() const { return m_elbowColor; } - pixel_type *leftPix() const { return m_leftPix; } - pixel_type *rightPix() const { return m_rightPix; } + pixel_type *leftPix() const { return m_leftPix; } + pixel_type *rightPix() const { return m_rightPix; } - pixel_type *pix() const { return m_rightSide ? m_rightPix : m_leftPix; } - pixel_type *otherPix() const { return m_rightSide ? m_leftPix : m_rightPix; } + pixel_type *pix() const { return m_rightSide ? m_rightPix : m_leftPix; } + pixel_type *otherPix() const { return m_rightSide ? m_leftPix : m_rightPix; } - int turn() const { return m_turn; } + int turn() const { return m_turn; } - void setAdherence(int side) { m_rightSide = (side == RIGHT); } - int adherence() const { return m_rightSide ? RIGHT : LEFT; } + void setAdherence(int side) { m_rightSide = (side == RIGHT); } + int adherence() const { return m_rightSide ? RIGHT : LEFT; } - RasterEdgeIterator &operator++(); + RasterEdgeIterator &operator++(); - bool operator==(const RasterEdgeIterator &it) const { return m_pos == it.m_pos && m_dir == it.m_dir; } - bool operator!=(const RasterEdgeIterator &it) const { return !operator==(it); } + bool operator==(const RasterEdgeIterator &it) const { + return m_pos == it.m_pos && m_dir == it.m_dir; + } + bool operator!=(const RasterEdgeIterator &it) const { + return !operator==(it); + } private: - void pixels(pixel_type *&pixLeft, pixel_type *&pixRight); - void colors(value_type &leftColor, value_type &rightColor); - void turn(const value_type &newLeftColor, const value_type &newRightColor); - void turnLeft() - { - int temp = m_dir.x; - m_dir.x = -m_dir.y; - m_dir.y = temp; - m_turn = LEFT; - } - void turnRight() - { - int temp = m_dir.x; - m_dir.x = m_dir.y; - m_dir.y = -temp; - m_turn = RIGHT; - } - void turnAmbiguous(const value_type &newLeftColor, const value_type &newRightColor); + void pixels(pixel_type *&pixLeft, pixel_type *&pixRight); + void colors(value_type &leftColor, value_type &rightColor); + void turn(const value_type &newLeftColor, const value_type &newRightColor); + void turnLeft() { + int temp = m_dir.x; + m_dir.x = -m_dir.y; + m_dir.y = temp; + m_turn = LEFT; + } + void turnRight() { + int temp = m_dir.x; + m_dir.x = m_dir.y; + m_dir.y = -temp; + m_turn = RIGHT; + } + void turnAmbiguous(const value_type &newLeftColor, + const value_type &newRightColor); }; } -} // namespace TRop::borders +} // namespace TRop::borders -#endif //RASTER_EDGE_ITERATOR_H +#endif // RASTER_EDGE_ITERATOR_H //===================================================================================== #ifdef INCLUDE_HPP #include "raster_edge_iterator.hpp" -#endif //INCLUDE_HPP +#endif // INCLUDE_HPP diff --git a/toonz/sources/common/trop/raster_edge_iterator.hpp b/toonz/sources/common/trop/raster_edge_iterator.hpp index 3e4ddf3..4df085a 100644 --- a/toonz/sources/common/trop/raster_edge_iterator.hpp +++ b/toonz/sources/common/trop/raster_edge_iterator.hpp @@ -5,243 +5,255 @@ #include "raster_edge_iterator.h" -namespace TRop -{ -namespace borders -{ +namespace TRop { +namespace borders { template RasterEdgeIterator::RasterEdgeIterator( - const raster_typeP &rin, const selector_type &selector, - const TPoint &pos, const TPoint &dir, int adherence) - : m_ras(rin), m_lx_1(rin->getLx() - 1), m_ly_1(rin->getLy() - 1), m_wrap(rin->getWrap()), m_selector(selector), m_pos(pos), m_dir(dir), m_elbowColor(selector.transparent()), m_rightSide(adherence == RIGHT), m_turn(UNKNOWN) -{ - pixels(m_leftPix, m_rightPix); - colors(m_leftColor, m_rightColor); + const raster_typeP &rin, const selector_type &selector, const TPoint &pos, + const TPoint &dir, int adherence) + : m_ras(rin) + , m_lx_1(rin->getLx() - 1) + , m_ly_1(rin->getLy() - 1) + , m_wrap(rin->getWrap()) + , m_selector(selector) + , m_pos(pos) + , m_dir(dir) + , m_elbowColor(selector.transparent()) + , m_rightSide(adherence == RIGHT) + , m_turn(UNKNOWN) { + pixels(m_leftPix, m_rightPix); + colors(m_leftColor, m_rightColor); } //--------------------------------------------------------------------------------------------- template -void RasterEdgeIterator::setEdge(const TPoint &pos, const TPoint &dir) -{ - m_pos = pos, m_dir = dir; - pixels(m_leftPix, m_rightPix); - colors(m_leftColor, m_rightColor); +void RasterEdgeIterator::setEdge(const TPoint &pos, + const TPoint &dir) { + m_pos = pos, m_dir = dir; + pixels(m_leftPix, m_rightPix); + colors(m_leftColor, m_rightColor); } //--------------------------------------------------------------------------------------------- template -inline void RasterEdgeIterator::pixels( - pixel_type *&pixLeft, pixel_type *&pixRight) -{ - pixel_type *pix = m_ras->pixels(0) + m_pos.y * m_wrap + m_pos.x; - if (m_dir.y) - if (m_dir.y > 0) - pixLeft = pix - 1, pixRight = pix; - else - pixLeft = pix - m_wrap, pixRight = pixLeft - 1; - else if (m_dir.x > 0) - pixLeft = pix, pixRight = pix - m_wrap; - else - pixRight = pix - 1, pixLeft = pixRight - m_wrap; +inline void RasterEdgeIterator::pixels(pixel_type *&pixLeft, + pixel_type *&pixRight) { + pixel_type *pix = m_ras->pixels(0) + m_pos.y * m_wrap + m_pos.x; + if (m_dir.y) + if (m_dir.y > 0) + pixLeft = pix - 1, pixRight = pix; + else + pixLeft = pix - m_wrap, pixRight = pixLeft - 1; + else if (m_dir.x > 0) + pixLeft = pix, pixRight = pix - m_wrap; + else + pixRight = pix - 1, pixLeft = pixRight - m_wrap; } //--------------------------------------------------------------------------------------------- template -inline void RasterEdgeIterator::colors( - value_type &leftColor, value_type &rightColor) -{ - if (m_dir.y) - if (m_dir.y > 0) { - if (m_pos.y > m_ly_1) - leftColor = rightColor = m_selector.transparent(); - else { - leftColor = (m_pos.x > 0) ? m_selector.value(*m_leftPix) : m_selector.transparent(); - rightColor = (m_pos.x <= m_lx_1) ? m_selector.value(*m_rightPix) : m_selector.transparent(); - } - } else { - if (m_pos.y < 1) - leftColor = rightColor = m_selector.transparent(); - else { - leftColor = (m_pos.x <= m_lx_1) ? m_selector.value(*m_leftPix) : m_selector.transparent(); - rightColor = (m_pos.x > 0) ? m_selector.value(*m_rightPix) : m_selector.transparent(); - } - } - else if (m_dir.x > 0) { - if (m_pos.x > m_lx_1) - leftColor = rightColor = m_selector.transparent(); - else { - leftColor = (m_pos.y <= m_ly_1) ? m_selector.value(*m_leftPix) : m_selector.transparent(); - rightColor = (m_pos.y > 0) ? m_selector.value(*m_rightPix) : m_selector.transparent(); - } - } else { - if (m_pos.x < 1) - leftColor = rightColor = m_selector.transparent(); - else { - leftColor = (m_pos.y > 0) ? m_selector.value(*m_leftPix) : m_selector.transparent(); - rightColor = (m_pos.y <= m_ly_1) ? m_selector.value(*m_rightPix) : m_selector.transparent(); - } - } +inline void RasterEdgeIterator::colors(value_type &leftColor, + value_type &rightColor) { + if (m_dir.y) + if (m_dir.y > 0) { + if (m_pos.y > m_ly_1) + leftColor = rightColor = m_selector.transparent(); + else { + leftColor = (m_pos.x > 0) ? m_selector.value(*m_leftPix) + : m_selector.transparent(); + rightColor = (m_pos.x <= m_lx_1) ? m_selector.value(*m_rightPix) + : m_selector.transparent(); + } + } else { + if (m_pos.y < 1) + leftColor = rightColor = m_selector.transparent(); + else { + leftColor = (m_pos.x <= m_lx_1) ? m_selector.value(*m_leftPix) + : m_selector.transparent(); + rightColor = (m_pos.x > 0) ? m_selector.value(*m_rightPix) + : m_selector.transparent(); + } + } + else if (m_dir.x > 0) { + if (m_pos.x > m_lx_1) + leftColor = rightColor = m_selector.transparent(); + else { + leftColor = (m_pos.y <= m_ly_1) ? m_selector.value(*m_leftPix) + : m_selector.transparent(); + rightColor = (m_pos.y > 0) ? m_selector.value(*m_rightPix) + : m_selector.transparent(); + } + } else { + if (m_pos.x < 1) + leftColor = rightColor = m_selector.transparent(); + else { + leftColor = (m_pos.y > 0) ? m_selector.value(*m_leftPix) + : m_selector.transparent(); + rightColor = (m_pos.y <= m_ly_1) ? m_selector.value(*m_rightPix) + : m_selector.transparent(); + } + } } //--------------------------------------------------------------------------------------------- template -inline void RasterEdgeIterator::turn(const value_type &newLeftColor, const value_type &newRightColor) -{ - if (m_rightSide) { - if (newLeftColor == m_rightColor) { - if (newRightColor == m_leftColor) - turnAmbiguous(newLeftColor, newRightColor); - else - turnLeft(); - } else { - if (newRightColor != m_rightColor) - turnRight(); - else - m_turn = STRAIGHT; - } - - m_elbowColor = newLeftColor; - } else { - if (newRightColor == m_leftColor) { - if (newLeftColor == m_rightColor) - turnAmbiguous(newLeftColor, newRightColor); - else - turnRight(); - } else { - if (newLeftColor != m_leftColor) - turnLeft(); - else - m_turn = STRAIGHT; - } - - m_elbowColor = newRightColor; - } - - pixels(m_leftPix, m_rightPix); +inline void RasterEdgeIterator::turn( + const value_type &newLeftColor, const value_type &newRightColor) { + if (m_rightSide) { + if (newLeftColor == m_rightColor) { + if (newRightColor == m_leftColor) + turnAmbiguous(newLeftColor, newRightColor); + else + turnLeft(); + } else { + if (newRightColor != m_rightColor) + turnRight(); + else + m_turn = STRAIGHT; + } + + m_elbowColor = newLeftColor; + } else { + if (newRightColor == m_leftColor) { + if (newLeftColor == m_rightColor) + turnAmbiguous(newLeftColor, newRightColor); + else + turnRight(); + } else { + if (newLeftColor != m_leftColor) + turnLeft(); + else + m_turn = STRAIGHT; + } + + m_elbowColor = newRightColor; + } + + pixels(m_leftPix, m_rightPix); } //--------------------------------------------------------------------------------------------- template inline void RasterEdgeIterator::turnAmbiguous( - const value_type &newLeftColor, const value_type &newRightColor) -{ - pixel_type *pix = m_ras->pixels(0) + m_pos.y * m_wrap + m_pos.x; - UCHAR count1 = 0, count2 = 0; - - value_type val; - - // Check the 4x4 neighbourhood and connect the minority color - if (m_pos.x > 2) { - val = m_selector.value(*(pix - 2)); - if (val == m_leftColor) - ++count1; - else if (val == m_rightColor) - ++count2; - - val = m_selector.value(*(pix - 2 - m_wrap)); - if (val == m_leftColor) - ++count1; - else if (val == m_rightColor) - ++count2; - } - - if (m_pos.x < m_lx_1) { - val = m_selector.value(*(pix + 1)); - if (val == m_leftColor) - ++count1; - else if (val == m_rightColor) - ++count2; - - val = m_selector.value(*(pix + 1 - m_wrap)); - if (val == m_leftColor) - ++count1; - else if (val == m_rightColor) - ++count2; - } - - if (m_pos.y > 2) { - int wrap2 = m_wrap << 1; - - val = m_selector.value(*(pix - wrap2)); - if (val == m_leftColor) - ++count1; - else if (val == m_rightColor) - ++count2; - - val = m_selector.value(*(pix - wrap2 - 1)); - if (val == m_leftColor) - ++count1; - else if (val == m_rightColor) - ++count2; - } - - if (m_pos.y < m_ly_1) { - val = m_selector.value(*(pix + m_wrap)); - if (val == m_leftColor) - ++count1; - else if (val == m_rightColor) - ++count2; - - val = m_selector.value(*(pix + m_wrap - 1)); - if (val == m_leftColor) - ++count1; - else if (val == m_rightColor) - ++count2; - } - - // Minority connection - join the one with less count - if (count1 < count2) - turnRight(); // Join m_leftColor == newRightColor - else if (count1 > count2) - turnLeft(); // Join m_rightColor == newLeftColor - else if (m_rightColor < m_leftColor) - turnLeft(); - else - turnRight(); - - m_turn |= AMBIGUOUS; + const value_type &newLeftColor, const value_type &newRightColor) { + pixel_type *pix = m_ras->pixels(0) + m_pos.y * m_wrap + m_pos.x; + UCHAR count1 = 0, count2 = 0; + + value_type val; + + // Check the 4x4 neighbourhood and connect the minority color + if (m_pos.x > 2) { + val = m_selector.value(*(pix - 2)); + if (val == m_leftColor) + ++count1; + else if (val == m_rightColor) + ++count2; + + val = m_selector.value(*(pix - 2 - m_wrap)); + if (val == m_leftColor) + ++count1; + else if (val == m_rightColor) + ++count2; + } + + if (m_pos.x < m_lx_1) { + val = m_selector.value(*(pix + 1)); + if (val == m_leftColor) + ++count1; + else if (val == m_rightColor) + ++count2; + + val = m_selector.value(*(pix + 1 - m_wrap)); + if (val == m_leftColor) + ++count1; + else if (val == m_rightColor) + ++count2; + } + + if (m_pos.y > 2) { + int wrap2 = m_wrap << 1; + + val = m_selector.value(*(pix - wrap2)); + if (val == m_leftColor) + ++count1; + else if (val == m_rightColor) + ++count2; + + val = m_selector.value(*(pix - wrap2 - 1)); + if (val == m_leftColor) + ++count1; + else if (val == m_rightColor) + ++count2; + } + + if (m_pos.y < m_ly_1) { + val = m_selector.value(*(pix + m_wrap)); + if (val == m_leftColor) + ++count1; + else if (val == m_rightColor) + ++count2; + + val = m_selector.value(*(pix + m_wrap - 1)); + if (val == m_leftColor) + ++count1; + else if (val == m_rightColor) + ++count2; + } + + // Minority connection - join the one with less count + if (count1 < count2) + turnRight(); // Join m_leftColor == newRightColor + else if (count1 > count2) + turnLeft(); // Join m_rightColor == newLeftColor + else if (m_rightColor < m_leftColor) + turnLeft(); + else + turnRight(); + + m_turn |= AMBIGUOUS; } //--------------------------------------------------------------------------------------------- template -RasterEdgeIterator &RasterEdgeIterator::operator++() -{ - value_type newLeftColor = m_leftColor, newRightColor = m_rightColor; - - int pixAdd = m_dir.y * m_wrap + m_dir.x; - if (m_rightSide) { - do { - m_pos.x += m_dir.x, m_pos.y += m_dir.y; - m_leftPix += pixAdd, m_rightPix += pixAdd; - m_leftColor = newLeftColor; - - colors(newLeftColor, newRightColor); - } while ((newRightColor == m_rightColor) && (newLeftColor != newRightColor) && - m_selector.skip(m_leftColor, newLeftColor)); - } else { - do { - m_pos.x += m_dir.x, m_pos.y += m_dir.y; - m_leftPix += pixAdd, m_rightPix += pixAdd; - m_rightColor = newRightColor; - - colors(newLeftColor, newRightColor); - } while ((newLeftColor == m_leftColor) && (newLeftColor != newRightColor) && - m_selector.skip(m_rightColor, newRightColor)); - } - - turn(newLeftColor, newRightColor); - colors(m_leftColor, m_rightColor); - - return *this; +RasterEdgeIterator + &RasterEdgeIterator::operator++() { + value_type newLeftColor = m_leftColor, newRightColor = m_rightColor; + + int pixAdd = m_dir.y * m_wrap + m_dir.x; + if (m_rightSide) { + do { + m_pos.x += m_dir.x, m_pos.y += m_dir.y; + m_leftPix += pixAdd, m_rightPix += pixAdd; + m_leftColor = newLeftColor; + + colors(newLeftColor, newRightColor); + } while ((newRightColor == m_rightColor) && + (newLeftColor != newRightColor) && + m_selector.skip(m_leftColor, newLeftColor)); + } else { + do { + m_pos.x += m_dir.x, m_pos.y += m_dir.y; + m_leftPix += pixAdd, m_rightPix += pixAdd; + m_rightColor = newRightColor; + + colors(newLeftColor, newRightColor); + } while ((newLeftColor == m_leftColor) && (newLeftColor != newRightColor) && + m_selector.skip(m_rightColor, newRightColor)); + } + + turn(newLeftColor, newRightColor); + colors(m_leftColor, m_rightColor); + + return *this; } } -} // namespace TRop::borders +} // namespace TRop::borders -#endif // RASTER_EDGE_ITERATOR_HPP +#endif // RASTER_EDGE_ITERATOR_HPP diff --git a/toonz/sources/common/trop/runsmap.cpp b/toonz/sources/common/trop/runsmap.cpp index 2d8d415..d04d936 100644 --- a/toonz/sources/common/trop/runsmap.cpp +++ b/toonz/sources/common/trop/runsmap.cpp @@ -4,44 +4,42 @@ //--------------------------------------------------------------------------------------------- -void RunsMap::setRunLength(TPixelGR8 *pix, TUINT32 length) -{ - TPixelGR8 *origPix = pix; - pix = origPix; - - TPixelGR8 *pixRev = pix + length - 1; - - --length; - if (length < 3) - pix->value = pixRev->value = (length << 6); - else { - pix->value = pixRev->value = (3 << 6); - ++pix, --pixRev; - if (length < 255) - pix->value = pixRev->value = length; - else { - pix->value = pixRev->value = 255; - ++pix, pixRev -= 4; - TUINT32 *l = (TUINT32 *)pix; - *l = length; - } - } - - assert(runLength(origPix) == (length + 1)); +void RunsMap::setRunLength(TPixelGR8 *pix, TUINT32 length) { + TPixelGR8 *origPix = pix; + pix = origPix; + + TPixelGR8 *pixRev = pix + length - 1; + + --length; + if (length < 3) + pix->value = pixRev->value = (length << 6); + else { + pix->value = pixRev->value = (3 << 6); + ++pix, --pixRev; + if (length < 255) + pix->value = pixRev->value = length; + else { + pix->value = pixRev->value = 255; + ++pix, pixRev -= 4; + TUINT32 *l = (TUINT32 *)pix; + *l = length; + } + } + + assert(runLength(origPix) == (length + 1)); } //--------------------------------------------------------------------------------------------- -TUINT32 RunsMap::runLength(const TPixelGR8 *pix, bool reversed) const -{ - int length = pix->value >> 6; - if (length >= 3) { - pix += (reversed) ? -1 : 1, length = pix->value; - if (length >= 255) { - pix += (reversed) ? -4 : 1; - length = *(TUINT32 *)pix; - } - } - - return length + 1; +TUINT32 RunsMap::runLength(const TPixelGR8 *pix, bool reversed) const { + int length = pix->value >> 6; + if (length >= 3) { + pix += (reversed) ? -1 : 1, length = pix->value; + if (length >= 255) { + pix += (reversed) ? -4 : 1; + length = *(TUINT32 *)pix; + } + } + + return length + 1; } diff --git a/toonz/sources/common/trop/runsmap.h b/toonz/sources/common/trop/runsmap.h index 777b0d0..b7fd4f2 100644 --- a/toonz/sources/common/trop/runsmap.h +++ b/toonz/sources/common/trop/runsmap.h @@ -10,44 +10,50 @@ //********************************************************************************************************* /*! - The RunsMapP is an auxiliary raster greymap type used to store run-length informations + The RunsMapP is an auxiliary raster greymap type used to store run-length + informations about an image. Not every image pixel has valid informations. Only pixels corresponding to run headers do, and those include the position of the next run header. - This means that users must always iterate from the beginning of a line to get valid + This means that users must always iterate from the beginning of a line to get + valid data. - The following coding is adopted to extract the run length from the run headers: + The following coding is adopted to extract the run length from the run + headers: - \li We'll use the last 2 bits only in the headers. With these, we can cover directly + \li We'll use the last 2 bits only in the headers. With these, we can cover + directly those runs up to 4 pixels length. - \li When the length >=4, we require that one byte is taken in the run to store the length + \li When the length >=4, we require that one byte is taken in the run to store + the length up to 256 pixels. - \li When the length >= 256, we take 4 additional bytes to store the length (which this time + \li When the length >= 256, we take 4 additional bytes to store the length + (which this time could go up to billions). Observe that the runsmap supports a symmetrical representation, useful to traverse runs both forward and backwards. This means that 2 headers are provided for each run, at the opposite ends (unless the run is 1 pixel-width). */ -class RunsMap : public TRasterT -{ +class RunsMap : public TRasterT { public: - RunsMap(int lx, int ly) : TRasterT(lx, ly) { clear(); } + RunsMap(int lx, int ly) : TRasterT(lx, ly) { clear(); } - const UCHAR &runHeader(int x, int y) const { return pixels(y)[x].value; } - UCHAR &runHeader(int x, int y) { return pixels(y)[x].value; } + const UCHAR &runHeader(int x, int y) const { return pixels(y)[x].value; } + UCHAR &runHeader(int x, int y) { return pixels(y)[x].value; } - TUINT32 runLength(const TPixelGR8 *run, bool reversed = false) const; - TUINT32 runLength(int x, int y, bool reversed = false) const - { - return runLength(pixels(y) + x, reversed); - } + TUINT32 runLength(const TPixelGR8 *run, bool reversed = false) const; + TUINT32 runLength(int x, int y, bool reversed = false) const { + return runLength(pixels(y) + x, reversed); + } public: - void setRunLength(TPixelGR8 *run, TUINT32 length); - void setRunLength(int x, int y, TUINT32 length) { setRunLength(pixels(y) + x, length); } + void setRunLength(TPixelGR8 *run, TUINT32 length); + void setRunLength(int x, int y, TUINT32 length) { + setRunLength(pixels(y) + x, length); + } }; //--------------------------------------------------------------------------------------------- @@ -56,35 +62,36 @@ public: template class DV_EXPORT_API TSmartPointerT; #endif -class RunsMapP : public TSmartPointerT -{ +class RunsMapP : public TSmartPointerT { public: - RunsMapP() {} - RunsMapP(int lx, int ly) : TSmartPointerT(new RunsMap(lx, ly)) {} - RunsMapP(const TDimension &d) : TSmartPointerT(new RunsMap(d.lx, d.ly)) {} + RunsMapP() {} + RunsMapP(int lx, int ly) : TSmartPointerT(new RunsMap(lx, ly)) {} + RunsMapP(const TDimension &d) + : TSmartPointerT(new RunsMap(d.lx, d.ly)) {} }; //--------------------------------------------------------------------------------------------- template -void buildRunsMap(RunsMapP &runsMap, const TRasterPT &ras, const PixelSelector &selector) -{ - //Traverse the raster, extracting run lengths - int y, ly = ras->getLy(); - for (y = 0; y < ly; ++y) { - Pixel *lineStart = (Pixel *)ras->pixels(y), *lineEnd = lineStart + ras->getLx(); - - Pixel *pix, *runStart; - typename PixelSelector::value_type colorIndex; - for (pix = runStart = lineStart, colorIndex = selector.value(*pix); - pix < lineEnd; ++pix) - if (selector.value(*pix) != colorIndex) { - runsMap->setRunLength(runStart - lineStart, y, pix - runStart); - runStart = pix; - colorIndex = selector.value(*pix); - } - runsMap->setRunLength(runStart - lineStart, y, pix - runStart); - } +void buildRunsMap(RunsMapP &runsMap, const TRasterPT &ras, + const PixelSelector &selector) { + // Traverse the raster, extracting run lengths + int y, ly = ras->getLy(); + for (y = 0; y < ly; ++y) { + Pixel *lineStart = (Pixel *)ras->pixels(y), + *lineEnd = lineStart + ras->getLx(); + + Pixel *pix, *runStart; + typename PixelSelector::value_type colorIndex; + for (pix = runStart = lineStart, colorIndex = selector.value(*pix); + pix < lineEnd; ++pix) + if (selector.value(*pix) != colorIndex) { + runsMap->setRunLength(runStart - lineStart, y, pix - runStart); + runStart = pix; + colorIndex = selector.value(*pix); + } + runsMap->setRunLength(runStart - lineStart, y, pix - runStart); + } } -#endif //RUNSMAP_H +#endif // RUNSMAP_H diff --git a/toonz/sources/common/trop/tantialias.cpp b/toonz/sources/common/trop/tantialias.cpp index 935fec0..3ccce3b 100644 --- a/toonz/sources/common/trop/tantialias.cpp +++ b/toonz/sources/common/trop/tantialias.cpp @@ -7,141 +7,135 @@ See Alexander Reshetov's "Morphological Antialiasing" paper on Intel Labs site. Basically, this antialiasing algorithm is based on the following ideas: - - Suppose that our image is just made up of flat colors. Then, a simple antialiasing - approach is that of assuming that the 'actual' line separating two distinct colors - is the polyline that passes through the midpoint of each edge of its original jaggy + - Suppose that our image is just made up of flat colors. Then, a simple +antialiasing + approach is that of assuming that the 'actual' line separating two distinct +colors + is the polyline that passes through the midpoint of each edge of its original +jaggy counterpart. - As pixels around the border are cut through by the polyline, the area of the pixel + As pixels around the border are cut through by the polyline, the area of the +pixel that is filled of a certain color is its weight in the output filtered pixel. - - The above method can be applied on each single uniform piece of a scanline, considering + - The above method can be applied on each single uniform piece of a scanline, +considering the lines originated by the vertical extensions of its left and right edges. - - Of these lines, only those which lie completely on pixels adjacent to the edge are - considered - so that the antialiasing effect is kept only around the contours. + - Of these lines, only those which lie completely on pixels adjacent to the +edge are + considered - so that the antialiasing effect is kept only around the +contours. -This algorithm would yield a good result at what may be considered 50% softness. Implementing -a generalized softness simply requires that the line slopes used above are modified +This algorithm would yield a good result at what may be considered 50% softness. +Implementing +a generalized softness simply requires that the line slopes used above are +modified accordingly (divide by 2 * softFactor). */ //----------------------------------------------------------------------------------------- -namespace -{ +namespace { template -class PixelSelector -{ +class PixelSelector { public: - typedef PIX pixel_type; + typedef PIX pixel_type; private: - int m_thresh; + int m_thresh; public: - PixelSelector(int thresh) : m_thresh(thresh) {} - - bool areEqual(const PIX &a, const PIX &b) const - { - return std::max({ - abs((int)a.r - b.r), - abs((int)a.g - b.g), - abs((int)a.b - b.b), - abs((int)a.m - b.m)}) < m_thresh; - } + PixelSelector(int thresh) : m_thresh(thresh) {} + + bool areEqual(const PIX &a, const PIX &b) const { + return std::max({abs((int)a.r - b.r), abs((int)a.g - b.g), + abs((int)a.b - b.b), abs((int)a.m - b.m)}) < m_thresh; + } }; //----------------------------------------------------------------------------------------- template <> -class PixelSelector -{ +class PixelSelector { public: - typedef TPixelCM32 pixel_type; + typedef TPixelCM32 pixel_type; private: - int m_thresh; + int m_thresh; public: - PixelSelector(int thresh) : m_thresh(thresh) {} + PixelSelector(int thresh) : m_thresh(thresh) {} - bool areEqual(const TPixelCM32 &a, const TPixelCM32 &b) const - { - return (a.getInk() == b.getInk()) && (abs(a.getTone() - b.getTone()) < m_thresh); - } + bool areEqual(const TPixelCM32 &a, const TPixelCM32 &b) const { + return (a.getInk() == b.getInk()) && + (abs(a.getTone() - b.getTone()) < m_thresh); + } }; //----------------------------------------------------------------------------------------- template -inline void weightPix(PIX *out, const PIX *a, const PIX *b, double weightA, double weightB) -{ - out->r = a->r * weightA + b->r * weightB; - out->g = a->g * weightA + b->g * weightB; - out->b = a->b * weightA + b->b * weightB; - out->m = a->m * weightA + b->m * weightB; +inline void weightPix(PIX *out, const PIX *a, const PIX *b, double weightA, + double weightB) { + out->r = a->r * weightA + b->r * weightB; + out->g = a->g * weightA + b->g * weightB; + out->b = a->b * weightA + b->b * weightB; + out->m = a->m * weightA + b->m * weightB; } //----------------------------------------------------------------------------------------- template <> -inline void weightPix(TPixelCM32 *out, const TPixelCM32 *a, const TPixelCM32 *b, - double weightA, double weightB) -{ - *out = TPixelCM32( - out->isPurePaint() ? b->getInk() : a->getInk(), a->getPaint(), - a->getTone() * weightA + b->getTone() * weightB); +inline void weightPix(TPixelCM32 *out, const TPixelCM32 *a, + const TPixelCM32 *b, double weightA, + double weightB) { + *out = + TPixelCM32(out->isPurePaint() ? b->getInk() : a->getInk(), a->getPaint(), + a->getTone() * weightA + b->getTone() * weightB); } //----------------------------------------------------------------------------------------- -//Returns 0 if pixels to connect are on the 00-11 diagonal, 1 on the 01-10 one. +// Returns 0 if pixels to connect are on the 00-11 diagonal, 1 on the 01-10 one. template -inline bool checkNeighbourHood(int x, int y, PIX *pix, int lx, int ly, int dx, int dy, - const SELECTOR &sel) -{ - int count1 = 0, count2 = 0; - int dx2 = 2 * dx, dy2 = 2 * dy; - if (y > 1) { - //Lower edge - count1 += - (int)sel.areEqual(*(pix - dx), *(pix - dy2)) + - (int)sel.areEqual(*(pix - dx), *(pix - dy2 - dx)); - count2 += - (int)sel.areEqual(*pix, *(pix - dy2)) + - (int)sel.areEqual(*pix, *(pix - dy2 - dx)); - } - if (y < ly - 1) { - //Upper edge - count1 += - (int)sel.areEqual(*(pix - dx), *(pix + dy)) + - (int)sel.areEqual(*(pix - dx), *(pix + dy - dx)); - count2 += - (int)sel.areEqual(*pix, *(pix + dy)) + - (int)sel.areEqual(*pix, *(pix + dy - dx)); - } - if (x > 1) { - //Left edge - count1 += - (int)sel.areEqual(*(pix - dx), *(pix - dx2)) + - (int)sel.areEqual(*(pix - dx), *(pix - dx2 - dy)); - count2 += - (int)sel.areEqual(*pix, *(pix - dx2)) + - (int)sel.areEqual(*pix, *(pix - dx2 - dy)); - } - if (x < lx - 1) { - //Left edge - count1 += - (int)sel.areEqual(*(pix - dx), *(pix + dx)) + - (int)sel.areEqual(*(pix - dx), *(pix + dx - dy)); - count2 += - (int)sel.areEqual(*pix, *(pix + dx)) + - (int)sel.areEqual(*pix, *(pix + dx - dy)); - } - - //Connect by minority: if there are more pixels like those on the 00-11 diagonal, connect the other, - //and viceversa. - return count1 > count2; +inline bool checkNeighbourHood(int x, int y, PIX *pix, int lx, int ly, int dx, + int dy, const SELECTOR &sel) { + int count1 = 0, count2 = 0; + int dx2 = 2 * dx, dy2 = 2 * dy; + if (y > 1) { + // Lower edge + count1 += (int)sel.areEqual(*(pix - dx), *(pix - dy2)) + + (int)sel.areEqual(*(pix - dx), *(pix - dy2 - dx)); + count2 += (int)sel.areEqual(*pix, *(pix - dy2)) + + (int)sel.areEqual(*pix, *(pix - dy2 - dx)); + } + if (y < ly - 1) { + // Upper edge + count1 += (int)sel.areEqual(*(pix - dx), *(pix + dy)) + + (int)sel.areEqual(*(pix - dx), *(pix + dy - dx)); + count2 += (int)sel.areEqual(*pix, *(pix + dy)) + + (int)sel.areEqual(*pix, *(pix + dy - dx)); + } + if (x > 1) { + // Left edge + count1 += (int)sel.areEqual(*(pix - dx), *(pix - dx2)) + + (int)sel.areEqual(*(pix - dx), *(pix - dx2 - dy)); + count2 += (int)sel.areEqual(*pix, *(pix - dx2)) + + (int)sel.areEqual(*pix, *(pix - dx2 - dy)); + } + if (x < lx - 1) { + // Left edge + count1 += (int)sel.areEqual(*(pix - dx), *(pix + dx)) + + (int)sel.areEqual(*(pix - dx), *(pix + dx - dy)); + count2 += (int)sel.areEqual(*pix, *(pix + dx)) + + (int)sel.areEqual(*pix, *(pix + dx - dy)); + } + + // Connect by minority: if there are more pixels like those on the 00-11 + // diagonal, connect the other, + // and viceversa. + return count1 > count2; } } @@ -149,255 +143,259 @@ inline bool checkNeighbourHood(int x, int y, PIX *pix, int lx, int ly, int dx, i template inline void filterLine(PIX *inLPix, PIX *inUPix, PIX *outLPix, PIX *outUPix, - int ll, int inDl, int outLDl, int outUDl, - double hStart, double slope, bool filterLower) -{ - assert(hStart >= 0.0 && slope > 0.0); - - double h0 = hStart, h1, area; - double base = hStart / slope; - - int i, end = std::min(tfloor(base), ll); - if (filterLower) { - //Filter lower line - for (i = 0; i < end; ++i, h0 = h1, - inLPix += inDl, inUPix += inDl, outLPix += outLDl) { - h1 = h0 - slope; - area = 0.5 * (h0 + h1); - weightPix(outLPix, outLPix, inUPix, 1.0 - area, area); - } - - if (i < ll) { - double remnant = base - end; - area = 0.5 * remnant * h0; - weightPix(outLPix, outLPix, inUPix, 1.0 - area, area); - } - } else { - //Filter upper line - for (i = 0; i < end; ++i, h0 = h1, - inLPix += inDl, inUPix += inDl, outUPix += outUDl) { - h1 = h0 - slope; - area = 0.5 * (h0 + h1); - weightPix(outUPix, outUPix, inLPix, 1.0 - area, area); - } - - if (i < ll) { - double remnant = base - end; - area = 0.5 * remnant * h0; - weightPix(outUPix, outUPix, inLPix, 1.0 - area, area); - } - } + int ll, int inDl, int outLDl, int outUDl, double hStart, + double slope, bool filterLower) { + assert(hStart >= 0.0 && slope > 0.0); + + double h0 = hStart, h1, area; + double base = hStart / slope; + + int i, end = std::min(tfloor(base), ll); + if (filterLower) { + // Filter lower line + for (i = 0; i < end; + ++i, h0 = h1, inLPix += inDl, inUPix += inDl, outLPix += outLDl) { + h1 = h0 - slope; + area = 0.5 * (h0 + h1); + weightPix(outLPix, outLPix, inUPix, 1.0 - area, area); + } + + if (i < ll) { + double remnant = base - end; + area = 0.5 * remnant * h0; + weightPix(outLPix, outLPix, inUPix, 1.0 - area, area); + } + } else { + // Filter upper line + for (i = 0; i < end; + ++i, h0 = h1, inLPix += inDl, inUPix += inDl, outUPix += outUDl) { + h1 = h0 - slope; + area = 0.5 * (h0 + h1); + weightPix(outUPix, outUPix, inLPix, 1.0 - area, area); + } + + if (i < ll) { + double remnant = base - end; + area = 0.5 * remnant * h0; + weightPix(outUPix, outUPix, inLPix, 1.0 - area, area); + } + } } //--------------------------------------------------------------------------------------- template -inline bool checkLength(int lLine, int y, int ly, int dy, - PIX *pixL1, PIX *pixU1, PIX *pixL2, PIX *pixU2, - bool uniteU, bool do1Line, - const SELECTOR &sel) -{ - //1-length edges must be processed (as primary edges) only if explicitly required, - //and only when its associated secondary edge is of the same length. - - return (lLine > 1) || - (do1Line && - ((uniteU && (y > 1 && !(sel.areEqual(*pixL1, *(pixL1 - dy)) && sel.areEqual(*pixL2, *(pixL2 - dy))))) || - (y < ly - 1 && !(sel.areEqual(*pixU1, *(pixU1 + dy)) && sel.areEqual(*pixU2, *(pixU2 + dy)))))); +inline bool checkLength(int lLine, int y, int ly, int dy, PIX *pixL1, + PIX *pixU1, PIX *pixL2, PIX *pixU2, bool uniteU, + bool do1Line, const SELECTOR &sel) { + // 1-length edges must be processed (as primary edges) only if explicitly + // required, + // and only when its associated secondary edge is of the same length. + + return (lLine > 1) || + (do1Line && ((uniteU && (y > 1 && + !(sel.areEqual(*pixL1, *(pixL1 - dy)) && + sel.areEqual(*pixL2, *(pixL2 - dy))))) || + (y < ly - 1 && + !(sel.areEqual(*pixU1, *(pixU1 + dy)) && + sel.areEqual(*pixU2, *(pixU2 + dy)))))); } //--------------------------------------------------------------------------------------- template -void processLine(int r, int lx, int ly, - PIX *inLRow, PIX *inURow, PIX *outLRow, PIX *outURow, - int inDx, int inDy, int outLDx, int outUDx, - bool do1Line, double hStart, double slope, - const SELECTOR &sel) -{ - //Using a 'horizontal' notation here - but the same applies in vertical too - ++r; - - //As long as we don't reach row end, process uninterrupted separation lines - //between colors - - PIX *inLL = inLRow, *inLR, *inUL = inURow, *inUR; - PIX *inLL_1, *inUL_1, *inLR_1, *inUR_1; - PIX *inLEnd = inLRow + lx * inDx; - int x, lLine; - bool uniteLL, uniteUL, uniteLR, uniteUR; - - //Special case: a line at row start has different weights - if (!sel.areEqual(*inLL, *inUL)) { - //Look for line ends - for (inLR = inLL + inDx, inUR = inUL + inDx; - inLR != inLEnd && sel.areEqual(*inLL, *inLR) && sel.areEqual(*inUL, *inUR); - inLR += inDx, inUR += inDx) - ; - - if (inLR != inLEnd) { - //Found a line to process - lLine = (inLR - inLL) / inDx; - - inLR_1 = inLR - inDx, inUR_1 = inUR - inDx; - x = (inLR_1 - inLRow) / inDx; - - uniteUR = sel.areEqual(*inUR_1, *inLR); - uniteLR = sel.areEqual(*inLR_1, *inUR); - if (uniteUR || uniteLR) { - if (uniteUR && uniteLR) - //Ambiguous case. Check neighborhood to find out which one must be actually united. - uniteUR = !checkNeighbourHood(x + 1, r, inUR, lx, ly, inDx, inDy, sel); - - if (checkLength(lLine, r, ly, inDy, inLR_1, inUR_1, inLR, inUR, uniteUR, do1Line, sel)) - filterLine(inLR_1, inUR_1, outLRow + x * outLDx, outURow + x * outUDx, - lLine, -inDx, -outLDx, -outUDx, hStart, slope / (lLine << 1), uniteUR); - } - } - - //Update lefts - inLL = inLR, inUL = inUR; - } - - //Search for a line start - for (; inLL != inLEnd && sel.areEqual(*inLL, *inUL); inLL += inDx, inUL += inDx) - ; - - while (inLL != inLEnd) { - //Look for line ends - for (inLR = inLL + inDx, inUR = inUL + inDx; - inLR != inLEnd && sel.areEqual(*inLL, *inLR) && sel.areEqual(*inUL, *inUR); - inLR += inDx, inUR += inDx) - ; - - if (inLR == inLEnd) - break; //Dealt with later - - //Found a line to process - lLine = (inLR - inLL) / inDx; - - //First, filter left to right - inLL_1 = inLL - inDx, inUL_1 = inUL - inDx; - x = (inLL - inLRow) / inDx; - - uniteUL = sel.areEqual(*inUL, *inLL_1); - uniteLL = sel.areEqual(*inLL, *inUL_1); - if (uniteUL || uniteLL) { - if (uniteUL && uniteLL) - uniteUL = checkNeighbourHood(x, r, inUL, lx, ly, inDx, inDy, sel); - - if (checkLength(lLine, r, ly, inDy, inLL_1, inUL_1, inLL, inUL, uniteUL, do1Line, sel)) - filterLine(inLL, inUL, outLRow + x * outLDx, outURow + x * outUDx, - lLine, inDx, outLDx, outUDx, hStart, slope / lLine, uniteUL); - } - - //Then, filter right to left - inLR_1 = inLR - inDx, inUR_1 = inUR - inDx; - x = (inLR_1 - inLRow) / inDx; - - uniteUR = sel.areEqual(*inUR_1, *inLR); - uniteLR = sel.areEqual(*inLR_1, *inUR); - if (uniteUR || uniteLR) { - if (uniteUR && uniteLR) - uniteUR = !checkNeighbourHood(x + 1, r, inUR, lx, ly, inDx, inDy, sel); - - if (checkLength(lLine, r, ly, inDy, inLR_1, inUR_1, inLR, inUR, uniteUR, do1Line, sel)) - filterLine(inLR_1, inUR_1, outLRow + x * outLDx, outURow + x * outUDx, - lLine, -inDx, -outLDx, -outUDx, hStart, slope / lLine, uniteUR); - } - - //Update lefts - search for a new line start - inLL = inLR, inUL = inUR; - for (; inLL != inLEnd && sel.areEqual(*inLL, *inUL); inLL += inDx, inUL += inDx) - ; - } - - //Special case: filter the last line in the row - if (inLL != inLEnd) { - //Found a line to process - lLine = (inLR - inLL) / inDx; - - inLL_1 = inLL - inDx, inUL_1 = inUL - inDx; - x = (inLL - inLRow) / inDx; - - uniteUL = sel.areEqual(*inUL, *inLL_1); - uniteLL = sel.areEqual(*inLL, *inUL_1); - if (uniteUL || uniteLL) { - if (uniteUL && uniteLL) - uniteUL = checkNeighbourHood(x, r, inUL, lx, ly, inDx, inDy, sel); - - if (checkLength(lLine, r, ly, inDy, inLL_1, inUL_1, inLL, inUL, uniteUL, do1Line, sel)) - filterLine(inLL, inUL, outLRow + x * outLDx, outURow + x * outUDx, - lLine, inDx, outLDx, outUDx, hStart, slope / (lLine << 1), uniteUL); - } - } +void processLine(int r, int lx, int ly, PIX *inLRow, PIX *inURow, PIX *outLRow, + PIX *outURow, int inDx, int inDy, int outLDx, int outUDx, + bool do1Line, double hStart, double slope, + const SELECTOR &sel) { + // Using a 'horizontal' notation here - but the same applies in vertical too + ++r; + + // As long as we don't reach row end, process uninterrupted separation lines + // between colors + + PIX *inLL = inLRow, *inLR, *inUL = inURow, *inUR; + PIX *inLL_1, *inUL_1, *inLR_1, *inUR_1; + PIX *inLEnd = inLRow + lx * inDx; + int x, lLine; + bool uniteLL, uniteUL, uniteLR, uniteUR; + + // Special case: a line at row start has different weights + if (!sel.areEqual(*inLL, *inUL)) { + // Look for line ends + for (inLR = inLL + inDx, inUR = inUL + inDx; + inLR != inLEnd && sel.areEqual(*inLL, *inLR) && + sel.areEqual(*inUL, *inUR); + inLR += inDx, inUR += inDx) + ; + + if (inLR != inLEnd) { + // Found a line to process + lLine = (inLR - inLL) / inDx; + + inLR_1 = inLR - inDx, inUR_1 = inUR - inDx; + x = (inLR_1 - inLRow) / inDx; + + uniteUR = sel.areEqual(*inUR_1, *inLR); + uniteLR = sel.areEqual(*inLR_1, *inUR); + if (uniteUR || uniteLR) { + if (uniteUR && uniteLR) + // Ambiguous case. Check neighborhood to find out which one must be + // actually united. + uniteUR = + !checkNeighbourHood(x + 1, r, inUR, lx, ly, inDx, inDy, sel); + + if (checkLength(lLine, r, ly, inDy, inLR_1, inUR_1, inLR, inUR, uniteUR, + do1Line, sel)) + filterLine(inLR_1, inUR_1, outLRow + x * outLDx, outURow + x * outUDx, + lLine, -inDx, -outLDx, -outUDx, hStart, + slope / (lLine << 1), uniteUR); + } + } + + // Update lefts + inLL = inLR, inUL = inUR; + } + + // Search for a line start + for (; inLL != inLEnd && sel.areEqual(*inLL, *inUL); + inLL += inDx, inUL += inDx) + ; + + while (inLL != inLEnd) { + // Look for line ends + for (inLR = inLL + inDx, inUR = inUL + inDx; + inLR != inLEnd && sel.areEqual(*inLL, *inLR) && + sel.areEqual(*inUL, *inUR); + inLR += inDx, inUR += inDx) + ; + + if (inLR == inLEnd) break; // Dealt with later + + // Found a line to process + lLine = (inLR - inLL) / inDx; + + // First, filter left to right + inLL_1 = inLL - inDx, inUL_1 = inUL - inDx; + x = (inLL - inLRow) / inDx; + + uniteUL = sel.areEqual(*inUL, *inLL_1); + uniteLL = sel.areEqual(*inLL, *inUL_1); + if (uniteUL || uniteLL) { + if (uniteUL && uniteLL) + uniteUL = checkNeighbourHood(x, r, inUL, lx, ly, inDx, inDy, sel); + + if (checkLength(lLine, r, ly, inDy, inLL_1, inUL_1, inLL, inUL, uniteUL, + do1Line, sel)) + filterLine(inLL, inUL, outLRow + x * outLDx, outURow + x * outUDx, + lLine, inDx, outLDx, outUDx, hStart, slope / lLine, uniteUL); + } + + // Then, filter right to left + inLR_1 = inLR - inDx, inUR_1 = inUR - inDx; + x = (inLR_1 - inLRow) / inDx; + + uniteUR = sel.areEqual(*inUR_1, *inLR); + uniteLR = sel.areEqual(*inLR_1, *inUR); + if (uniteUR || uniteLR) { + if (uniteUR && uniteLR) + uniteUR = !checkNeighbourHood(x + 1, r, inUR, lx, ly, inDx, inDy, sel); + + if (checkLength(lLine, r, ly, inDy, inLR_1, inUR_1, inLR, inUR, uniteUR, + do1Line, sel)) + filterLine(inLR_1, inUR_1, outLRow + x * outLDx, outURow + x * outUDx, + lLine, -inDx, -outLDx, -outUDx, hStart, slope / lLine, + uniteUR); + } + + // Update lefts - search for a new line start + inLL = inLR, inUL = inUR; + for (; inLL != inLEnd && sel.areEqual(*inLL, *inUL); + inLL += inDx, inUL += inDx) + ; + } + + // Special case: filter the last line in the row + if (inLL != inLEnd) { + // Found a line to process + lLine = (inLR - inLL) / inDx; + + inLL_1 = inLL - inDx, inUL_1 = inUL - inDx; + x = (inLL - inLRow) / inDx; + + uniteUL = sel.areEqual(*inUL, *inLL_1); + uniteLL = sel.areEqual(*inLL, *inUL_1); + if (uniteUL || uniteLL) { + if (uniteUL && uniteLL) + uniteUL = checkNeighbourHood(x, r, inUL, lx, ly, inDx, inDy, sel); + + if (checkLength(lLine, r, ly, inDy, inLL_1, inUL_1, inLL, inUL, uniteUL, + do1Line, sel)) + filterLine(inLL, inUL, outLRow + x * outLDx, outURow + x * outUDx, + lLine, inDx, outLDx, outUDx, hStart, slope / (lLine << 1), + uniteUL); + } + } } //--------------------------------------------------------------------------------------- template -void makeAntialias(const TRasterPT &src, TRasterPT &dst, int threshold, int softness) -{ - dst->copy(src); - if (softness == 0) - return; - - double slope = (50.0 / softness); - double hStart = 0.5; //fixed for now - - src->lock(); - dst->lock(); - - PixelSelector sel(threshold); - - //First, filter by rows - int x, y, lx = src->getLx(), ly = src->getLy(), lx_1 = lx - 1, ly_1 = ly - 1; - for (y = 0; y < ly_1; ++y) { - processLine(y, lx, ly, - src->pixels(y), src->pixels(y + 1), - dst->pixels(y), dst->pixels(y + 1), - 1, src->getWrap(), 1, 1, - true, hStart, slope, - sel); - } - - //Then, go by columns - for (x = 0; x < lx_1; ++x) { - processLine(x, ly, lx, - src->pixels(0) + x, src->pixels(0) + x + 1, - dst->pixels(0) + x, dst->pixels(0) + x + 1, - src->getWrap(), 1, dst->getWrap(), dst->getWrap(), - false, hStart, slope, - sel); - } - - dst->unlock(); - src->unlock(); +void makeAntialias(const TRasterPT &src, TRasterPT &dst, + int threshold, int softness) { + dst->copy(src); + if (softness == 0) return; + + double slope = (50.0 / softness); + double hStart = 0.5; // fixed for now + + src->lock(); + dst->lock(); + + PixelSelector sel(threshold); + + // First, filter by rows + int x, y, lx = src->getLx(), ly = src->getLy(), lx_1 = lx - 1, ly_1 = ly - 1; + for (y = 0; y < ly_1; ++y) { + processLine(y, lx, ly, src->pixels(y), src->pixels(y + 1), dst->pixels(y), + dst->pixels(y + 1), 1, src->getWrap(), 1, 1, true, hStart, + slope, sel); + } + + // Then, go by columns + for (x = 0; x < lx_1; ++x) { + processLine(x, ly, lx, src->pixels(0) + x, src->pixels(0) + x + 1, + dst->pixels(0) + x, dst->pixels(0) + x + 1, src->getWrap(), 1, + dst->getWrap(), dst->getWrap(), false, hStart, slope, sel); + } + + dst->unlock(); + src->unlock(); } //--------------------------------------------------------------------------------------- -void TRop::antialias(const TRasterP &src, const TRasterP &dst, int threshold, int softness) -{ - assert(src->getSize() == dst->getSize()); - - TRaster32P src32(src), dst32(dst); - if (src32 && dst32) { - makeAntialias(src32, dst32, threshold, softness); - return; - } - - TRaster64P src64(src), dst64(dst); - if (src64 && dst64) { - makeAntialias(src64, dst64, threshold << 8, softness); - return; - } - - TRasterCM32P srcCM(src), dstCM(dst); - if (srcCM && dstCM) { - makeAntialias(srcCM, dstCM, threshold, softness); - return; - } - - assert(!"Source and destination rasters must be of the same type!"); +void TRop::antialias(const TRasterP &src, const TRasterP &dst, int threshold, + int softness) { + assert(src->getSize() == dst->getSize()); + + TRaster32P src32(src), dst32(dst); + if (src32 && dst32) { + makeAntialias(src32, dst32, threshold, softness); + return; + } + + TRaster64P src64(src), dst64(dst); + if (src64 && dst64) { + makeAntialias(src64, dst64, threshold << 8, softness); + return; + } + + TRasterCM32P srcCM(src), dstCM(dst); + if (srcCM && dstCM) { + makeAntialias(srcCM, dstCM, threshold, softness); + return; + } + + assert(!"Source and destination rasters must be of the same type!"); } diff --git a/toonz/sources/common/trop/tautoclose.cpp b/toonz/sources/common/trop/tautoclose.cpp index eefd152..f14b538 100644 --- a/toonz/sources/common/trop/tautoclose.cpp +++ b/toonz/sources/common/trop/tautoclose.cpp @@ -9,611 +9,593 @@ using namespace SkeletonLut; -class TAutocloser::Imp -{ +class TAutocloser::Imp { public: - struct Seed { - UCHAR *m_ptr; - UCHAR m_preseed; - Seed(UCHAR *ptr, UCHAR preseed) : m_ptr(ptr), m_preseed(preseed) {} - }; - - int m_closingDistance; - double m_spotAngle; - int m_inkIndex; - TRasterP m_raster; - TRasterGR8P m_bRaster; - UCHAR *m_br; - - int m_bWrap; - - int m_displaceVector[8]; - TPointD m_displAverage; - int m_visited; - - double m_csp, m_snp, m_csm, m_snm, m_csa, m_sna, m_csb, m_snb; - - Imp(const TRasterP &r) - : m_raster(r), m_spotAngle((180 * TConsts::pi) / 360.0), m_closingDistance(10), m_inkIndex(0) - { - } - - ~Imp() {} - - bool inline isInk(UCHAR *br) { return (*br) & 0x1; } - inline void eraseInk(UCHAR *br) { *(br) &= 0xfe; } - - UCHAR inline ePix(UCHAR *br) { return (*(br + 1)); } - UCHAR inline wPix(UCHAR *br) { return (*(br - 1)); } - UCHAR inline nPix(UCHAR *br) { return (*(br + m_bWrap)); } - UCHAR inline sPix(UCHAR *br) { return (*(br - m_bWrap)); } - UCHAR inline swPix(UCHAR *br) { return (*(br - m_bWrap - 1)); } - UCHAR inline nwPix(UCHAR *br) { return (*(br + m_bWrap - 1)); } - UCHAR inline nePix(UCHAR *br) { return (*(br + m_bWrap + 1)); } - UCHAR inline sePix(UCHAR *br) { return (*(br - m_bWrap + 1)); } - UCHAR inline neighboursCode(UCHAR *seed) - { - return ((swPix(seed) & 0x1) | ((sPix(seed) & 0x1) << 1) | - ((sePix(seed) & 0x1) << 2) | ((wPix(seed) & 0x1) << 3) | - ((ePix(seed) & 0x1) << 4) | ((nwPix(seed) & 0x1) << 5) | - ((nPix(seed) & 0x1) << 6) | ((nePix(seed) & 0x1) << 7)); - } - - //....................... - - inline bool notMarkedBorderInk(UCHAR *br) - { - return ((((*br) & 0x5) == 1) && (ePix(br) == 0 || wPix(br) == 0 || nPix(br) == 0 || sPix(br) == 0)); - } - - //....................... - UCHAR *getPtr(int x, int y) { return m_br + m_bWrap * y + x; } - UCHAR *getPtr(const TPoint &p) { return m_br + m_bWrap * p.y + p.x; } - - TPoint getCoordinates(UCHAR *br) - { - TPoint p; - int pixelCount = br - m_bRaster->getRawData(); - p.y = pixelCount / m_bWrap; - p.x = pixelCount - p.y * m_bWrap; - return p; - } - - //....................... - void compute(vector &closingSegmentArray); - void skeletonize(vector &endpoints); - void findSeeds(vector &seeds, vector &endpoints); - void erase(vector &seeds, vector &endpoints); - void circuitAndMark(UCHAR *seed, UCHAR preseed); - bool circuitAndCancel(UCHAR *seed, UCHAR preseed, vector &endpoints); - void findMeetingPoints(vector &endpoints, vector &closingSegments); - void calculateWeightAndDirection(vector &orientedEndpoints); - bool spotResearchTwoPoints(vector &endpoints, vector &closingSegments); - bool spotResearchOnePoint(vector &endpoints, vector &closingSegments); - - void copy(const TRasterGR8P &braux, TRaster32P &raux); - int exploreTwoSpots(const TAutocloser::Segment &s0, const TAutocloser::Segment &s1); - int notInsidePath(const TPoint &p, const TPoint &q); - void drawInByteRaster(const TPoint &p0, const TPoint &p1); - TPoint visitEndpoint(UCHAR *br); - bool exploreSpot(const Segment &s, TPoint &p); - bool exploreRay(UCHAR *br, Segment s, TPoint &p); - void visitPix(UCHAR *br, int toVisit, const TPoint &dis); - void cancelMarks(UCHAR *br); - void cancelFromArray(vector &array, TPoint p, int &count); + struct Seed { + UCHAR *m_ptr; + UCHAR m_preseed; + Seed(UCHAR *ptr, UCHAR preseed) : m_ptr(ptr), m_preseed(preseed) {} + }; + + int m_closingDistance; + double m_spotAngle; + int m_inkIndex; + TRasterP m_raster; + TRasterGR8P m_bRaster; + UCHAR *m_br; + + int m_bWrap; + + int m_displaceVector[8]; + TPointD m_displAverage; + int m_visited; + + double m_csp, m_snp, m_csm, m_snm, m_csa, m_sna, m_csb, m_snb; + + Imp(const TRasterP &r) + : m_raster(r) + , m_spotAngle((180 * TConsts::pi) / 360.0) + , m_closingDistance(10) + , m_inkIndex(0) {} + + ~Imp() {} + + bool inline isInk(UCHAR *br) { return (*br) & 0x1; } + inline void eraseInk(UCHAR *br) { *(br) &= 0xfe; } + + UCHAR inline ePix(UCHAR *br) { return (*(br + 1)); } + UCHAR inline wPix(UCHAR *br) { return (*(br - 1)); } + UCHAR inline nPix(UCHAR *br) { return (*(br + m_bWrap)); } + UCHAR inline sPix(UCHAR *br) { return (*(br - m_bWrap)); } + UCHAR inline swPix(UCHAR *br) { return (*(br - m_bWrap - 1)); } + UCHAR inline nwPix(UCHAR *br) { return (*(br + m_bWrap - 1)); } + UCHAR inline nePix(UCHAR *br) { return (*(br + m_bWrap + 1)); } + UCHAR inline sePix(UCHAR *br) { return (*(br - m_bWrap + 1)); } + UCHAR inline neighboursCode(UCHAR *seed) { + return ((swPix(seed) & 0x1) | ((sPix(seed) & 0x1) << 1) | + ((sePix(seed) & 0x1) << 2) | ((wPix(seed) & 0x1) << 3) | + ((ePix(seed) & 0x1) << 4) | ((nwPix(seed) & 0x1) << 5) | + ((nPix(seed) & 0x1) << 6) | ((nePix(seed) & 0x1) << 7)); + } + + //....................... + + inline bool notMarkedBorderInk(UCHAR *br) { + return ((((*br) & 0x5) == 1) && + (ePix(br) == 0 || wPix(br) == 0 || nPix(br) == 0 || sPix(br) == 0)); + } + + //....................... + UCHAR *getPtr(int x, int y) { return m_br + m_bWrap * y + x; } + UCHAR *getPtr(const TPoint &p) { return m_br + m_bWrap * p.y + p.x; } + + TPoint getCoordinates(UCHAR *br) { + TPoint p; + int pixelCount = br - m_bRaster->getRawData(); + p.y = pixelCount / m_bWrap; + p.x = pixelCount - p.y * m_bWrap; + return p; + } + + //....................... + void compute(vector &closingSegmentArray); + void skeletonize(vector &endpoints); + void findSeeds(vector &seeds, vector &endpoints); + void erase(vector &seeds, vector &endpoints); + void circuitAndMark(UCHAR *seed, UCHAR preseed); + bool circuitAndCancel(UCHAR *seed, UCHAR preseed, vector &endpoints); + void findMeetingPoints(vector &endpoints, + vector &closingSegments); + void calculateWeightAndDirection(vector &orientedEndpoints); + bool spotResearchTwoPoints(vector &endpoints, + vector &closingSegments); + bool spotResearchOnePoint(vector &endpoints, + vector &closingSegments); + + void copy(const TRasterGR8P &braux, TRaster32P &raux); + int exploreTwoSpots(const TAutocloser::Segment &s0, + const TAutocloser::Segment &s1); + int notInsidePath(const TPoint &p, const TPoint &q); + void drawInByteRaster(const TPoint &p0, const TPoint &p1); + TPoint visitEndpoint(UCHAR *br); + bool exploreSpot(const Segment &s, TPoint &p); + bool exploreRay(UCHAR *br, Segment s, TPoint &p); + void visitPix(UCHAR *br, int toVisit, const TPoint &dis); + void cancelMarks(UCHAR *br); + void cancelFromArray(vector &array, TPoint p, int &count); }; /*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/ -#define DRAW_SEGMENT(a, b, da, db, istr1, istr2, block) \ - { \ - d = 2 * db - da; \ - incr_1 = 2 * db; \ - incr_2 = 2 * (db - da); \ - while (a < da) { \ - if (d <= 0) { \ - d += incr_1; \ - a++; \ - istr1; \ - } else { \ - d += incr_2; \ - a++; \ - b++; \ - istr2; \ - } \ - block; \ - } \ - } +#define DRAW_SEGMENT(a, b, da, db, istr1, istr2, block) \ + { \ + d = 2 * db - da; \ + incr_1 = 2 * db; \ + incr_2 = 2 * (db - da); \ + while (a < da) { \ + if (d <= 0) { \ + d += incr_1; \ + a++; \ + istr1; \ + } else { \ + d += incr_2; \ + a++; \ + b++; \ + istr2; \ + } \ + block; \ + } \ + } /*------------------------------------------------------------------------*/ -#define EXPLORE_RAY_ISTR(istr) \ - if (!inside_ink) { \ - if (((*br) & 0x1) && !((*br) & 0x80)) { \ - p.x = istr; \ - p.y = (s.first.y < s.second.y) ? s.first.y + y : s.first.y - y; \ - return true; \ - } \ - } else if (inside_ink && !((*br) & 0x1)) \ - inside_ink = 0; +#define EXPLORE_RAY_ISTR(istr) \ + if (!inside_ink) { \ + if (((*br) & 0x1) && !((*br) & 0x80)) { \ + p.x = istr; \ + p.y = (s.first.y < s.second.y) ? s.first.y + y : s.first.y - y; \ + return true; \ + } \ + } else if (inside_ink && !((*br) & 0x1)) \ + inside_ink = 0; /*------------------------------------------------------------------------*/ //------------------------------------------------- -namespace -{ +namespace { -inline bool isInk(const TPixel32 &pix) -{ - return pix.r < 80; -} +inline bool isInk(const TPixel32 &pix) { return pix.r < 80; } /*------------------------------------------------------------------------*/ -TRasterGR8P makeByteRaster(const TRasterCM32P &r) -{ - int lx = r->getLx(); - int ly = r->getLy(); - TRasterGR8P bRaster(lx + 4, ly + 4); - int i, j; - - //bRaster->create(lx+4, ly+4); - bRaster->lock(); - UCHAR *br = bRaster->getRawData(); - - for (i = 0; i < lx + 4; i++) - *(br++) = 0; - - for (i = 0; i < lx + 4; i++) - *(br++) = 131; - - r->lock(); - for (i = 0; i < ly; i++) { - *(br++) = 0; - *(br++) = 131; - TPixelCM32 *pix = r->pixels(i); - for (j = 0; j < lx; j++, pix++) { - if (pix->getTone() != pix->getMaxTone()) - *(br++) = 3; - else - *(br++) = 0; - } - *(br++) = 131; - *(br++) = 0; - } - r->unlock(); - for (i = 0; i < lx + 4; i++) - *(br++) = 131; - - for (i = 0; i < lx + 4; i++) - *(br++) = 0; - - bRaster->unlock(); - return bRaster; +TRasterGR8P makeByteRaster(const TRasterCM32P &r) { + int lx = r->getLx(); + int ly = r->getLy(); + TRasterGR8P bRaster(lx + 4, ly + 4); + int i, j; + + // bRaster->create(lx+4, ly+4); + bRaster->lock(); + UCHAR *br = bRaster->getRawData(); + + for (i = 0; i < lx + 4; i++) *(br++) = 0; + + for (i = 0; i < lx + 4; i++) *(br++) = 131; + + r->lock(); + for (i = 0; i < ly; i++) { + *(br++) = 0; + *(br++) = 131; + TPixelCM32 *pix = r->pixels(i); + for (j = 0; j < lx; j++, pix++) { + if (pix->getTone() != pix->getMaxTone()) + *(br++) = 3; + else + *(br++) = 0; + } + *(br++) = 131; + *(br++) = 0; + } + r->unlock(); + for (i = 0; i < lx + 4; i++) *(br++) = 131; + + for (i = 0; i < lx + 4; i++) *(br++) = 0; + + bRaster->unlock(); + return bRaster; } /*------------------------------------------------------------------------*/ -#define SET_INK \ - if (buf->getTone() == buf->getMaxTone()) \ - *buf = TPixelCM32(inkIndex, 22, 0); +#define SET_INK \ + if (buf->getTone() == buf->getMaxTone()) *buf = TPixelCM32(inkIndex, 22, 0); -void drawSegment(TRasterCM32P &r, const TAutocloser::Segment &s, USHORT inkIndex) -{ - int wrap = r->getWrap(); - TPixelCM32 *buf = r->pixels(); - /* +void drawSegment(TRasterCM32P &r, const TAutocloser::Segment &s, + USHORT inkIndex) { + int wrap = r->getWrap(); + TPixelCM32 *buf = r->pixels(); + /* int i, j; for (i=0; igetLy();i++) - { - for (j=0; jgetLx();j++, buf++) - *buf = (1<<4)|0xf; - buf += wrap-r->getLx(); - } +{ + for (j=0; jgetLx();j++, buf++) +*buf = (1<<4)|0xf; +buf += wrap-r->getLx(); + } return; */ - int x, y, dx, dy, d, incr_1, incr_2; - - int x1 = s.first.x; - int y1 = s.first.y; - int x2 = s.second.x; - int y2 = s.second.y; - - if (x1 > x2) { - tswap(x1, x2); - tswap(y1, y2); - } - - buf += y1 * wrap + x1; - - dx = x2 - x1; - dy = y2 - y1; - - x = y = 0; - - if (dy >= 0) { - if (dy <= dx) - DRAW_SEGMENT(x, y, dx, dy, (buf++), (buf += wrap + 1), SET_INK) - else - DRAW_SEGMENT(y, x, dy, dx, (buf += wrap), (buf += wrap + 1), SET_INK) - } else { - dy = -dy; - if (dy <= dx) - DRAW_SEGMENT(x, y, dx, dy, (buf++), (buf -= (wrap - 1)), SET_INK) - else - DRAW_SEGMENT(y, x, dy, dx, (buf -= wrap), (buf -= (wrap - 1)), SET_INK) - } -} - -/*------------------------------------------------------------------------*/ - -} //namespace -/*------------------------------------------------------------------------*/ - -void TAutocloser::Imp::compute(vector &closingSegmentArray) -{ - vector endpoints; - try { - - assert(closingSegmentArray.empty()); + int x, y, dx, dy, d, incr_1, incr_2; - TRasterCM32P raux; + int x1 = s.first.x; + int y1 = s.first.y; + int x2 = s.second.x; + int y2 = s.second.y; - if (!(raux = (TRasterCM32P)m_raster)) - throw TException("Unable to autoclose a not CM32 image."); + if (x1 > x2) { + tswap(x1, x2); + tswap(y1, y2); + } - if (m_raster->getLx() == 0 || m_raster->getLy() == 0) - throw TException("Autoclose error: bad image size"); + buf += y1 * wrap + x1; - //Lx = r->lx; - //Ly = r->ly; + dx = x2 - x1; + dy = y2 - y1; - TRasterGR8P braux = makeByteRaster(raux); + x = y = 0; - m_bRaster = braux->extract(TRect(2, 2, braux->getLx() - 3, braux->getLy() - 3)); - m_bRaster->lock(); - m_br = m_bRaster->getRawData(); - m_bWrap = m_bRaster->getWrap(); + if (dy >= 0) { + if (dy <= dx) + DRAW_SEGMENT(x, y, dx, dy, (buf++), (buf += wrap + 1), SET_INK) + else + DRAW_SEGMENT(y, x, dy, dx, (buf += wrap), (buf += wrap + 1), SET_INK) + } else { + dy = -dy; + if (dy <= dx) + DRAW_SEGMENT(x, y, dx, dy, (buf++), (buf -= (wrap - 1)), SET_INK) + else + DRAW_SEGMENT(y, x, dy, dx, (buf -= wrap), (buf -= (wrap - 1)), SET_INK) + } +} - m_displaceVector[0] = -m_bWrap - 1; - m_displaceVector[1] = -m_bWrap; - m_displaceVector[2] = -m_bWrap + 1; - m_displaceVector[3] = -1; - m_displaceVector[4] = +1; - m_displaceVector[5] = m_bWrap - 1; - m_displaceVector[6] = m_bWrap; - m_displaceVector[7] = m_bWrap + 1; +/*------------------------------------------------------------------------*/ - skeletonize(endpoints); +} // namespace +/*------------------------------------------------------------------------*/ - findMeetingPoints(endpoints, closingSegmentArray); - raux->lock(); - for (int i = 0; i < (int)closingSegmentArray.size(); i++) - drawSegment(raux, closingSegmentArray[i], m_inkIndex); - raux->unlock(); - //copy(m_bRaster, raux); - m_bRaster->unlock(); - m_br = 0; - } +void TAutocloser::Imp::compute(vector &closingSegmentArray) { + vector endpoints; + try { + assert(closingSegmentArray.empty()); + + TRasterCM32P raux; + + if (!(raux = (TRasterCM32P)m_raster)) + throw TException("Unable to autoclose a not CM32 image."); + + if (m_raster->getLx() == 0 || m_raster->getLy() == 0) + throw TException("Autoclose error: bad image size"); + + // Lx = r->lx; + // Ly = r->ly; + + TRasterGR8P braux = makeByteRaster(raux); + + m_bRaster = + braux->extract(TRect(2, 2, braux->getLx() - 3, braux->getLy() - 3)); + m_bRaster->lock(); + m_br = m_bRaster->getRawData(); + m_bWrap = m_bRaster->getWrap(); + + m_displaceVector[0] = -m_bWrap - 1; + m_displaceVector[1] = -m_bWrap; + m_displaceVector[2] = -m_bWrap + 1; + m_displaceVector[3] = -1; + m_displaceVector[4] = +1; + m_displaceVector[5] = m_bWrap - 1; + m_displaceVector[6] = m_bWrap; + m_displaceVector[7] = m_bWrap + 1; + + skeletonize(endpoints); + + findMeetingPoints(endpoints, closingSegmentArray); + raux->lock(); + for (int i = 0; i < (int)closingSegmentArray.size(); i++) + drawSegment(raux, closingSegmentArray[i], m_inkIndex); + raux->unlock(); + // copy(m_bRaster, raux); + m_bRaster->unlock(); + m_br = 0; + } - catch (TException &e) { - throw e; - } + catch (TException &e) { + throw e; + } } /*------------------------------------------------------------------------*/ -void TAutocloser::Imp::copy(const TRasterGR8P &br, TRaster32P &r) -{ - assert(r->getLx() == br->getLx() && r->getLy() == br->getLy()); - int i, j; - - int lx = r->getLx(); - int ly = r->getLy(); - br->lock(); - r->lock(); - UCHAR *bbuf = br->getRawData(); - TPixel *buf = (TPixel *)r->getRawData(); - - for (i = 0; i < ly; i++) { - for (j = 0; j < lx; j++, buf++, bbuf++) { - buf->m = 255; - if ((*bbuf) & 0x40) - buf->r = 255, buf->g = buf->b = 0; - else if (isInk(bbuf)) - buf->r = buf->g = buf->b = 0; - else - buf->r = buf->g = buf->b = 255; - } - buf += r->getWrap() - lx; - bbuf += br->getWrap() - lx; - } - - br->unlock(); - r->unlock(); +void TAutocloser::Imp::copy(const TRasterGR8P &br, TRaster32P &r) { + assert(r->getLx() == br->getLx() && r->getLy() == br->getLy()); + int i, j; + + int lx = r->getLx(); + int ly = r->getLy(); + br->lock(); + r->lock(); + UCHAR *bbuf = br->getRawData(); + TPixel *buf = (TPixel *)r->getRawData(); + + for (i = 0; i < ly; i++) { + for (j = 0; j < lx; j++, buf++, bbuf++) { + buf->m = 255; + if ((*bbuf) & 0x40) + buf->r = 255, buf->g = buf->b = 0; + else if (isInk(bbuf)) + buf->r = buf->g = buf->b = 0; + else + buf->r = buf->g = buf->b = 255; + } + buf += r->getWrap() - lx; + bbuf += br->getWrap() - lx; + } + + br->unlock(); + r->unlock(); } /*=============================================================================*/ -namespace -{ +namespace { -int intersect_segment(int x1, int y1, int x2, int y2, int i, double *ris) -{ - if ((i < tmin(y1, y2)) || (i > tmax(y1, y2)) || (y1 == y2)) - return 0; +int intersect_segment(int x1, int y1, int x2, int y2, int i, double *ris) { + if ((i < tmin(y1, y2)) || (i > tmax(y1, y2)) || (y1 == y2)) return 0; - *ris = ((double)((x1 - x2) * (i - y2)) / (double)(y1 - y2) + x2); + *ris = ((double)((x1 - x2) * (i - y2)) / (double)(y1 - y2) + x2); - return 1; + return 1; } /*=============================================================================*/ -inline int distance2(const TPoint p0, const TPoint p1) -{ - return (p0.x - p1.x) * (p0.x - p1.x) + (p0.y - p1.y) * (p0.y - p1.y); +inline int distance2(const TPoint p0, const TPoint p1) { + return (p0.x - p1.x) * (p0.x - p1.x) + (p0.y - p1.y) * (p0.y - p1.y); } /*=============================================================================*/ -int closerPoint(const vector &points, vector &marks, int index) -{ - assert(points.size() == marks.size()); +int closerPoint(const vector &points, vector &marks, + int index) { + assert(points.size() == marks.size()); - int min, curr; - int minval = 9999999; + int min, curr; + int minval = 9999999; - min = index + 1; + min = index + 1; - for (curr = index + 1; curr < (int)points.size(); curr++) - if (!(marks[curr])) { - int distance = distance2(points[index].first, points[curr].first); + for (curr = index + 1; curr < (int)points.size(); curr++) + if (!(marks[curr])) { + int distance = distance2(points[index].first, points[curr].first); - if (distance < minval) { - minval = distance; - min = curr; - } - } + if (distance < minval) { + minval = distance; + min = curr; + } + } - marks[min] = true; - return min; + marks[min] = true; + return min; } /*------------------------------------------------------------------------*/ int intersect_triangle(int x1a, int y1a, int x2a, int y2a, int x3a, int y3a, - int x1b, int y1b, int x2b, int y2b, int x3b, int y3b) -{ - int minx, maxx, miny, maxy, i; - double xamin, xamax, xbmin, xbmax, val; + int x1b, int y1b, int x2b, int y2b, int x3b, int y3b) { + int minx, maxx, miny, maxy, i; + double xamin, xamax, xbmin, xbmax, val; - miny = tmax(tmin(y1a, y2a, y3a), tmin(y1b, y2b, y3b)); - maxy = tmin(tmax(y1a, y2a, y3a), tmax(y1b, y2b, y3b)); - if (maxy < miny) - return 0; + miny = tmax(tmin(y1a, y2a, y3a), tmin(y1b, y2b, y3b)); + maxy = tmin(tmax(y1a, y2a, y3a), tmax(y1b, y2b, y3b)); + if (maxy < miny) return 0; - minx = tmax(tmin(x1a, x2a, x3a), tmin(x1b, x2b, x3b)); - maxx = tmin(tmax(x1a, x2a, x3a), tmax(x1b, x2b, x3b)); - if (maxx < minx) - return 0; + minx = tmax(tmin(x1a, x2a, x3a), tmin(x1b, x2b, x3b)); + maxx = tmin(tmax(x1a, x2a, x3a), tmax(x1b, x2b, x3b)); + if (maxx < minx) return 0; - for (i = miny; i <= maxy; i++) { - xamin = xamax = xbmin = xbmax = 0.0; + for (i = miny; i <= maxy; i++) { + xamin = xamax = xbmin = xbmax = 0.0; - intersect_segment(x1a, y1a, x2a, y2a, i, &xamin); + intersect_segment(x1a, y1a, x2a, y2a, i, &xamin); - if (intersect_segment(x1a, y1a, x3a, y3a, i, &val)) - if (xamin) - xamax = val; - else - xamin = val; + if (intersect_segment(x1a, y1a, x3a, y3a, i, &val)) + if (xamin) + xamax = val; + else + xamin = val; - if (!xamax) - intersect_segment(x2a, y2a, x3a, y3a, i, &xamax); + if (!xamax) intersect_segment(x2a, y2a, x3a, y3a, i, &xamax); - if (xamax < xamin) { - val = xamin, xamin = xamax, xamax = val; - } + if (xamax < xamin) { + val = xamin, xamin = xamax, xamax = val; + } - intersect_segment(x1b, y1b, x2b, y2b, i, &xbmin); + intersect_segment(x1b, y1b, x2b, y2b, i, &xbmin); - if (intersect_segment(x1b, y1b, x3b, y3b, i, &val)) - if (xbmin) - xbmax = val; - else - xbmin = val; + if (intersect_segment(x1b, y1b, x3b, y3b, i, &val)) + if (xbmin) + xbmax = val; + else + xbmin = val; - if (!xbmax) - intersect_segment(x2b, y2b, x3b, y3b, i, &xbmax); + if (!xbmax) intersect_segment(x2b, y2b, x3b, y3b, i, &xbmax); - if (xbmax < xbmin) { - val = xbmin, xbmin = xbmax, xbmax = val; - } + if (xbmax < xbmin) { + val = xbmin, xbmin = xbmax, xbmax = val; + } - if (!((tceil(xamax) < tfloor(xbmin)) || (tceil(xbmax) < tfloor(xamin)))) - return 1; - } - return 0; + if (!((tceil(xamax) < tfloor(xbmin)) || (tceil(xbmax) < tfloor(xamin)))) + return 1; + } + return 0; } /*------------------------------------------------------------------------*/ -} //namespace +} // namespace /*------------------------------------------------------------------------*/ -int TAutocloser::Imp::notInsidePath(const TPoint &p, const TPoint &q) -{ - int tmp, x, y, dx, dy, d, incr_1, incr_2; - int x1, y1, x2, y2; - - x1 = p.x; - y1 = p.y; - x2 = q.x; - y2 = q.y; - - if (x1 > x2) { - tmp = x1, x1 = x2, x2 = tmp; - tmp = y1, y1 = y2, y2 = tmp; - } - UCHAR *br = getPtr(x1, y1); - - dx = x2 - x1; - dy = y2 - y1; - x = y = 0; - - if (dy >= 0) { - if (dy <= dx) - DRAW_SEGMENT(x, y, dx, dy, (br++), (br += m_bWrap + 1), if (!((*br) & 0x2)) return true) - else - DRAW_SEGMENT(y, x, dy, dx, (br += m_bWrap), (br += m_bWrap + 1), if (!((*br) & 0x2)) return true) - } else { - dy = -dy; - if (dy <= dx) - DRAW_SEGMENT(x, y, dx, dy, (br++), (br -= m_bWrap - 1), if (!((*br) & 0x2)) return true) - else - DRAW_SEGMENT(y, x, dy, dx, (br -= m_bWrap), (br -= m_bWrap - 1), if (!((*br) & 0x2)) return true) - } - - return 0; +int TAutocloser::Imp::notInsidePath(const TPoint &p, const TPoint &q) { + int tmp, x, y, dx, dy, d, incr_1, incr_2; + int x1, y1, x2, y2; + + x1 = p.x; + y1 = p.y; + x2 = q.x; + y2 = q.y; + + if (x1 > x2) { + tmp = x1, x1 = x2, x2 = tmp; + tmp = y1, y1 = y2, y2 = tmp; + } + UCHAR *br = getPtr(x1, y1); + + dx = x2 - x1; + dy = y2 - y1; + x = y = 0; + + if (dy >= 0) { + if (dy <= dx) + DRAW_SEGMENT(x, y, dx, dy, (br++), (br += m_bWrap + 1), + if (!((*br) & 0x2)) return true) + else + DRAW_SEGMENT(y, x, dy, dx, (br += m_bWrap), (br += m_bWrap + 1), + if (!((*br) & 0x2)) return true) + } else { + dy = -dy; + if (dy <= dx) + DRAW_SEGMENT(x, y, dx, dy, (br++), (br -= m_bWrap - 1), + if (!((*br) & 0x2)) return true) + else + DRAW_SEGMENT(y, x, dy, dx, (br -= m_bWrap), (br -= m_bWrap - 1), + if (!((*br) & 0x2)) return true) + } + + return 0; } /*------------------------------------------------------------------------*/ -int TAutocloser::Imp::exploreTwoSpots(const TAutocloser::Segment &s0, const TAutocloser::Segment &s1) -{ - int x1a, y1a, x2a, y2a, x3a, y3a, x1b, y1b, x2b, y2b, x3b, y3b; - - x1a = s0.first.x; - y1a = s0.first.y; - x1b = s1.first.x; - y1b = s1.first.y; - - TPoint p0aux = s0.second; - TPoint p1aux = s1.second; - - if (x1a == p0aux.x && y1a == p0aux.y) - return 0; - if (x1b == p1aux.x && y1b == p1aux.y) - return 0; - - x2a = tround(x1a + (p0aux.x - x1a) * m_csp - (p0aux.y - y1a) * m_snp); - y2a = tround(y1a + (p0aux.x - x1a) * m_snp + (p0aux.y - y1a) * m_csp); - x3a = tround(x1a + (p0aux.x - x1a) * m_csm - (p0aux.y - y1a) * m_snm); - y3a = tround(y1a + (p0aux.x - x1a) * m_snm + (p0aux.y - y1a) * m_csm); - - x2b = tround(x1b + (p1aux.x - x1b) * m_csp - (p1aux.y - y1b) * m_snp); - y2b = tround(y1b + (p1aux.x - x1b) * m_snp + (p1aux.y - y1b) * m_csp); - x3b = tround(x1b + (p1aux.x - x1b) * m_csm - (p1aux.y - y1b) * m_snm); - y3b = tround(y1b + (p1aux.x - x1b) * m_snm + (p1aux.y - y1b) * m_csm); - - return (intersect_triangle(x1a, y1a, p0aux.x, p0aux.y, x2a, y2a, - x1b, y1b, p1aux.x, p1aux.y, x2b, y2b) || - intersect_triangle(x1a, y1a, p0aux.x, p0aux.y, x3a, y3a, - x1b, y1b, p1aux.x, p1aux.y, x2b, y2b) || - intersect_triangle(x1a, y1a, p0aux.x, p0aux.y, x2a, y2a, - x1b, y1b, p1aux.x, p1aux.y, x3b, y3b) || - intersect_triangle(x1a, y1a, p0aux.x, p0aux.y, x3a, y3a, - x1b, y1b, p1aux.x, p1aux.y, x3b, y3b)); +int TAutocloser::Imp::exploreTwoSpots(const TAutocloser::Segment &s0, + const TAutocloser::Segment &s1) { + int x1a, y1a, x2a, y2a, x3a, y3a, x1b, y1b, x2b, y2b, x3b, y3b; + + x1a = s0.first.x; + y1a = s0.first.y; + x1b = s1.first.x; + y1b = s1.first.y; + + TPoint p0aux = s0.second; + TPoint p1aux = s1.second; + + if (x1a == p0aux.x && y1a == p0aux.y) return 0; + if (x1b == p1aux.x && y1b == p1aux.y) return 0; + + x2a = tround(x1a + (p0aux.x - x1a) * m_csp - (p0aux.y - y1a) * m_snp); + y2a = tround(y1a + (p0aux.x - x1a) * m_snp + (p0aux.y - y1a) * m_csp); + x3a = tround(x1a + (p0aux.x - x1a) * m_csm - (p0aux.y - y1a) * m_snm); + y3a = tround(y1a + (p0aux.x - x1a) * m_snm + (p0aux.y - y1a) * m_csm); + + x2b = tround(x1b + (p1aux.x - x1b) * m_csp - (p1aux.y - y1b) * m_snp); + y2b = tround(y1b + (p1aux.x - x1b) * m_snp + (p1aux.y - y1b) * m_csp); + x3b = tround(x1b + (p1aux.x - x1b) * m_csm - (p1aux.y - y1b) * m_snm); + y3b = tround(y1b + (p1aux.x - x1b) * m_snm + (p1aux.y - y1b) * m_csm); + + return (intersect_triangle(x1a, y1a, p0aux.x, p0aux.y, x2a, y2a, x1b, y1b, + p1aux.x, p1aux.y, x2b, y2b) || + intersect_triangle(x1a, y1a, p0aux.x, p0aux.y, x3a, y3a, x1b, y1b, + p1aux.x, p1aux.y, x2b, y2b) || + intersect_triangle(x1a, y1a, p0aux.x, p0aux.y, x2a, y2a, x1b, y1b, + p1aux.x, p1aux.y, x3b, y3b) || + intersect_triangle(x1a, y1a, p0aux.x, p0aux.y, x3a, y3a, x1b, y1b, + p1aux.x, p1aux.y, x3b, y3b)); } /*------------------------------------------------------------------------*/ void TAutocloser::Imp::findMeetingPoints(vector &endpoints, - vector &closingSegments) -{ - int i; - double alfa; - alfa = m_spotAngle / AUT_SPOT_SAMPLES; - m_csp = cos(m_spotAngle / 5); - m_snp = sin(m_spotAngle / 5); - m_csm = cos(-m_spotAngle / 5); - m_snm = sin(-m_spotAngle / 5); - m_csa = cos(alfa); - m_sna = sin(alfa); - m_csb = cos(-alfa); - m_snb = sin(-alfa); - - vector orientedEndpoints(endpoints.size()); - for (i = 0; i < (int)endpoints.size(); i++) - orientedEndpoints[i].first = endpoints[i]; - - int size = -1; - - while ((int)closingSegments.size() > size && !orientedEndpoints.empty()) { - size = closingSegments.size(); - do - calculateWeightAndDirection(orientedEndpoints); - while (spotResearchTwoPoints(orientedEndpoints, closingSegments)); - - do - calculateWeightAndDirection(orientedEndpoints); - while (spotResearchOnePoint(orientedEndpoints, closingSegments)); - } + vector &closingSegments) { + int i; + double alfa; + alfa = m_spotAngle / AUT_SPOT_SAMPLES; + m_csp = cos(m_spotAngle / 5); + m_snp = sin(m_spotAngle / 5); + m_csm = cos(-m_spotAngle / 5); + m_snm = sin(-m_spotAngle / 5); + m_csa = cos(alfa); + m_sna = sin(alfa); + m_csb = cos(-alfa); + m_snb = sin(-alfa); + + vector orientedEndpoints(endpoints.size()); + for (i = 0; i < (int)endpoints.size(); i++) + orientedEndpoints[i].first = endpoints[i]; + + int size = -1; + + while ((int)closingSegments.size() > size && !orientedEndpoints.empty()) { + size = closingSegments.size(); + do + calculateWeightAndDirection(orientedEndpoints); + while (spotResearchTwoPoints(orientedEndpoints, closingSegments)); + + do + calculateWeightAndDirection(orientedEndpoints); + while (spotResearchOnePoint(orientedEndpoints, closingSegments)); + } } /*------------------------------------------------------------------------*/ -bool allMarked(const vector &marks, int index) -{ - int i; +bool allMarked(const vector &marks, int index) { + int i; - for (i = index + 1; i < (int)marks.size(); i++) - if (!marks[i]) - return false; - return true; + for (i = index + 1; i < (int)marks.size(); i++) + if (!marks[i]) return false; + return true; } /*------------------------------------------------------------------------*/ -bool TAutocloser::Imp::spotResearchTwoPoints(vector &endpoints, vector &closingSegments) -{ - int i, distance, current = 0, closerIndex; - int sqrDistance = m_closingDistance * m_closingDistance; - bool found = 0; - vector marks(endpoints.size()); - - while (current < (int)endpoints.size() - 1) { - found = 0; - for (i = current + 1; i < (int)marks.size(); i++) - marks[i] = false; - distance = 0; - - while (!found && (distance <= sqrDistance) && !allMarked(marks, current)) { - closerIndex = closerPoint(endpoints, marks, current); - if (exploreTwoSpots(endpoints[current], endpoints[closerIndex]) && - notInsidePath(endpoints[current].first, endpoints[closerIndex].first)) { - drawInByteRaster(endpoints[current].first, endpoints[closerIndex].first); - closingSegments.push_back(Segment(endpoints[current].first, endpoints[closerIndex].first)); - - if (!EndpointTable[neighboursCode(getPtr(endpoints[closerIndex].first))]) { - std::vector::iterator it = endpoints.begin(); - std::advance(it, closerIndex); - endpoints.erase(it); - std::vector::iterator it1 = marks.begin(); - std::advance(it1, closerIndex); - marks.erase(it1); - } - found = true; - } - } - - if (found) { - std::vector::iterator it = endpoints.begin(); - std::advance(it, current); - endpoints.erase(it); - std::vector::iterator it1 = marks.begin(); - std::advance(it1, current); - marks.erase(it1); - } else - current++; - } - return found; +bool TAutocloser::Imp::spotResearchTwoPoints(vector &endpoints, + vector &closingSegments) { + int i, distance, current = 0, closerIndex; + int sqrDistance = m_closingDistance * m_closingDistance; + bool found = 0; + vector marks(endpoints.size()); + + while (current < (int)endpoints.size() - 1) { + found = 0; + for (i = current + 1; i < (int)marks.size(); i++) marks[i] = false; + distance = 0; + + while (!found && (distance <= sqrDistance) && !allMarked(marks, current)) { + closerIndex = closerPoint(endpoints, marks, current); + if (exploreTwoSpots(endpoints[current], endpoints[closerIndex]) && + notInsidePath(endpoints[current].first, + endpoints[closerIndex].first)) { + drawInByteRaster(endpoints[current].first, + endpoints[closerIndex].first); + closingSegments.push_back( + Segment(endpoints[current].first, endpoints[closerIndex].first)); + + if (!EndpointTable[neighboursCode( + getPtr(endpoints[closerIndex].first))]) { + std::vector::iterator it = endpoints.begin(); + std::advance(it, closerIndex); + endpoints.erase(it); + std::vector::iterator it1 = marks.begin(); + std::advance(it1, closerIndex); + marks.erase(it1); + } + found = true; + } + } + + if (found) { + std::vector::iterator it = endpoints.begin(); + std::advance(it, current); + endpoints.erase(it); + std::vector::iterator it1 = marks.begin(); + std::advance(it1, current); + marks.erase(it1); + } else + current++; + } + return found; } /*------------------------------------------------------------------------*/ @@ -641,211 +623,217 @@ return 0; /*------------------------------------------------------------------------*/ -void TAutocloser::Imp::calculateWeightAndDirection(vector &orientedEndpoints) +void TAutocloser::Imp::calculateWeightAndDirection( + vector &orientedEndpoints) { + // UCHAR *br; + int lx = m_raster->getLx(); + int ly = m_raster->getLy(); + + std::vector::iterator it = orientedEndpoints.begin(); + + while (it != orientedEndpoints.end()) { + TPoint p0 = it->first; + TPoint &p1 = it->second; + + // br = (UCHAR *)m_bRaster->pixels(p0.y)+p0.x; + // code = neighboursCode(br); + /*if (!EndpointTable[code]) { - //UCHAR *br; - int lx = m_raster->getLx(); - int ly = m_raster->getLy(); - - std::vector::iterator it = orientedEndpoints.begin(); - - while (it != orientedEndpoints.end()) { - TPoint p0 = it->first; - TPoint &p1 = it->second; - - //br = (UCHAR *)m_bRaster->pixels(p0.y)+p0.x; - //code = neighboursCode(br); - /*if (!EndpointTable[code]) - { - it = orientedEndpoints.erase(it); - continue; - }*/ - TPoint displAverage = visitEndpoint(getPtr(p0)); - - p1 = p0 - displAverage; - - /*if ((point->x2<0 && point->y2<0) || (point->x2>Lx && point->y2>Ly)) printf("che palle!!!!!!\n");*/ - - if (p1.x < 0) { - p1.y = tround(p0.y - (float)((p0.y - p1.y) * p0.x) / (p0.x - p1.x)); - p1.x = 0; - } else if (p1.x > lx) { - p1.y = tround(p0.y - (float)((p0.y - p1.y) * (p0.x - lx)) / (p0.x - p1.x)); - p1.x = lx; - } - - if (p1.y < 0) { - p1.x = tround(p0.x - (float)((p0.x - p1.x) * p0.y) / (p0.y - p1.y)); - p1.y = 0; - } else if (p1.y > ly) { - p1.x = tround(p0.x - (float)((p0.x - p1.x) * (p0.y - ly)) / (p0.y - p1.y)); - p1.y = ly; - } - it++; - } +it = orientedEndpoints.erase(it); +continue; +}*/ + TPoint displAverage = visitEndpoint(getPtr(p0)); + + p1 = p0 - displAverage; + + /*if ((point->x2<0 && point->y2<0) || (point->x2>Lx && point->y2>Ly)) + * printf("che palle!!!!!!\n");*/ + + if (p1.x < 0) { + p1.y = tround(p0.y - (float)((p0.y - p1.y) * p0.x) / (p0.x - p1.x)); + p1.x = 0; + } else if (p1.x > lx) { + p1.y = + tround(p0.y - (float)((p0.y - p1.y) * (p0.x - lx)) / (p0.x - p1.x)); + p1.x = lx; + } + + if (p1.y < 0) { + p1.x = tround(p0.x - (float)((p0.x - p1.x) * p0.y) / (p0.y - p1.y)); + p1.y = 0; + } else if (p1.y > ly) { + p1.x = + tround(p0.x - (float)((p0.x - p1.x) * (p0.y - ly)) / (p0.y - p1.y)); + p1.y = ly; + } + it++; + } } /*------------------------------------------------------------------------*/ -bool TAutocloser::Imp::spotResearchOnePoint(vector &endpoints, vector &closingSegments) -{ - int count = 0; - bool ret = false; - - while (count < (int)endpoints.size()) { - TPoint p; - - if (exploreSpot(endpoints[count], p)) { - ret = true; - drawInByteRaster(endpoints[count].first, p); - closingSegments.push_back(Segment(endpoints[count].first, p)); - cancelFromArray(endpoints, p, count); - if (!EndpointTable[neighboursCode(getPtr(endpoints[count].first))]) { - std::vector::iterator it = endpoints.begin(); - std::advance(it, count); - endpoints.erase(it); - continue; - } - } - count++; - } - - return ret; +bool TAutocloser::Imp::spotResearchOnePoint(vector &endpoints, + vector &closingSegments) { + int count = 0; + bool ret = false; + + while (count < (int)endpoints.size()) { + TPoint p; + + if (exploreSpot(endpoints[count], p)) { + ret = true; + drawInByteRaster(endpoints[count].first, p); + closingSegments.push_back(Segment(endpoints[count].first, p)); + cancelFromArray(endpoints, p, count); + if (!EndpointTable[neighboursCode(getPtr(endpoints[count].first))]) { + std::vector::iterator it = endpoints.begin(); + std::advance(it, count); + endpoints.erase(it); + continue; + } + } + count++; + } + + return ret; } /*------------------------------------------------------------------------*/ -bool TAutocloser::Imp::exploreSpot(const Segment &s, TPoint &p) -{ - int x1, y1, x2, y2, x3, y3, i; - double x2a, y2a, x2b, y2b, xnewa, ynewa, xnewb, ynewb; - int lx = m_raster->getLx(); - int ly = m_raster->getLy(); - - x1 = s.first.x; - y1 = s.first.y; - x2 = s.second.x; - y2 = s.second.y; - - if (x1 == x2 && y1 == y2) - return 0; - - if (exploreRay(getPtr(x1, y1), s, p)) - return true; - - x2a = x2b = (double)x2; - y2a = y2b = (double)y2; - - for (i = 0; i < AUT_SPOT_SAMPLES; i++) { - xnewa = x1 + (x2a - x1) * m_csa - (y2a - y1) * m_sna; - ynewa = y1 + (y2a - y1) * m_csa + (x2a - x1) * m_sna; - x3 = tround(xnewa); - y3 = tround(ynewa); - if ((x3 != tround(x2a) || y3 != tround(y2a)) && x3 > 0 && x3 < lx && y3 > 0 && y3 < ly && - exploreRay(getPtr(x1, y1), Segment(TPoint(x1, y1), TPoint(tround(xnewa), tround(ynewa))), p)) - return true; - - x2a = xnewa; - y2a = ynewa; - - xnewb = x1 + (x2b - x1) * m_csb - (y2b - y1) * m_snb; - ynewb = y1 + (y2b - y1) * m_csb + (x2b - x1) * m_snb; - x3 = tround(xnewb); - y3 = tround(ynewb); - if ((x3 != tround(x2b) || y3 != tround(y2b)) && x3 > 0 && x3 < lx && y3 > 0 && y3 < ly && - exploreRay(getPtr(x1, y1), Segment(TPoint(x1, y1), TPoint(tround(xnewb), tround(ynewb))), p)) - return true; - - x2b = xnewb; - y2b = ynewb; - } - return false; +bool TAutocloser::Imp::exploreSpot(const Segment &s, TPoint &p) { + int x1, y1, x2, y2, x3, y3, i; + double x2a, y2a, x2b, y2b, xnewa, ynewa, xnewb, ynewb; + int lx = m_raster->getLx(); + int ly = m_raster->getLy(); + + x1 = s.first.x; + y1 = s.first.y; + x2 = s.second.x; + y2 = s.second.y; + + if (x1 == x2 && y1 == y2) return 0; + + if (exploreRay(getPtr(x1, y1), s, p)) return true; + + x2a = x2b = (double)x2; + y2a = y2b = (double)y2; + + for (i = 0; i < AUT_SPOT_SAMPLES; i++) { + xnewa = x1 + (x2a - x1) * m_csa - (y2a - y1) * m_sna; + ynewa = y1 + (y2a - y1) * m_csa + (x2a - x1) * m_sna; + x3 = tround(xnewa); + y3 = tround(ynewa); + if ((x3 != tround(x2a) || y3 != tround(y2a)) && x3 > 0 && x3 < lx && + y3 > 0 && y3 < ly && + exploreRay( + getPtr(x1, y1), + Segment(TPoint(x1, y1), TPoint(tround(xnewa), tround(ynewa))), p)) + return true; + + x2a = xnewa; + y2a = ynewa; + + xnewb = x1 + (x2b - x1) * m_csb - (y2b - y1) * m_snb; + ynewb = y1 + (y2b - y1) * m_csb + (x2b - x1) * m_snb; + x3 = tround(xnewb); + y3 = tround(ynewb); + if ((x3 != tround(x2b) || y3 != tround(y2b)) && x3 > 0 && x3 < lx && + y3 > 0 && y3 < ly && + exploreRay( + getPtr(x1, y1), + Segment(TPoint(x1, y1), TPoint(tround(xnewb), tround(ynewb))), p)) + return true; + + x2b = xnewb; + y2b = ynewb; + } + return false; } /*------------------------------------------------------------------------*/ -bool TAutocloser::Imp::exploreRay(UCHAR *br, Segment s, TPoint &p) -{ - int x, y, dx, dy, d, incr_1, incr_2, inside_ink; - - inside_ink = 1; - - x = 0; - y = 0; - - if (s.first.x < s.second.x) { - dx = s.second.x - s.first.x; - dy = s.second.y - s.first.y; - if (dy >= 0) - if (dy <= dx) - DRAW_SEGMENT(x, y, dx, dy, (br++), (br += m_bWrap + 1), - EXPLORE_RAY_ISTR((s.first.x + x))) - else - DRAW_SEGMENT(y, x, dy, dx, (br += m_bWrap), (br += m_bWrap + 1), - EXPLORE_RAY_ISTR((s.first.x + x))) - else { - dy = -dy; - if (dy <= dx) - DRAW_SEGMENT(x, y, dx, dy, (br++), (br -= m_bWrap - 1), - EXPLORE_RAY_ISTR((s.first.x + x))) - else - DRAW_SEGMENT(y, x, dy, dx, (br -= m_bWrap), (br -= m_bWrap - 1), - EXPLORE_RAY_ISTR((s.first.x + x))) - } - } else { - dx = s.first.x - s.second.x; - dy = s.second.y - s.first.y; - if (dy >= 0) - if (dy <= dx) - DRAW_SEGMENT(x, y, dx, dy, (br--), (br += m_bWrap - 1), - EXPLORE_RAY_ISTR((s.first.x - x))) - else - DRAW_SEGMENT(y, x, dy, dx, (br += m_bWrap), (br += m_bWrap - 1), - EXPLORE_RAY_ISTR((s.first.x - x))) - else { - dy = -dy; - if (dy <= dx) - DRAW_SEGMENT(x, y, dx, dy, (br--), (br -= m_bWrap + 1), - EXPLORE_RAY_ISTR((s.first.x - x))) - else - DRAW_SEGMENT(y, x, dy, dx, (br -= m_bWrap), (br -= m_bWrap + 1), - EXPLORE_RAY_ISTR((s.first.x - x))) - } - } - return false; +bool TAutocloser::Imp::exploreRay(UCHAR *br, Segment s, TPoint &p) { + int x, y, dx, dy, d, incr_1, incr_2, inside_ink; + + inside_ink = 1; + + x = 0; + y = 0; + + if (s.first.x < s.second.x) { + dx = s.second.x - s.first.x; + dy = s.second.y - s.first.y; + if (dy >= 0) + if (dy <= dx) + DRAW_SEGMENT(x, y, dx, dy, (br++), (br += m_bWrap + 1), + EXPLORE_RAY_ISTR((s.first.x + x))) + else + DRAW_SEGMENT(y, x, dy, dx, (br += m_bWrap), (br += m_bWrap + 1), + EXPLORE_RAY_ISTR((s.first.x + x))) + else { + dy = -dy; + if (dy <= dx) + DRAW_SEGMENT(x, y, dx, dy, (br++), (br -= m_bWrap - 1), + EXPLORE_RAY_ISTR((s.first.x + x))) + else + DRAW_SEGMENT(y, x, dy, dx, (br -= m_bWrap), (br -= m_bWrap - 1), + EXPLORE_RAY_ISTR((s.first.x + x))) + } + } else { + dx = s.first.x - s.second.x; + dy = s.second.y - s.first.y; + if (dy >= 0) + if (dy <= dx) + DRAW_SEGMENT(x, y, dx, dy, (br--), (br += m_bWrap - 1), + EXPLORE_RAY_ISTR((s.first.x - x))) + else + DRAW_SEGMENT(y, x, dy, dx, (br += m_bWrap), (br += m_bWrap - 1), + EXPLORE_RAY_ISTR((s.first.x - x))) + else { + dy = -dy; + if (dy <= dx) + DRAW_SEGMENT(x, y, dx, dy, (br--), (br -= m_bWrap + 1), + EXPLORE_RAY_ISTR((s.first.x - x))) + else + DRAW_SEGMENT(y, x, dy, dx, (br -= m_bWrap), (br -= m_bWrap + 1), + EXPLORE_RAY_ISTR((s.first.x - x))) + } + } + return false; } /*------------------------------------------------------------------------*/ -void TAutocloser::Imp::drawInByteRaster(const TPoint &p0, const TPoint &p1) -{ - int x, y, dx, dy, d, incr_1, incr_2; - UCHAR *br; - - if (p0.x > p1.x) { - br = getPtr(p1); - dx = p0.x - p1.x; - dy = p0.y - p1.y; - } else { - br = getPtr(p0); - dx = p1.x - p0.x; - dy = p1.y - p0.y; - } - - x = y = 0; - - if (dy >= 0) { - if (dy <= dx) - DRAW_SEGMENT(x, y, dx, dy, (br++), (br += m_bWrap + 1), ((*br) |= 0x41)) - else - DRAW_SEGMENT(y, x, dy, dx, (br += m_bWrap), (br += m_bWrap + 1), ((*br) |= 0x41)) - } else { - dy = -dy; - if (dy <= dx) - DRAW_SEGMENT(x, y, dx, dy, (br++), (br -= m_bWrap - 1), ((*br) |= 0x41)) - else - DRAW_SEGMENT(y, x, dy, dx, (br -= m_bWrap), (br -= m_bWrap - 1), ((*br) |= 0x41)) - } +void TAutocloser::Imp::drawInByteRaster(const TPoint &p0, const TPoint &p1) { + int x, y, dx, dy, d, incr_1, incr_2; + UCHAR *br; + + if (p0.x > p1.x) { + br = getPtr(p1); + dx = p0.x - p1.x; + dy = p0.y - p1.y; + } else { + br = getPtr(p0); + dx = p1.x - p0.x; + dy = p1.y - p0.y; + } + + x = y = 0; + + if (dy >= 0) { + if (dy <= dx) + DRAW_SEGMENT(x, y, dx, dy, (br++), (br += m_bWrap + 1), ((*br) |= 0x41)) + else + DRAW_SEGMENT(y, x, dy, dx, (br += m_bWrap), (br += m_bWrap + 1), + ((*br) |= 0x41)) + } else { + dy = -dy; + if (dy <= dx) + DRAW_SEGMENT(x, y, dx, dy, (br++), (br -= m_bWrap - 1), ((*br) |= 0x41)) + else + DRAW_SEGMENT(y, x, dy, dx, (br -= m_bWrap), (br -= m_bWrap - 1), + ((*br) |= 0x41)) + } } /*------------------------------------------------------------------------*/ @@ -853,70 +841,63 @@ void TAutocloser::Imp::drawInByteRaster(const TPoint &p0, const TPoint &p1) TPoint TAutocloser::Imp::visitEndpoint(UCHAR *br) { - m_displAverage = TPointD(); + m_displAverage = TPointD(); - m_visited = 0; + m_visited = 0; - visitPix(br, m_closingDistance, TPoint()); - cancelMarks(br); + visitPix(br, m_closingDistance, TPoint()); + cancelMarks(br); - return TPoint(convert((1.0 / m_visited) * m_displAverage)); + return TPoint(convert((1.0 / m_visited) * m_displAverage)); } /*------------------------------------------------------------------------*/ -void TAutocloser::Imp::visitPix(UCHAR *br, int toVisit, const TPoint &dis) -{ - UCHAR b = 0; - int i, pixToVisit = 0; +void TAutocloser::Imp::visitPix(UCHAR *br, int toVisit, const TPoint &dis) { + UCHAR b = 0; + int i, pixToVisit = 0; - *br |= 0x10; - m_visited++; - m_displAverage.x += dis.x; - m_displAverage.y += dis.y; + *br |= 0x10; + m_visited++; + m_displAverage.x += dis.x; + m_displAverage.y += dis.y; - toVisit--; - if (toVisit == 0) - return; + toVisit--; + if (toVisit == 0) return; - for (i = 0; i < 8; i++) { - UCHAR *v = br + m_displaceVector[i]; - if (isInk(v) && !((*v) & 0x10)) { - b |= (1 << i); - pixToVisit++; - } - } + for (i = 0; i < 8; i++) { + UCHAR *v = br + m_displaceVector[i]; + if (isInk(v) && !((*v) & 0x10)) { + b |= (1 << i); + pixToVisit++; + } + } - if (pixToVisit == 0) - return; + if (pixToVisit == 0) return; - if (pixToVisit <= 4) - toVisit = troundp(toVisit / (double)pixToVisit); + if (pixToVisit <= 4) toVisit = troundp(toVisit / (double)pixToVisit); - if (toVisit == 0) - return; + if (toVisit == 0) return; - int x[8] = {-1, 0, 1, -1, 1, -1, 0, 1}; - int y[8] = {-1, -1, -1, 0, 0, 1, 1, 1}; + int x[8] = {-1, 0, 1, -1, 1, -1, 0, 1}; + int y[8] = {-1, -1, -1, 0, 0, 1, 1, 1}; - for (i = 0; i < 8; i++) - if (b & (1 << i)) - visitPix(br + m_displaceVector[i], toVisit, dis + TPoint(x[i], y[i])); + for (i = 0; i < 8; i++) + if (b & (1 << i)) + visitPix(br + m_displaceVector[i], toVisit, dis + TPoint(x[i], y[i])); } /*------------------------------------------------------------------------*/ -void TAutocloser::Imp::cancelMarks(UCHAR *br) -{ - *br &= 0xef; - int i; +void TAutocloser::Imp::cancelMarks(UCHAR *br) { + *br &= 0xef; + int i; - for (i = 0; i < 8; i++) { - UCHAR *v = br + m_displaceVector[i]; + for (i = 0; i < 8; i++) { + UCHAR *v = br + m_displaceVector[i]; - if (isInk(v) && (*v) & 0x10) - cancelMarks(v); - } + if (isInk(v) && (*v) & 0x10) cancelMarks(v); + } } /*=============================================================================*/ @@ -934,184 +915,179 @@ void TAutocloser::Imp::cancelMarks(UCHAR *br) /*=============================================================================*/ -void TAutocloser::Imp::skeletonize(vector &endpoints) -{ - vector seeds; +void TAutocloser::Imp::skeletonize(vector &endpoints) { + vector seeds; - findSeeds(seeds, endpoints); + findSeeds(seeds, endpoints); - erase(seeds, endpoints); + erase(seeds, endpoints); } /*------------------------------------------------------------------------*/ -void TAutocloser::Imp::findSeeds(vector &seeds, vector &endpoints) -{ - int i, j; - UCHAR preseed; - - UCHAR *br = m_br; - - for (i = 0; i < m_bRaster->getLy(); i++) { - for (j = 0; j < m_bRaster->getLx(); j++, br++) { - if (notMarkedBorderInk(br)) { - preseed = FirstPreseedTable[neighboursCode(br)]; - - if (preseed != 8) /*non e' un pixel isolato*/ - { - seeds.push_back(Seed(br, preseed)); - circuitAndMark(br, preseed); - } else { - (*br) |= 0x8; - endpoints.push_back(getCoordinates(br)); - } - } - } - br += m_bWrap - m_bRaster->getLx(); - } +void TAutocloser::Imp::findSeeds(vector &seeds, + vector &endpoints) { + int i, j; + UCHAR preseed; + + UCHAR *br = m_br; + + for (i = 0; i < m_bRaster->getLy(); i++) { + for (j = 0; j < m_bRaster->getLx(); j++, br++) { + if (notMarkedBorderInk(br)) { + preseed = FirstPreseedTable[neighboursCode(br)]; + + if (preseed != 8) /*non e' un pixel isolato*/ + { + seeds.push_back(Seed(br, preseed)); + circuitAndMark(br, preseed); + } else { + (*br) |= 0x8; + endpoints.push_back(getCoordinates(br)); + } + } + } + br += m_bWrap - m_bRaster->getLx(); + } } /*------------------------------------------------------------------------*/ -void TAutocloser::Imp::circuitAndMark(UCHAR *seed, UCHAR preseed) -{ - UCHAR *walker; - UCHAR displ, prewalker; +void TAutocloser::Imp::circuitAndMark(UCHAR *seed, UCHAR preseed) { + UCHAR *walker; + UCHAR displ, prewalker; - *seed |= 0x4; + *seed |= 0x4; - displ = NextPointTable[(neighboursCode(seed) << 3) | preseed]; - assert(displ >= 0 && displ < 8); + displ = NextPointTable[(neighboursCode(seed) << 3) | preseed]; + assert(displ >= 0 && displ < 8); - walker = seed + m_displaceVector[displ]; - prewalker = displ ^ 0x7; + walker = seed + m_displaceVector[displ]; + prewalker = displ ^ 0x7; - while ((walker != seed) || (preseed != prewalker)) { - *walker |= 0x4; /* metto la marca di passaggio */ + while ((walker != seed) || (preseed != prewalker)) { + *walker |= 0x4; /* metto la marca di passaggio */ - displ = NextPointTable[(neighboursCode(walker) << 3) | prewalker]; - assert(displ >= 0 && displ < 8); - walker += m_displaceVector[displ]; - prewalker = displ ^ 0x7; - } + displ = NextPointTable[(neighboursCode(walker) << 3) | prewalker]; + assert(displ >= 0 && displ < 8); + walker += m_displaceVector[displ]; + prewalker = displ ^ 0x7; + } - return; + return; } /*------------------------------------------------------------------------*/ -void TAutocloser::Imp::erase(vector &seeds, vector &endpoints) -{ - int i, size = 0, oldSize; - UCHAR *seed, preseed, code, displ; - oldSize = seeds.size(); - - while (oldSize != size) { - oldSize = size; - size = seeds.size(); - - for (i = oldSize; i < size; i++) { - seed = seeds[i].m_ptr; - preseed = seeds[i].m_preseed; - - if (!isInk(seed)) { - code = NextSeedTable[neighboursCode(seed)]; - seed += m_displaceVector[code & 0x7]; - preseed = (code & 0x38) >> 3; - } - - if (circuitAndCancel(seed, preseed, endpoints)) { - if (isInk(seed)) { - - displ = NextPointTable[(neighboursCode(seed) << 3) | preseed]; - assert(displ >= 0 && displ < 8); - seeds.push_back(Seed(seed + m_displaceVector[displ], displ ^ 0x7)); - - } else /* il seed e' stato cancellato */ - { - code = NextSeedTable[neighboursCode(seed)]; - seeds.push_back(Seed(seed + m_displaceVector[code & 0x7], (code & 0x38) >> 3)); - } - } - } - } +void TAutocloser::Imp::erase(vector &seeds, vector &endpoints) { + int i, size = 0, oldSize; + UCHAR *seed, preseed, code, displ; + oldSize = seeds.size(); + + while (oldSize != size) { + oldSize = size; + size = seeds.size(); + + for (i = oldSize; i < size; i++) { + seed = seeds[i].m_ptr; + preseed = seeds[i].m_preseed; + + if (!isInk(seed)) { + code = NextSeedTable[neighboursCode(seed)]; + seed += m_displaceVector[code & 0x7]; + preseed = (code & 0x38) >> 3; + } + + if (circuitAndCancel(seed, preseed, endpoints)) { + if (isInk(seed)) { + displ = NextPointTable[(neighboursCode(seed) << 3) | preseed]; + assert(displ >= 0 && displ < 8); + seeds.push_back(Seed(seed + m_displaceVector[displ], displ ^ 0x7)); + + } else /* il seed e' stato cancellato */ + { + code = NextSeedTable[neighboursCode(seed)]; + seeds.push_back( + Seed(seed + m_displaceVector[code & 0x7], (code & 0x38) >> 3)); + } + } + } + } } /*------------------------------------------------------------------------*/ -bool TAutocloser::Imp::circuitAndCancel(UCHAR *seed, UCHAR preseed, vector &endpoints) -{ - UCHAR *walker, *previous; - UCHAR displ, prewalker; - bool ret = false; - - displ = NextPointTable[(neighboursCode(seed) << 3) | preseed]; - assert(displ >= 0 && displ < 8); - - if ((displ == preseed) && !((*seed) & 0x8)) { - endpoints.push_back(getCoordinates(seed)); - *seed |= 0x8; - } - - walker = seed + m_displaceVector[displ]; - prewalker = displ ^ 0x7; - - while ((walker != seed) || (preseed != prewalker)) { - assert(prewalker >= 0 && prewalker < 8); - displ = NextPointTable[(neighboursCode(walker) << 3) | prewalker]; - assert(displ >= 0 && displ < 8); - - if ((displ == prewalker) && !((*walker) & 0x8)) { - endpoints.push_back(getCoordinates(walker)); - *walker |= 0x8; - } - previous = walker + m_displaceVector[prewalker]; - if (ConnectionTable[neighboursCode(previous)]) { - ret = true; - if (previous != seed) - eraseInk(previous); - } - walker += m_displaceVector[displ]; - prewalker = displ ^ 0x7; - } - - displ = NextPointTable[(neighboursCode(walker) << 3) | prewalker]; - - if ((displ == preseed) && !((*seed) & 0x8)) { - endpoints.push_back(getCoordinates(seed)); - *seed |= 0x8; - } - - if (ConnectionTable[neighboursCode(seed + m_displaceVector[preseed])]) { - ret = true; - eraseInk(seed + m_displaceVector[preseed]); - } - - if (ConnectionTable[neighboursCode(seed)]) { - ret = true; - eraseInk(seed); - } - - return ret; +bool TAutocloser::Imp::circuitAndCancel(UCHAR *seed, UCHAR preseed, + vector &endpoints) { + UCHAR *walker, *previous; + UCHAR displ, prewalker; + bool ret = false; + + displ = NextPointTable[(neighboursCode(seed) << 3) | preseed]; + assert(displ >= 0 && displ < 8); + + if ((displ == preseed) && !((*seed) & 0x8)) { + endpoints.push_back(getCoordinates(seed)); + *seed |= 0x8; + } + + walker = seed + m_displaceVector[displ]; + prewalker = displ ^ 0x7; + + while ((walker != seed) || (preseed != prewalker)) { + assert(prewalker >= 0 && prewalker < 8); + displ = NextPointTable[(neighboursCode(walker) << 3) | prewalker]; + assert(displ >= 0 && displ < 8); + + if ((displ == prewalker) && !((*walker) & 0x8)) { + endpoints.push_back(getCoordinates(walker)); + *walker |= 0x8; + } + previous = walker + m_displaceVector[prewalker]; + if (ConnectionTable[neighboursCode(previous)]) { + ret = true; + if (previous != seed) eraseInk(previous); + } + walker += m_displaceVector[displ]; + prewalker = displ ^ 0x7; + } + + displ = NextPointTable[(neighboursCode(walker) << 3) | prewalker]; + + if ((displ == preseed) && !((*seed) & 0x8)) { + endpoints.push_back(getCoordinates(seed)); + *seed |= 0x8; + } + + if (ConnectionTable[neighboursCode(seed + m_displaceVector[preseed])]) { + ret = true; + eraseInk(seed + m_displaceVector[preseed]); + } + + if (ConnectionTable[neighboursCode(seed)]) { + ret = true; + eraseInk(seed); + } + + return ret; } /*=============================================================================*/ -void TAutocloser::Imp::cancelFromArray(vector &array, TPoint p, int &count) -{ - std::vector::iterator it = array.begin(); - int i = 0; - - for (; it != array.end(); ++it, i++) - if (it->first == p) { - if (!EndpointTable[neighboursCode(getPtr(p))]) { - assert(i != count); - if (i < count) - count--; - array.erase(it); - } - return; - } +void TAutocloser::Imp::cancelFromArray(vector &array, TPoint p, + int &count) { + std::vector::iterator it = array.begin(); + int i = 0; + + for (; it != array.end(); ++it, i++) + if (it->first == p) { + if (!EndpointTable[neighboursCode(getPtr(p))]) { + assert(i != count); + if (i < count) count--; + array.erase(it); + } + return; + } } /*------------------------------------------------------------------------*/ @@ -1132,21 +1108,15 @@ return 0; /*=============================================================================*/ -TAutocloser::TAutocloser(const TRasterP &r) -{ - m_imp = new Imp(r); -} +TAutocloser::TAutocloser(const TRasterP &r) { m_imp = new Imp(r); } //....................... -TAutocloser::~TAutocloser() -{ - delete m_imp; -} +TAutocloser::~TAutocloser() { delete m_imp; } //------------------------------------------------- -//if this function is never used, use default values +// if this function is never used, use default values void TAutocloser::setClosingDistance(int d) { m_imp->m_closingDistance = d; } //------------------------------------------------- @@ -1155,12 +1125,10 @@ int TAutocloser::getClosingDistance() const { return m_imp->m_closingDistance; } //------------------------------------------------- -void TAutocloser::setSpotAngle(double degrees) -{ - if (degrees <= 0.0) - degrees = 1.0; +void TAutocloser::setSpotAngle(double degrees) { + if (degrees <= 0.0) degrees = 1.0; - m_imp->m_spotAngle = (degrees * TConsts::pi) / 360.0; + m_imp->m_spotAngle = (degrees * TConsts::pi) / 360.0; } //------------------------------------------------- @@ -1169,22 +1137,15 @@ double TAutocloser::getSpotAngle() const { return m_imp->m_spotAngle; } //------------------------------------------------- -void TAutocloser::setInkIndex(int inkIndex) -{ - m_imp->m_inkIndex = inkIndex; -} +void TAutocloser::setInkIndex(int inkIndex) { m_imp->m_inkIndex = inkIndex; } //------------------------------------------------- -int TAutocloser::getInkIndex() const -{ - return m_imp->m_inkIndex; -} +int TAutocloser::getInkIndex() const { return m_imp->m_inkIndex; } //------------------------------------------------- -void TAutocloser::compute(vector &closingSegmentArray) -{ - m_imp->compute(closingSegmentArray); +void TAutocloser::compute(vector &closingSegmentArray) { + m_imp->compute(closingSegmentArray); } //------------------------------------------------- diff --git a/toonz/sources/common/trop/tblur.cpp b/toonz/sources/common/trop/tblur.cpp index acad3cd..3361194 100644 --- a/toonz/sources/common/trop/tblur.cpp +++ b/toonz/sources/common/trop/tblur.cpp @@ -8,223 +8,217 @@ #include #endif -namespace -{ +namespace { #ifdef _WIN32 template struct BlurPixel { - T b; - T g; - T r; - T m; + T b; + T g; + T r; + T m; }; #else template struct BlurPixel { - T r; - T g; - T b; - T m; + T r; + T g; + T b; + T m; }; #endif //=================================================================== -#define LOAD_COL_CODE \ - \ - buffer += x; \ - pix = col + by1; \ - \ - for (i = by1; i < ly + by1; i++) { \ - *pix++ = *buffer; \ - buffer += lx; \ - } \ - \ - pix += by2; \ - left_val = col[0]; \ - right_val = *(pix - 1); \ - col--; \ - \ - for (i = 0; i < brad; i++) { \ - *col-- = left_val; \ - *pix++ = right_val; \ - } +#define LOAD_COL_CODE \ + \ + buffer += x; \ + pix = col + by1; \ + \ + for (i = by1; i < ly + by1; i++) { \ + *pix++ = *buffer; \ + buffer += lx; \ + } \ + \ + pix += by2; \ + left_val = col[0]; \ + right_val = *(pix - 1); \ + col--; \ + \ + for (i = 0; i < brad; i++) { \ + *col-- = left_val; \ + *pix++ = right_val; \ + } //------------------------------------------------------------------- -#define BLUR_CODE(round_fac, channel_type) \ - pix1 = row1; \ - pix2 = row1 - 1; \ - \ - sigma1.r = pix1->r; \ - sigma1.g = pix1->g; \ - sigma1.b = pix1->b; \ - sigma1.m = pix1->m; \ - pix1++; \ - \ - sigma2.r = sigma2.g = sigma2.b = sigma2.m = 0.0; \ - sigma3.r = sigma3.g = sigma3.b = sigma3.m = 0.0; \ - \ - for (i = 1; i < brad; i++) { \ - sigma1.r += pix1->r; \ - sigma1.g += pix1->g; \ - sigma1.b += pix1->b; \ - sigma1.m += pix1->m; \ - \ - sigma2.r += pix2->r; \ - sigma2.g += pix2->g; \ - sigma2.b += pix2->b; \ - sigma2.m += pix2->m; \ - \ - sigma3.r += i * (pix1->r + pix2->r); \ - sigma3.g += i * (pix1->g + pix2->g); \ - sigma3.b += i * (pix1->b + pix2->b); \ - sigma3.m += i * (pix1->m + pix2->m); \ - \ - pix1++; \ - pix2--; \ - } \ - \ - rsum = (sigma1.r + sigma2.r) * coeff - sigma3.r * coeffq + (round_fac); \ - gsum = (sigma1.g + sigma2.g) * coeff - sigma3.g * coeffq + (round_fac); \ - bsum = (sigma1.b + sigma2.b) * coeff - sigma3.b * coeffq + (round_fac); \ - msum = (sigma1.m + sigma2.m) * coeff - sigma3.m * coeffq + (round_fac); \ - \ - row2->r = (channel_type)(rsum); \ - row2->g = (channel_type)(gsum); \ - row2->b = (channel_type)(bsum); \ - row2->m = (channel_type)(msum); \ - row2++; \ - \ - sigma2.r += row1[-brad].r; \ - sigma2.g += row1[-brad].g; \ - sigma2.b += row1[-brad].b; \ - sigma2.m += row1[-brad].m; \ - \ - pix1 = row1 + brad; \ - pix2 = row1; \ - pix3 = row1 - brad; \ - pix4 = row1 - brad + 1; \ - \ - desigma.r = sigma1.r - sigma2.r; \ - desigma.g = sigma1.g - sigma2.g; \ - desigma.b = sigma1.b - sigma2.b; \ - desigma.m = sigma1.m - sigma2.m; \ - \ - for (i = 1; i < length; i++) { \ - desigma.r += pix1->r - 2 * pix2->r + pix3->r; \ - desigma.g += pix1->g - 2 * pix2->g + pix3->g; \ - desigma.b += pix1->b - 2 * pix2->b + pix3->b; \ - desigma.m += pix1->m - 2 * pix2->m + pix3->m; \ - \ - rsum += (desigma.r + diff * (pix1->r - pix4->r)) * coeffq; \ - gsum += (desigma.g + diff * (pix1->g - pix4->g)) * coeffq; \ - bsum += (desigma.b + diff * (pix1->b - pix4->b)) * coeffq; \ - msum += (desigma.m + diff * (pix1->m - pix4->m)) * coeffq; \ - \ - row2->r = (channel_type)(rsum); \ - row2->g = (channel_type)(gsum); \ - row2->b = (channel_type)(bsum); \ - row2->m = (channel_type)(msum); \ - row2++; \ - pix1++, pix2++, pix3++, pix4++; \ - } +#define BLUR_CODE(round_fac, channel_type) \ + pix1 = row1; \ + pix2 = row1 - 1; \ + \ + sigma1.r = pix1->r; \ + sigma1.g = pix1->g; \ + sigma1.b = pix1->b; \ + sigma1.m = pix1->m; \ + pix1++; \ + \ + sigma2.r = sigma2.g = sigma2.b = sigma2.m = 0.0; \ + sigma3.r = sigma3.g = sigma3.b = sigma3.m = 0.0; \ + \ + for (i = 1; i < brad; i++) { \ + sigma1.r += pix1->r; \ + sigma1.g += pix1->g; \ + sigma1.b += pix1->b; \ + sigma1.m += pix1->m; \ + \ + sigma2.r += pix2->r; \ + sigma2.g += pix2->g; \ + sigma2.b += pix2->b; \ + sigma2.m += pix2->m; \ + \ + sigma3.r += i * (pix1->r + pix2->r); \ + sigma3.g += i * (pix1->g + pix2->g); \ + sigma3.b += i * (pix1->b + pix2->b); \ + sigma3.m += i * (pix1->m + pix2->m); \ + \ + pix1++; \ + pix2--; \ + } \ + \ + rsum = (sigma1.r + sigma2.r) * coeff - sigma3.r * coeffq + (round_fac); \ + gsum = (sigma1.g + sigma2.g) * coeff - sigma3.g * coeffq + (round_fac); \ + bsum = (sigma1.b + sigma2.b) * coeff - sigma3.b * coeffq + (round_fac); \ + msum = (sigma1.m + sigma2.m) * coeff - sigma3.m * coeffq + (round_fac); \ + \ + row2->r = (channel_type)(rsum); \ + row2->g = (channel_type)(gsum); \ + row2->b = (channel_type)(bsum); \ + row2->m = (channel_type)(msum); \ + row2++; \ + \ + sigma2.r += row1[-brad].r; \ + sigma2.g += row1[-brad].g; \ + sigma2.b += row1[-brad].b; \ + sigma2.m += row1[-brad].m; \ + \ + pix1 = row1 + brad; \ + pix2 = row1; \ + pix3 = row1 - brad; \ + pix4 = row1 - brad + 1; \ + \ + desigma.r = sigma1.r - sigma2.r; \ + desigma.g = sigma1.g - sigma2.g; \ + desigma.b = sigma1.b - sigma2.b; \ + desigma.m = sigma1.m - sigma2.m; \ + \ + for (i = 1; i < length; i++) { \ + desigma.r += pix1->r - 2 * pix2->r + pix3->r; \ + desigma.g += pix1->g - 2 * pix2->g + pix3->g; \ + desigma.b += pix1->b - 2 * pix2->b + pix3->b; \ + desigma.m += pix1->m - 2 * pix2->m + pix3->m; \ + \ + rsum += (desigma.r + diff * (pix1->r - pix4->r)) * coeffq; \ + gsum += (desigma.g + diff * (pix1->g - pix4->g)) * coeffq; \ + bsum += (desigma.b + diff * (pix1->b - pix4->b)) * coeffq; \ + msum += (desigma.m + diff * (pix1->m - pix4->m)) * coeffq; \ + \ + row2->r = (channel_type)(rsum); \ + row2->g = (channel_type)(gsum); \ + row2->b = (channel_type)(bsum); \ + row2->m = (channel_type)(msum); \ + row2++; \ + pix1++, pix2++, pix3++, pix4++; \ + } //------------------------------------------------------------------- template -inline void blur_code( - PIXEL_SRC *row1, PIXEL_DST *row2, - int length, - float coeff, float coeffq, - int brad, float diff, - float round_fac) -{ - int i; - T rsum, gsum, bsum, msum; - - BlurPixel sigma1, sigma2, sigma3, desigma; - PIXEL_SRC *pix1, *pix2, *pix3, *pix4; - - pix1 = row1; - pix2 = row1 - 1; - - sigma1.r = pix1->r; - sigma1.g = pix1->g; - sigma1.b = pix1->b; - sigma1.m = pix1->m; - pix1++; - - sigma2.r = sigma2.g = sigma2.b = sigma2.m = 0.0; - sigma3.r = sigma3.g = sigma3.b = sigma3.m = 0.0; - - for (i = 1; i < brad; i++) { - sigma1.r += pix1->r; - sigma1.g += pix1->g; - sigma1.b += pix1->b; - sigma1.m += pix1->m; - - sigma2.r += pix2->r; - sigma2.g += pix2->g; - sigma2.b += pix2->b; - sigma2.m += pix2->m; - - sigma3.r += i * (pix1->r + pix2->r); - sigma3.g += i * (pix1->g + pix2->g); - sigma3.b += i * (pix1->b + pix2->b); - sigma3.m += i * (pix1->m + pix2->m); - - pix1++; - pix2--; - } - - rsum = (sigma1.r + sigma2.r) * coeff - sigma3.r * coeffq + (round_fac); - gsum = (sigma1.g + sigma2.g) * coeff - sigma3.g * coeffq + (round_fac); - bsum = (sigma1.b + sigma2.b) * coeff - sigma3.b * coeffq + (round_fac); - msum = (sigma1.m + sigma2.m) * coeff - sigma3.m * coeffq + (round_fac); - - row2->r = rsum; - row2->g = gsum; - row2->b = bsum; - row2->m = msum; - row2++; - - sigma2.r += row1[-brad].r; - sigma2.g += row1[-brad].g; - sigma2.b += row1[-brad].b; - sigma2.m += row1[-brad].m; - - pix1 = row1 + brad; - pix2 = row1; - pix3 = row1 - brad; - pix4 = row1 - brad + 1; - - desigma.r = sigma1.r - sigma2.r; - desigma.g = sigma1.g - sigma2.g; - desigma.b = sigma1.b - sigma2.b; - desigma.m = sigma1.m - sigma2.m; - - for (i = 1; i < length; i++) { - desigma.r += pix1->r - 2 * pix2->r + pix3->r; - desigma.g += pix1->g - 2 * pix2->g + pix3->g; - desigma.b += pix1->b - 2 * pix2->b + pix3->b; - desigma.m += pix1->m - 2 * pix2->m + pix3->m; - - rsum += (desigma.r + diff * (pix1->r - pix4->r)) * coeffq; - gsum += (desigma.g + diff * (pix1->g - pix4->g)) * coeffq; - bsum += (desigma.b + diff * (pix1->b - pix4->b)) * coeffq; - msum += (desigma.m + diff * (pix1->m - pix4->m)) * coeffq; - - row2->r = rsum; - row2->g = gsum; - row2->b = bsum; - row2->m = msum; - row2++; - pix1++, pix2++, pix3++, pix4++; - } +inline void blur_code(PIXEL_SRC *row1, PIXEL_DST *row2, int length, float coeff, + float coeffq, int brad, float diff, float round_fac) { + int i; + T rsum, gsum, bsum, msum; + + BlurPixel sigma1, sigma2, sigma3, desigma; + PIXEL_SRC *pix1, *pix2, *pix3, *pix4; + + pix1 = row1; + pix2 = row1 - 1; + + sigma1.r = pix1->r; + sigma1.g = pix1->g; + sigma1.b = pix1->b; + sigma1.m = pix1->m; + pix1++; + + sigma2.r = sigma2.g = sigma2.b = sigma2.m = 0.0; + sigma3.r = sigma3.g = sigma3.b = sigma3.m = 0.0; + + for (i = 1; i < brad; i++) { + sigma1.r += pix1->r; + sigma1.g += pix1->g; + sigma1.b += pix1->b; + sigma1.m += pix1->m; + + sigma2.r += pix2->r; + sigma2.g += pix2->g; + sigma2.b += pix2->b; + sigma2.m += pix2->m; + + sigma3.r += i * (pix1->r + pix2->r); + sigma3.g += i * (pix1->g + pix2->g); + sigma3.b += i * (pix1->b + pix2->b); + sigma3.m += i * (pix1->m + pix2->m); + + pix1++; + pix2--; + } + + rsum = (sigma1.r + sigma2.r) * coeff - sigma3.r * coeffq + (round_fac); + gsum = (sigma1.g + sigma2.g) * coeff - sigma3.g * coeffq + (round_fac); + bsum = (sigma1.b + sigma2.b) * coeff - sigma3.b * coeffq + (round_fac); + msum = (sigma1.m + sigma2.m) * coeff - sigma3.m * coeffq + (round_fac); + + row2->r = rsum; + row2->g = gsum; + row2->b = bsum; + row2->m = msum; + row2++; + + sigma2.r += row1[-brad].r; + sigma2.g += row1[-brad].g; + sigma2.b += row1[-brad].b; + sigma2.m += row1[-brad].m; + + pix1 = row1 + brad; + pix2 = row1; + pix3 = row1 - brad; + pix4 = row1 - brad + 1; + + desigma.r = sigma1.r - sigma2.r; + desigma.g = sigma1.g - sigma2.g; + desigma.b = sigma1.b - sigma2.b; + desigma.m = sigma1.m - sigma2.m; + + for (i = 1; i < length; i++) { + desigma.r += pix1->r - 2 * pix2->r + pix3->r; + desigma.g += pix1->g - 2 * pix2->g + pix3->g; + desigma.b += pix1->b - 2 * pix2->b + pix3->b; + desigma.m += pix1->m - 2 * pix2->m + pix3->m; + + rsum += (desigma.r + diff * (pix1->r - pix4->r)) * coeffq; + gsum += (desigma.g + diff * (pix1->g - pix4->g)) * coeffq; + bsum += (desigma.b + diff * (pix1->b - pix4->b)) * coeffq; + msum += (desigma.m + diff * (pix1->m - pix4->m)) * coeffq; + + row2->r = rsum; + row2->g = gsum; + row2->b = bsum; + row2->m = msum; + row2++; + pix1++, pix2++, pix3++, pix4++; + } } //------------------------------------------------------------------- @@ -233,531 +227,514 @@ inline void blur_code( //------------------------------------------------------------------- template -inline void blur_code_SSE2( - T *row1, BlurPixel

    *row2, - int length, - float coeff, float coeffq, - int brad, float diff, - float round_fac) -{ - - static float two = 2; - static __m128i zeros = _mm_setzero_si128(); - static __m128 twos = _mm_load_ps1(&two); - - int i; - - __m128 sigma1, sigma2, sigma3, desigma; - T *pix1, *pix2, *pix3, *pix4; - - pix1 = row1; - pix2 = row1 - 1; - - // - __m128i piPix1 = _mm_cvtsi32_si128(*(DWORD *)pix1); - __m128i piPix2 = _mm_cvtsi32_si128(*(DWORD *)pix2); - - piPix1 = _mm_unpacklo_epi8(piPix1, zeros); - piPix2 = _mm_unpacklo_epi8(piPix2, zeros); - piPix1 = _mm_unpacklo_epi16(piPix1, zeros); - piPix2 = _mm_unpacklo_epi16(piPix2, zeros); - - sigma1 = _mm_cvtepi32_ps(piPix1); - // - - pix1++; - - float zero = 0; - sigma2 = _mm_load1_ps(&zero); - sigma3 = _mm_load1_ps(&zero); - - for (i = 1; i < brad; i++) { - piPix1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(*(DWORD *)pix1), zeros); - piPix2 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(*(DWORD *)pix2), zeros); - - __m128 pPix1 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(piPix1, zeros)); - __m128 pPix2 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(piPix2, zeros)); - - sigma1 = _mm_add_ps(sigma1, pPix1); - sigma2 = _mm_add_ps(sigma2, pPix2); - - __m128i pii = _mm_unpacklo_epi8(_mm_cvtsi32_si128(i), zeros); - __m128 pi = _mm_cvtepi32_ps(_mm_unpacklo_epi16(pii, zeros)); - - pPix1 = _mm_add_ps(pPix1, pPix2); - pPix1 = _mm_mul_ps(pi, pPix1); // i*(pix1 + pix2) - sigma3 = _mm_add_ps(sigma3, pPix1); // sigma3 += i*(pix1 + pix2) - - pix1++; - pix2--; - } - - __m128 pCoeff = _mm_load1_ps(&coeff); - __m128 pCoeffq = _mm_load1_ps(&coeffq); - __m128 pRoundFac = _mm_load1_ps(&round_fac); - __m128 pDiff = _mm_load1_ps(&diff); - - // sum = (sigma1 + sigma2)*coeff - sigma3*coeffq + round_fac - __m128 sum = _mm_add_ps(sigma1, sigma2); - sum = _mm_mul_ps(sum, pCoeff); - __m128 sum2 = _mm_mul_ps(sigma3, pCoeffq); - sum2 = _mm_add_ps(sum2, pRoundFac); - sum = _mm_sub_ps(sum, sum2); - /* - __m128i isum = _mm_cvtps_epi32(sum); - isum = _mm_packs_epi32(isum, zeros); - isum = _mm_packs_epi16(isum, zeros); - - *(DWORD*)row2 = _mm_cvtsi128_si32(isum); -*/ - _mm_store_ps((float *)row2, sum); - row2++; +inline void blur_code_SSE2(T *row1, BlurPixel

    *row2, int length, float coeff, + float coeffq, int brad, float diff, + float round_fac) { + static float two = 2; + static __m128i zeros = _mm_setzero_si128(); + static __m128 twos = _mm_load_ps1(&two); - __m128i piPixMin = _mm_unpacklo_epi8(_mm_cvtsi32_si128(*(DWORD *)(row1 - brad)), zeros); - __m128 pPixMin = _mm_cvtepi32_ps(_mm_unpacklo_epi16(piPixMin, zeros)); - sigma2 = _mm_add_ps(sigma2, pPixMin); - /* - sigma2.r += row1[-brad].r; - sigma2.g += row1[-brad].g; - sigma2.b += row1[-brad].b; - sigma2.m += row1[-brad].m; + int i; + + __m128 sigma1, sigma2, sigma3, desigma; + T *pix1, *pix2, *pix3, *pix4; + + pix1 = row1; + pix2 = row1 - 1; + + // + __m128i piPix1 = _mm_cvtsi32_si128(*(DWORD *)pix1); + __m128i piPix2 = _mm_cvtsi32_si128(*(DWORD *)pix2); + + piPix1 = _mm_unpacklo_epi8(piPix1, zeros); + piPix2 = _mm_unpacklo_epi8(piPix2, zeros); + piPix1 = _mm_unpacklo_epi16(piPix1, zeros); + piPix2 = _mm_unpacklo_epi16(piPix2, zeros); + + sigma1 = _mm_cvtepi32_ps(piPix1); + // + + pix1++; + + float zero = 0; + sigma2 = _mm_load1_ps(&zero); + sigma3 = _mm_load1_ps(&zero); + + for (i = 1; i < brad; i++) { + piPix1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(*(DWORD *)pix1), zeros); + piPix2 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(*(DWORD *)pix2), zeros); + + __m128 pPix1 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(piPix1, zeros)); + __m128 pPix2 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(piPix2, zeros)); + + sigma1 = _mm_add_ps(sigma1, pPix1); + sigma2 = _mm_add_ps(sigma2, pPix2); + + __m128i pii = _mm_unpacklo_epi8(_mm_cvtsi32_si128(i), zeros); + __m128 pi = _mm_cvtepi32_ps(_mm_unpacklo_epi16(pii, zeros)); + + pPix1 = _mm_add_ps(pPix1, pPix2); + pPix1 = _mm_mul_ps(pi, pPix1); // i*(pix1 + pix2) + sigma3 = _mm_add_ps(sigma3, pPix1); // sigma3 += i*(pix1 + pix2) + + pix1++; + pix2--; + } + + __m128 pCoeff = _mm_load1_ps(&coeff); + __m128 pCoeffq = _mm_load1_ps(&coeffq); + __m128 pRoundFac = _mm_load1_ps(&round_fac); + __m128 pDiff = _mm_load1_ps(&diff); + + // sum = (sigma1 + sigma2)*coeff - sigma3*coeffq + round_fac + __m128 sum = _mm_add_ps(sigma1, sigma2); + sum = _mm_mul_ps(sum, pCoeff); + __m128 sum2 = _mm_mul_ps(sigma3, pCoeffq); + sum2 = _mm_add_ps(sum2, pRoundFac); + sum = _mm_sub_ps(sum, sum2); + /* + __m128i isum = _mm_cvtps_epi32(sum); +isum = _mm_packs_epi32(isum, zeros); +isum = _mm_packs_epi16(isum, zeros); + +*(DWORD*)row2 = _mm_cvtsi128_si32(isum); +*/ + _mm_store_ps((float *)row2, sum); + row2++; + + __m128i piPixMin = + _mm_unpacklo_epi8(_mm_cvtsi32_si128(*(DWORD *)(row1 - brad)), zeros); + __m128 pPixMin = _mm_cvtepi32_ps(_mm_unpacklo_epi16(piPixMin, zeros)); + sigma2 = _mm_add_ps(sigma2, pPixMin); + /* +sigma2.r += row1[-brad].r; +sigma2.g += row1[-brad].g; +sigma2.b += row1[-brad].b; +sigma2.m += row1[-brad].m; */ - pix1 = row1 + brad; - pix2 = row1; - pix3 = row1 - brad; - pix4 = row1 - brad + 1; - - desigma = _mm_sub_ps(sigma1, sigma2); - - for (i = 1; i < length; i++) { - piPix1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(*(DWORD *)pix1), zeros); - piPix2 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(*(DWORD *)pix2), zeros); - __m128i piPix3 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(*(DWORD *)pix3), zeros); - __m128i piPix4 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(*(DWORD *)pix4), zeros); - - __m128 pPix1 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(piPix1, zeros)); - __m128 pPix2 = _mm_cvtepi32_ps(_mm_slli_epi32(_mm_unpacklo_epi16(piPix2, zeros), 1)); - __m128 pPix3 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(piPix3, zeros)); - __m128 pPix4 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(piPix4, zeros)); - - // desigma += pix1 - 2*pix2 + pix3 - __m128 tmp = _mm_sub_ps(pPix3, pPix2); - tmp = _mm_add_ps(tmp, pPix1); - desigma = _mm_add_ps(desigma, tmp); - - // sum += (desigma + diff*(pix1 - pix4))*coeffq - tmp = _mm_sub_ps(pPix1, pPix4); - tmp = _mm_mul_ps(tmp, pDiff); - tmp = _mm_add_ps(desigma, tmp); - tmp = _mm_mul_ps(tmp, pCoeffq); - sum = _mm_add_ps(sum, tmp); - /* - isum = _mm_cvtps_epi32(sum); - isum = _mm_packs_epi32(isum, zeros); - isum = _mm_packs_epi16(isum, zeros); - - *(DWORD*)row2 = _mm_cvtsi128_si32(isum); + pix1 = row1 + brad; + pix2 = row1; + pix3 = row1 - brad; + pix4 = row1 - brad + 1; + + desigma = _mm_sub_ps(sigma1, sigma2); + + for (i = 1; i < length; i++) { + piPix1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(*(DWORD *)pix1), zeros); + piPix2 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(*(DWORD *)pix2), zeros); + __m128i piPix3 = + _mm_unpacklo_epi8(_mm_cvtsi32_si128(*(DWORD *)pix3), zeros); + __m128i piPix4 = + _mm_unpacklo_epi8(_mm_cvtsi32_si128(*(DWORD *)pix4), zeros); + + __m128 pPix1 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(piPix1, zeros)); + __m128 pPix2 = + _mm_cvtepi32_ps(_mm_slli_epi32(_mm_unpacklo_epi16(piPix2, zeros), 1)); + __m128 pPix3 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(piPix3, zeros)); + __m128 pPix4 = _mm_cvtepi32_ps(_mm_unpacklo_epi16(piPix4, zeros)); + + // desigma += pix1 - 2*pix2 + pix3 + __m128 tmp = _mm_sub_ps(pPix3, pPix2); + tmp = _mm_add_ps(tmp, pPix1); + desigma = _mm_add_ps(desigma, tmp); + + // sum += (desigma + diff*(pix1 - pix4))*coeffq + tmp = _mm_sub_ps(pPix1, pPix4); + tmp = _mm_mul_ps(tmp, pDiff); + tmp = _mm_add_ps(desigma, tmp); + tmp = _mm_mul_ps(tmp, pCoeffq); + sum = _mm_add_ps(sum, tmp); + /* +isum = _mm_cvtps_epi32(sum); +isum = _mm_packs_epi32(isum, zeros); +isum = _mm_packs_epi16(isum, zeros); + +*(DWORD*)row2 = _mm_cvtsi128_si32(isum); */ - _mm_store_ps((float *)row2, sum); + _mm_store_ps((float *)row2, sum); - row2++; - pix1++, pix2++, pix3++, pix4++; - } + row2++; + pix1++, pix2++, pix3++, pix4++; + } } //------------------------------------------------------------------- template -inline void blur_code_SSE2( - BlurPixel

    *row1, T *row2, - int length, - float coeff, float coeffq, - int brad, float diff, - float round_fac) -{ - int i; - - float two = 2; - __m128i zeros = _mm_setzero_si128(); - __m128 twos = _mm_load_ps1(&two); - - __m128 sigma1, sigma2, sigma3, desigma; - BlurPixel

    *pix1, *pix2, *pix3, *pix4; - - pix1 = row1; - pix2 = row1 - 1; - - __m128 pPix1 = _mm_load_ps((float *)pix1); - __m128 pPix2 = _mm_load_ps((float *)pix2); - - // sigma1 = *pix1 - sigma1 = pPix1; - - pix1++; - - float zero = 0; - sigma2 = _mm_load1_ps(&zero); - sigma3 = _mm_load1_ps(&zero); - - for (i = 1; i < brad; i++) { - pPix1 = _mm_load_ps((float *)pix1); - pPix2 = _mm_load_ps((float *)pix2); - - sigma1 = _mm_add_ps(sigma1, pPix1); - sigma2 = _mm_add_ps(sigma2, pPix2); - - __m128i pii = _mm_unpacklo_epi8(_mm_cvtsi32_si128(i), zeros); - __m128 pi = _mm_cvtepi32_ps(_mm_unpacklo_epi16(pii, zeros)); - - pPix1 = _mm_add_ps(pPix1, pPix2); - pPix1 = _mm_mul_ps(pi, pPix1); // i*(pix1 + pix2) - sigma3 = _mm_add_ps(sigma3, pPix1); // sigma3 += i*(pix1 + pix2) - - pix1++; - pix2--; - } - - __m128 pCoeff = _mm_load1_ps(&coeff); - __m128 pCoeffq = _mm_load1_ps(&coeffq); - // __m128 pRoundFac = _mm_load1_ps(&round_fac); - __m128 pDiff = _mm_load1_ps(&diff); - - // sum = (sigma1 + sigma2)*coeff - sigma3*coeffq + round_fac - __m128 sum = _mm_add_ps(sigma1, sigma2); - sum = _mm_mul_ps(sum, pCoeff); - __m128 sum2 = _mm_mul_ps(sigma3, pCoeffq); - //sum2 = _mm_add_ps(sum2, pRoundFac); - sum = _mm_sub_ps(sum, sum2); - - // converte i canali da float a char - __m128i isum = _mm_cvtps_epi32(sum); - isum = _mm_packs_epi32(isum, zeros); - //isum = _mm_packs_epi16(isum, zeros); - isum = _mm_packus_epi16(isum, zeros); - *(DWORD *)row2 = _mm_cvtsi128_si32(isum); - - row2++; - - // sigma2 += row1[-brad] - __m128 pPixMin = _mm_load_ps((float *)(row1 - brad)); - sigma2 = _mm_add_ps(sigma2, pPixMin); - - pix1 = row1 + brad; - pix2 = row1; - pix3 = row1 - brad; - pix4 = row1 - brad + 1; - - desigma = _mm_sub_ps(sigma1, sigma2); - - for (i = 1; i < length; i++) { - __m128 pPix1 = _mm_load_ps((float *)pix1); - __m128 pPix2 = _mm_load_ps((float *)pix2); - __m128 pPix3 = _mm_load_ps((float *)pix3); - __m128 pPix4 = _mm_load_ps((float *)pix4); - - pPix2 = _mm_mul_ps(pPix2, twos); - - // desigma += pix1 - 2*pix2 + pix3 - __m128 tmp = _mm_sub_ps(pPix3, pPix2); - tmp = _mm_add_ps(tmp, pPix1); - desigma = _mm_add_ps(desigma, tmp); - - // sum += (desigma + diff*(pix1 - pix4))*coeffq - tmp = _mm_sub_ps(pPix1, pPix4); - tmp = _mm_mul_ps(tmp, pDiff); - tmp = _mm_add_ps(desigma, tmp); - tmp = _mm_mul_ps(tmp, pCoeffq); - sum = _mm_add_ps(sum, tmp); - - // converte i canali da float a char - __m128i isum = _mm_cvtps_epi32(sum); - isum = _mm_packs_epi32(isum, zeros); - //isum = _mm_packs_epi16(isum, zeros); // QUESTA RIGA E' SBAGLIATA - //assert(false); - isum = _mm_packus_epi16(isum, zeros); - *(DWORD *)row2 = _mm_cvtsi128_si32(isum); - - row2++; - pix1++, pix2++, pix3++, pix4++; - } +inline void blur_code_SSE2(BlurPixel

    *row1, T *row2, int length, float coeff, + float coeffq, int brad, float diff, + float round_fac) { + int i; + + float two = 2; + __m128i zeros = _mm_setzero_si128(); + __m128 twos = _mm_load_ps1(&two); + + __m128 sigma1, sigma2, sigma3, desigma; + BlurPixel

    *pix1, *pix2, *pix3, *pix4; + + pix1 = row1; + pix2 = row1 - 1; + + __m128 pPix1 = _mm_load_ps((float *)pix1); + __m128 pPix2 = _mm_load_ps((float *)pix2); + + // sigma1 = *pix1 + sigma1 = pPix1; + + pix1++; + + float zero = 0; + sigma2 = _mm_load1_ps(&zero); + sigma3 = _mm_load1_ps(&zero); + + for (i = 1; i < brad; i++) { + pPix1 = _mm_load_ps((float *)pix1); + pPix2 = _mm_load_ps((float *)pix2); + + sigma1 = _mm_add_ps(sigma1, pPix1); + sigma2 = _mm_add_ps(sigma2, pPix2); + + __m128i pii = _mm_unpacklo_epi8(_mm_cvtsi32_si128(i), zeros); + __m128 pi = _mm_cvtepi32_ps(_mm_unpacklo_epi16(pii, zeros)); + + pPix1 = _mm_add_ps(pPix1, pPix2); + pPix1 = _mm_mul_ps(pi, pPix1); // i*(pix1 + pix2) + sigma3 = _mm_add_ps(sigma3, pPix1); // sigma3 += i*(pix1 + pix2) + + pix1++; + pix2--; + } + + __m128 pCoeff = _mm_load1_ps(&coeff); + __m128 pCoeffq = _mm_load1_ps(&coeffq); + // __m128 pRoundFac = _mm_load1_ps(&round_fac); + __m128 pDiff = _mm_load1_ps(&diff); + + // sum = (sigma1 + sigma2)*coeff - sigma3*coeffq + round_fac + __m128 sum = _mm_add_ps(sigma1, sigma2); + sum = _mm_mul_ps(sum, pCoeff); + __m128 sum2 = _mm_mul_ps(sigma3, pCoeffq); + // sum2 = _mm_add_ps(sum2, pRoundFac); + sum = _mm_sub_ps(sum, sum2); + + // converte i canali da float a char + __m128i isum = _mm_cvtps_epi32(sum); + isum = _mm_packs_epi32(isum, zeros); + // isum = _mm_packs_epi16(isum, zeros); + isum = _mm_packus_epi16(isum, zeros); + *(DWORD *)row2 = _mm_cvtsi128_si32(isum); + + row2++; + + // sigma2 += row1[-brad] + __m128 pPixMin = _mm_load_ps((float *)(row1 - brad)); + sigma2 = _mm_add_ps(sigma2, pPixMin); + + pix1 = row1 + brad; + pix2 = row1; + pix3 = row1 - brad; + pix4 = row1 - brad + 1; + + desigma = _mm_sub_ps(sigma1, sigma2); + + for (i = 1; i < length; i++) { + __m128 pPix1 = _mm_load_ps((float *)pix1); + __m128 pPix2 = _mm_load_ps((float *)pix2); + __m128 pPix3 = _mm_load_ps((float *)pix3); + __m128 pPix4 = _mm_load_ps((float *)pix4); + + pPix2 = _mm_mul_ps(pPix2, twos); + + // desigma += pix1 - 2*pix2 + pix3 + __m128 tmp = _mm_sub_ps(pPix3, pPix2); + tmp = _mm_add_ps(tmp, pPix1); + desigma = _mm_add_ps(desigma, tmp); + + // sum += (desigma + diff*(pix1 - pix4))*coeffq + tmp = _mm_sub_ps(pPix1, pPix4); + tmp = _mm_mul_ps(tmp, pDiff); + tmp = _mm_add_ps(desigma, tmp); + tmp = _mm_mul_ps(tmp, pCoeffq); + sum = _mm_add_ps(sum, tmp); + + // converte i canali da float a char + __m128i isum = _mm_cvtps_epi32(sum); + isum = _mm_packs_epi32(isum, zeros); + // isum = _mm_packs_epi16(isum, zeros); // QUESTA RIGA E' SBAGLIATA + // assert(false); + isum = _mm_packus_epi16(isum, zeros); + *(DWORD *)row2 = _mm_cvtsi128_si32(isum); + + row2++; + pix1++, pix2++, pix3++, pix4++; + } } -#endif // _WIN32 +#endif // _WIN32 //------------------------------------------------------------------- -#define STORE_COL_CODE(crop_val) \ - { \ - int i, val; \ - double ampl; \ - buffer += x; \ - \ - ampl = 1.0 + blur / 15.0; \ - \ - if (backlit) \ - for (i = ((dy >= 0) ? 0 : -dy); i < std::min(ly, r_ly - dy); i++) { \ - val = troundp(col[i].r * ampl); \ - buffer->r = (val > crop_val) ? crop_val : val; \ - val = troundp(col[i].g * ampl); \ - buffer->g = (val > crop_val) ? crop_val : val; \ - val = troundp(col[i].b * ampl); \ - buffer->b = (val > crop_val) ? crop_val : val; \ - val = troundp(col[i].m * ampl); \ - buffer->m = (val > crop_val) ? crop_val : val; \ - buffer += wrap; \ - } \ - else \ - for (i = ((dy >= 0) ? 0 : -dy); i < std::min(ly, r_ly - dy); i++) { \ - *buffer = col[i]; \ - buffer += wrap; \ - } \ - } +#define STORE_COL_CODE(crop_val) \ + { \ + int i, val; \ + double ampl; \ + buffer += x; \ + \ + ampl = 1.0 + blur / 15.0; \ + \ + if (backlit) \ + for (i = ((dy >= 0) ? 0 : -dy); i < std::min(ly, r_ly - dy); i++) { \ + val = troundp(col[i].r * ampl); \ + buffer->r = (val > crop_val) ? crop_val : val; \ + val = troundp(col[i].g * ampl); \ + buffer->g = (val > crop_val) ? crop_val : val; \ + val = troundp(col[i].b * ampl); \ + buffer->b = (val > crop_val) ? crop_val : val; \ + val = troundp(col[i].m * ampl); \ + buffer->m = (val > crop_val) ? crop_val : val; \ + buffer += wrap; \ + } \ + else \ + for (i = ((dy >= 0) ? 0 : -dy); i < std::min(ly, r_ly - dy); i++) { \ + *buffer = col[i]; \ + buffer += wrap; \ + } \ + } //------------------------------------------------------------------- template -void store_colRgb(T *buffer, int wrap, int r_ly, T *col, - int ly, int x, int dy, int backlit, double blur) -{ - int val = T::maxChannelValue; - - if (val == 255) - STORE_COL_CODE(204) - else if (val == 65535) - STORE_COL_CODE(204 * 257) - else - assert(false); +void store_colRgb(T *buffer, int wrap, int r_ly, T *col, int ly, int x, int dy, + int backlit, double blur) { + int val = T::maxChannelValue; + + if (val == 255) + STORE_COL_CODE(204) + else if (val == 65535) + STORE_COL_CODE(204 * 257) + else + assert(false); } //------------------------------------------------------------------- template -void store_colGray(T *buffer, int wrap, int r_ly, T *col, - int ly, int x, int dy, int backlit, double blur) -{ - int i; - double ampl; - buffer += x; - - ampl = 1.0 + blur / 15.0; - - for (i = ((dy >= 0) ? 0 : -dy); i < std::min(ly, r_ly - dy); i++) { - *buffer = col[i]; - buffer += wrap; - } +void store_colGray(T *buffer, int wrap, int r_ly, T *col, int ly, int x, int dy, + int backlit, double blur) { + int i; + double ampl; + buffer += x; + + ampl = 1.0 + blur / 15.0; + + for (i = ((dy >= 0) ? 0 : -dy); i < std::min(ly, r_ly - dy); i++) { + *buffer = col[i]; + buffer += wrap; + } } //------------------------------------------------------------------- template -void load_colRgb(BlurPixel

    *buffer, BlurPixel

    *col, - int lx, int ly, int x, int brad, int by1, int by2) -{ - int i; - BlurPixel

    *pix, left_val, right_val; +void load_colRgb(BlurPixel

    *buffer, BlurPixel

    *col, int lx, int ly, int x, + int brad, int by1, int by2) { + int i; + BlurPixel

    *pix, left_val, right_val; - LOAD_COL_CODE + LOAD_COL_CODE } //------------------------------------------------------------------- -void load_channel_col32(float *buffer, float *col, - int lx, int ly, int x, int brad, int by1, int by2) -{ - int i; - float *pix, left_val, right_val; +void load_channel_col32(float *buffer, float *col, int lx, int ly, int x, + int brad, int by1, int by2) { + int i; + float *pix, left_val, right_val; - LOAD_COL_CODE + LOAD_COL_CODE } //------------------------------------------------------------------- template -void do_filtering_chan(BlurPixel

    *row1, T *row2, int length, - float coeff, float coeffq, int brad, float diff, bool useSSE) -{ +void do_filtering_chan(BlurPixel

    *row1, T *row2, int length, float coeff, + float coeffq, int brad, float diff, bool useSSE) { #ifdef _WIN32 - if (useSSE && T::maxChannelValue == 255) - blur_code_SSE2(row1, row2, length, coeff, coeffq, brad, diff, 0.5); - else + if (useSSE && T::maxChannelValue == 255) + blur_code_SSE2(row1, row2, length, coeff, coeffq, brad, diff, 0.5); + else #endif - { - int i; - P rsum, gsum, bsum, msum; - BlurPixel

    sigma1, sigma2, sigma3, desigma; - BlurPixel

    *pix1, *pix2, *pix3, *pix4; - - BLUR_CODE((P)0.5, Q) - } + { + int i; + P rsum, gsum, bsum, msum; + BlurPixel

    sigma1, sigma2, sigma3, desigma; + BlurPixel

    *pix1, *pix2, *pix3, *pix4; + + BLUR_CODE((P)0.5, Q) + } } //------------------------------------------------------------------- template -void do_filtering_channel_float(T *row1, float *row2, - int length, - float coeff, float coeffq, - int brad, float diff) -{ - int i; - float sum; - float sigma1, sigma2, sigma3, desigma; - T *pix1, *pix2, *pix3, *pix4; +void do_filtering_channel_float(T *row1, float *row2, int length, float coeff, + float coeffq, int brad, float diff) { + int i; + float sum; + float sigma1, sigma2, sigma3, desigma; + T *pix1, *pix2, *pix3, *pix4; - pix1 = row1; - pix2 = row1 - 1; + pix1 = row1; + pix2 = row1 - 1; - sigma1 = pix1->value; - pix1++; + sigma1 = pix1->value; + pix1++; - sigma2 = 0.0; - sigma3 = 0.0; + sigma2 = 0.0; + sigma3 = 0.0; - for (i = 1; i < brad; i++) { - sigma1 += pix1->value; - sigma2 += pix2->value; - sigma3 += i * (pix1->value + pix2->value); - pix1++; - pix2--; - } + for (i = 1; i < brad; i++) { + sigma1 += pix1->value; + sigma2 += pix2->value; + sigma3 += i * (pix1->value + pix2->value); + pix1++; + pix2--; + } - sum = (sigma1 + sigma2) * coeff - sigma3 * coeffq; + sum = (sigma1 + sigma2) * coeff - sigma3 * coeffq; - *row2 = sum; - row2++; + *row2 = sum; + row2++; - sigma2 += row1[-brad].value; + sigma2 += row1[-brad].value; - pix1 = row1 + brad; - pix2 = row1; - pix3 = row1 - brad; - pix4 = row1 - brad + 1; + pix1 = row1 + brad; + pix2 = row1; + pix3 = row1 - brad; + pix4 = row1 - brad + 1; - desigma = sigma1 - sigma2; + desigma = sigma1 - sigma2; - for (i = 1; i < length; i++) { - desigma += pix1->value - 2 * pix2->value + pix3->value; + for (i = 1; i < length; i++) { + desigma += pix1->value - 2 * pix2->value + pix3->value; - sum += (desigma + diff * (pix1->value - pix4->value)) * coeffq; + sum += (desigma + diff * (pix1->value - pix4->value)) * coeffq; - *row2 = sum; - row2++; - pix1++, pix2++, pix3++, pix4++; - } + *row2 = sum; + row2++; + pix1++, pix2++, pix3++, pix4++; + } } //------------------------------------------------------------------- template -void do_filtering_channel_gray(float *row1, T *row2, int length, - float coeff, float coeffq, int brad, float diff) -{ - int i; - float sum; - float sigma1, sigma2, sigma3, desigma; - float *pix1, *pix2, *pix3, *pix4; +void do_filtering_channel_gray(float *row1, T *row2, int length, float coeff, + float coeffq, int brad, float diff) { + int i; + float sum; + float sigma1, sigma2, sigma3, desigma; + float *pix1, *pix2, *pix3, *pix4; - pix1 = row1; - pix2 = row1 - 1; + pix1 = row1; + pix2 = row1 - 1; - sigma1 = *pix1; - pix1++; + sigma1 = *pix1; + pix1++; - sigma2 = 0.0; - sigma3 = 0.0; + sigma2 = 0.0; + sigma3 = 0.0; - for (i = 1; i < brad; i++) { - sigma1 += *pix1; - sigma2 += *pix2; - sigma3 += i * (*pix1 + *pix2); - pix1++; - pix2--; - } + for (i = 1; i < brad; i++) { + sigma1 += *pix1; + sigma2 += *pix2; + sigma3 += i * (*pix1 + *pix2); + pix1++; + pix2--; + } - sum = (sigma1 + sigma2) * coeff - sigma3 * coeffq + 0.5F; + sum = (sigma1 + sigma2) * coeff - sigma3 * coeffq + 0.5F; - row2->setValue((int)sum); - row2++; + row2->setValue((int)sum); + row2++; - sigma2 += row1[-brad]; + sigma2 += row1[-brad]; - pix1 = row1 + brad; - pix2 = row1; - pix3 = row1 - brad; - pix4 = row1 - brad + 1; + pix1 = row1 + brad; + pix2 = row1; + pix3 = row1 - brad; + pix4 = row1 - brad + 1; - desigma = sigma1 - sigma2; + desigma = sigma1 - sigma2; - for (i = 1; i < length; i++) { - desigma += *pix1 - 2 * (*pix2) + (*pix3); + for (i = 1; i < length; i++) { + desigma += *pix1 - 2 * (*pix2) + (*pix3); - sum += (desigma + diff * (*pix1 - *pix4)) * coeffq; + sum += (desigma + diff * (*pix1 - *pix4)) * coeffq; - row2->setValue((int)sum); - row2++; - pix1++, pix2++, pix3++, pix4++; - } + row2->setValue((int)sum); + row2++; + pix1++, pix2++, pix3++, pix4++; + } } //------------------------------------------------------------------- template -void load_rowRgb(TRasterPT &rin, T *row, int lx, int y, int brad, - int bx1, int bx2) -{ - int i; - T *buf32, *pix; - T left_val, right_val; - - pix = row + bx1; - - { - rin->lock(); - buf32 = rin->pixels(y); - - for (i = 0; i < lx; i++) - *pix++ = *buf32++; - rin->unlock(); - } - - pix += bx2; - left_val = *row; - right_val = *(pix - 1); - row--; - - for (i = 0; i < brad; i++) /* pixels equal to the ones of border of image are added */ - { /* to avoid a black blur to get into the picture. */ - *row-- = left_val; - *pix++ = right_val; - } +void load_rowRgb(TRasterPT &rin, T *row, int lx, int y, int brad, int bx1, + int bx2) { + int i; + T *buf32, *pix; + T left_val, right_val; + + pix = row + bx1; + + { + rin->lock(); + buf32 = rin->pixels(y); + + for (i = 0; i < lx; i++) *pix++ = *buf32++; + rin->unlock(); + } + + pix += bx2; + left_val = *row; + right_val = *(pix - 1); + row--; + + for (i = 0; i < brad; + i++) /* pixels equal to the ones of border of image are added */ + { /* to avoid a black blur to get into the picture. */ + *row-- = left_val; + *pix++ = right_val; + } } //------------------------------------------------------------------- template -void load_rowGray(TRasterPT &rin, T *row, int lx, int y, int brad, - int bx1, int bx2) -{ - int i; - T *buf8, *pix; - T left_val, right_val; - - pix = row + bx1; - buf8 = (T *)(rin->pixels(y)); - - for (i = 0; i < lx; i++) - *pix++ = *buf8++; - - pix += bx2; - left_val = *row; - right_val = *(pix - 1); - row--; - - for (i = 0; i < brad; i++) /* pixels equal to the ones of border of image are added */ - { /* to avoid a black blur to get into the picture. */ - *row-- = left_val; - *pix++ = right_val; - } +void load_rowGray(TRasterPT &rin, T *row, int lx, int y, int brad, int bx1, + int bx2) { + int i; + T *buf8, *pix; + T left_val, right_val; + + pix = row + bx1; + buf8 = (T *)(rin->pixels(y)); + + for (i = 0; i < lx; i++) *pix++ = *buf8++; + + pix += bx2; + left_val = *row; + right_val = *(pix - 1); + row--; + + for (i = 0; i < brad; + i++) /* pixels equal to the ones of border of image are added */ + { /* to avoid a black blur to get into the picture. */ + *row-- = left_val; + *pix++ = right_val; + } } //------------------------------------------------------------------- template -void do_filtering_floatRgb(T *row1, BlurPixel

    *row2, int length, - float coeff, float coeffq, int brad, float diff, bool useSSE) -{ +void do_filtering_floatRgb(T *row1, BlurPixel

    *row2, int length, float coeff, + float coeffq, int brad, float diff, bool useSSE) { /* int i; float rsum, gsum, bsum, msum; @@ -768,226 +745,237 @@ void do_filtering_floatRgb(T *row1, BlurPixel

    *row2, int length, */ #ifdef _WIN32 - if (useSSE) - blur_code_SSE2(row1, row2, length, coeff, coeffq, brad, diff, 0); - else + if (useSSE) + blur_code_SSE2(row1, row2, length, coeff, coeffq, brad, diff, 0); + else #endif - blur_code, P>(row1, row2, length, coeff, coeffq, brad, diff, 0); + blur_code, P>(row1, row2, length, coeff, coeffq, brad, diff, + 0); } //------------------------------------------------------------------- template -void doBlurRgb(TRasterPT &dstRas, TRasterPT &srcRas, double blur, int dx, int dy, bool useSSE) -{ - int i, lx, ly, llx, lly, brad; - float coeff, coeffq, diff; - int bx1 = 0, by1 = 0, bx2 = 0, by2 = 0; +void doBlurRgb(TRasterPT &dstRas, TRasterPT &srcRas, double blur, int dx, + int dy, bool useSSE) { + int i, lx, ly, llx, lly, brad; + float coeff, coeffq, diff; + int bx1 = 0, by1 = 0, bx2 = 0, by2 = 0; - brad = (int)ceil(blur); /* number of pixels involved in the filtering */ + brad = (int)ceil(blur); /* number of pixels involved in the filtering */ - //int border = brad*2; // per sicurezza + // int border = brad*2; // per sicurezza - coeff = (float)(blur / (brad - brad * brad + blur * (2 * brad - 1))); /*sum of the weights of triangolar filter. */ - coeffq = (float)(coeff / blur); - diff = (float)(blur - brad); - lx = srcRas->getLx(); - ly = srcRas->getLy(); + coeff = (float)(blur / + (brad - brad * brad + + blur * (2 * brad - + 1))); /*sum of the weights of triangolar filter. */ + coeffq = (float)(coeff / blur); + diff = (float)(blur - brad); + lx = srcRas->getLx(); + ly = srcRas->getLy(); - if ((lx == 0) || (ly == 0)) - return; + if ((lx == 0) || (ly == 0)) return; - llx = lx + bx1 + bx2; - lly = ly + by1 + by2; + llx = lx + bx1 + bx2; + lly = ly + by1 + by2; - T *row1, *col2, *buffer; - BlurPixel

    *row2, *col1, *fbuffer; - TRasterGR8P r1; + T *row1, *col2, *buffer; + BlurPixel

    *row2, *col1, *fbuffer; + TRasterGR8P r1; #ifdef _WIN32 - if (useSSE) { - fbuffer = (BlurPixel

    *)_aligned_malloc(llx * ly * sizeof(BlurPixel

    ), 16); - row1 = (T *)_aligned_malloc((llx + 2 * brad) * sizeof(T), 16); - col1 = (BlurPixel

    *)_aligned_malloc((lly + 2 * brad) * sizeof(BlurPixel

    ), 16); - col2 = (T *)_aligned_malloc(lly * sizeof(T), 16); - } else + if (useSSE) { + fbuffer = + (BlurPixel

    *)_aligned_malloc(llx * ly * sizeof(BlurPixel

    ), 16); + row1 = (T *)_aligned_malloc((llx + 2 * brad) * sizeof(T), 16); + col1 = (BlurPixel

    *)_aligned_malloc( + (lly + 2 * brad) * sizeof(BlurPixel

    ), 16); + col2 = (T *)_aligned_malloc(lly * sizeof(T), 16); + } else #endif - { - TRasterGR8P raux(llx * sizeof(BlurPixel

    ), ly); - r1 = raux; - r1->lock(); - fbuffer = (BlurPixel

    *)r1->getRawData(); //new CASM_FPIXEL [llx *ly]; - row1 = new T[llx + 2 * brad]; - col1 = new BlurPixel

    [lly + 2 * brad]; - col2 = new T[lly]; - } - - if ((!fbuffer) || (!row1) || (!col1) || (!col2)) { - if (!useSSE) - r1->unlock(); + { + TRasterGR8P raux(llx * sizeof(BlurPixel

    ), ly); + r1 = raux; + r1->lock(); + fbuffer = (BlurPixel

    *)r1->getRawData(); // new CASM_FPIXEL [llx *ly]; + row1 = new T[llx + 2 * brad]; + col1 = new BlurPixel

    [lly + 2 * brad]; + col2 = new T[lly]; + } + + if ((!fbuffer) || (!row1) || (!col1) || (!col2)) { + if (!useSSE) r1->unlock(); #ifdef _WIN32 - if (useSSE) { - _aligned_free(col2); - _aligned_free(col1); - _aligned_free(row1); - _aligned_free(fbuffer); - } else + if (useSSE) { + _aligned_free(col2); + _aligned_free(col1); + _aligned_free(row1); + _aligned_free(fbuffer); + } else #endif - { - delete[] col2; - delete[] col1; - delete[] row1; - } - return; - } - - row2 = fbuffer; - - try { - for (i = 0; i < ly; i++) { - load_rowRgb(srcRas, row1 + brad, lx, i, brad, bx1, bx2); - do_filtering_floatRgb(row1 + brad, row2, llx, coeff, coeffq, brad, diff, useSSE); - row2 += llx; - } - dstRas->lock(); - buffer = (T *)dstRas->getRawData(); - - if (dy >= 0) - buffer += (dstRas->getWrap()) * dy; - - for (i = (dx >= 0) ? 0 : -dx; i < std::min(llx, dstRas->getLx() - dx); i++) { - load_colRgb

    (fbuffer, col1 + brad, llx, ly, i, brad, by1, by2); - do_filtering_chan(col1 + brad, col2, lly, coeff, coeffq, brad, diff, useSSE); - store_colRgb(buffer, dstRas->getWrap(), dstRas->getLy(), col2, lly, i + dx, dy, 0, blur); - } - dstRas->unlock(); - } catch (...) { - dstRas->clear(); - } + { + delete[] col2; + delete[] col1; + delete[] row1; + } + return; + } + + row2 = fbuffer; + + try { + for (i = 0; i < ly; i++) { + load_rowRgb(srcRas, row1 + brad, lx, i, brad, bx1, bx2); + do_filtering_floatRgb(row1 + brad, row2, llx, coeff, coeffq, brad, + diff, useSSE); + row2 += llx; + } + dstRas->lock(); + buffer = (T *)dstRas->getRawData(); + + if (dy >= 0) buffer += (dstRas->getWrap()) * dy; + + for (i = (dx >= 0) ? 0 : -dx; i < std::min(llx, dstRas->getLx() - dx); + i++) { + load_colRgb

    (fbuffer, col1 + brad, llx, ly, i, brad, by1, by2); + do_filtering_chan(col1 + brad, col2, lly, coeff, coeffq, brad, + diff, useSSE); + store_colRgb(buffer, dstRas->getWrap(), dstRas->getLy(), col2, lly, + i + dx, dy, 0, blur); + } + dstRas->unlock(); + } catch (...) { + dstRas->clear(); + } #ifdef _WIN32 - if (useSSE) { - _aligned_free(col2); - _aligned_free(col1); - _aligned_free(row1); - _aligned_free(fbuffer); - } else + if (useSSE) { + _aligned_free(col2); + _aligned_free(col1); + _aligned_free(row1); + _aligned_free(fbuffer); + } else #endif - { - delete[] col2; - delete[] col1; - delete[] row1; - r1->unlock(); - } + { + delete[] col2; + delete[] col1; + delete[] row1; + r1->unlock(); + } } //------------------------------------------------------------------- template -void doBlurGray(TRasterPT &dstRas, TRasterPT &srcRas, double blur, int dx, int dy) -{ - int i, lx, ly, llx, lly, brad; - float coeff, coeffq, diff; - int bx1 = 0, by1 = 0, bx2 = 0, by2 = 0; - - brad = (int)ceil(blur); /* number of pixels involved in the filtering */ - coeff = (float)(blur / (brad - brad * brad + blur * (2 * brad - 1))); /*sum of the weights of triangolar filter. */ - coeffq = (float)(coeff / blur); - diff = (float)(blur - brad); - lx = srcRas->getLx(); - ly = srcRas->getLy(); - - if ((lx == 0) || (ly == 0)) - return; - - llx = lx + bx1 + bx2; - lly = ly + by1 + by2; - - T *row1, *col2, *buffer; - float *row2, *col1, *fbuffer; - - TRasterGR8P r1(llx * sizeof(float), ly); - r1->lock(); - fbuffer = (float *)r1->getRawData(); //new float[llx *ly]; - - row1 = new T[llx + 2 * brad]; - col1 = new float[lly + 2 * brad]; - col2 = new T[lly]; - - if ((!fbuffer) || (!row1) || (!col1) || (!col2)) { - delete[] row1; - delete[] col1; - delete[] col2; - return; - } - - row2 = fbuffer; - - for (i = 0; i < ly; i++) { - load_rowGray(srcRas, row1 + brad, lx, i, brad, bx1, bx2); - do_filtering_channel_float(row1 + brad, row2, llx, coeff, coeffq, brad, diff); - row2 += llx; - } - dstRas->lock(); - buffer = (T *)dstRas->getRawData(); - - if (dy >= 0) - buffer += (dstRas->getWrap()) * dy; - - for (i = (dx >= 0) ? 0 : -dx; i < std::min(llx, dstRas->getLx() - dx); i++) { - load_channel_col32(fbuffer, col1 + brad, llx, ly, i, brad, by1, by2); - do_filtering_channel_gray(col1 + brad, col2, lly, coeff, coeffq, brad, diff); - - int backlit = 0; - store_colGray(buffer, dstRas->getWrap(), dstRas->getLy(), col2, lly, i + dx, dy, backlit, blur); - } - dstRas->unlock(); - delete[] col2; - delete[] col1; - delete[] row1; - r1->unlock(); //delete[]fbuffer; +void doBlurGray(TRasterPT &dstRas, TRasterPT &srcRas, double blur, int dx, + int dy) { + int i, lx, ly, llx, lly, brad; + float coeff, coeffq, diff; + int bx1 = 0, by1 = 0, bx2 = 0, by2 = 0; + + brad = (int)ceil(blur); /* number of pixels involved in the filtering */ + coeff = (float)(blur / + (brad - brad * brad + + blur * (2 * brad - + 1))); /*sum of the weights of triangolar filter. */ + coeffq = (float)(coeff / blur); + diff = (float)(blur - brad); + lx = srcRas->getLx(); + ly = srcRas->getLy(); + + if ((lx == 0) || (ly == 0)) return; + + llx = lx + bx1 + bx2; + lly = ly + by1 + by2; + + T *row1, *col2, *buffer; + float *row2, *col1, *fbuffer; + + TRasterGR8P r1(llx * sizeof(float), ly); + r1->lock(); + fbuffer = (float *)r1->getRawData(); // new float[llx *ly]; + + row1 = new T[llx + 2 * brad]; + col1 = new float[lly + 2 * brad]; + col2 = new T[lly]; + + if ((!fbuffer) || (!row1) || (!col1) || (!col2)) { + delete[] row1; + delete[] col1; + delete[] col2; + return; + } + + row2 = fbuffer; + + for (i = 0; i < ly; i++) { + load_rowGray(srcRas, row1 + brad, lx, i, brad, bx1, bx2); + do_filtering_channel_float(row1 + brad, row2, llx, coeff, coeffq, brad, + diff); + row2 += llx; + } + dstRas->lock(); + buffer = (T *)dstRas->getRawData(); + + if (dy >= 0) buffer += (dstRas->getWrap()) * dy; + + for (i = (dx >= 0) ? 0 : -dx; i < std::min(llx, dstRas->getLx() - dx); i++) { + load_channel_col32(fbuffer, col1 + brad, llx, ly, i, brad, by1, by2); + do_filtering_channel_gray(col1 + brad, col2, lly, coeff, coeffq, brad, + diff); + + int backlit = 0; + store_colGray(buffer, dstRas->getWrap(), dstRas->getLy(), col2, lly, + i + dx, dy, backlit, blur); + } + dstRas->unlock(); + delete[] col2; + delete[] col1; + delete[] row1; + r1->unlock(); // delete[]fbuffer; } -}; // namespace +}; // namespace //==================================================================== -int TRop::getBlurBorder(double blur) -{ - int brad = (int)ceil(blur); /* number of pixels involved in the filtering */ +int TRop::getBlurBorder(double blur) { + int brad = (int)ceil(blur); /* number of pixels involved in the filtering */ - int border = brad * 2; // per sicurezza - return border; + int border = brad * 2; // per sicurezza + return border; } //-------------------------------------------------------------------- -void TRop::blur(const TRasterP &dstRas, const TRasterP &srcRas, double blur, int dx, int dy, bool useSSE) -{ - TRaster32P dstRas32 = dstRas; - TRaster32P srcRas32 = srcRas; - - if (dstRas32 && srcRas32) - doBlurRgb(dstRas32, srcRas32, blur, dx, dy, useSSE); - else { - TRaster64P dstRas64 = dstRas; - TRaster64P srcRas64 = srcRas; - if (dstRas64 && srcRas64) - doBlurRgb(dstRas64, srcRas64, blur, dx, dy, useSSE); - else { - TRasterGR8P dstRasGR8 = dstRas; - TRasterGR8P srcRasGR8 = srcRas; - - if (dstRasGR8 && srcRasGR8) - doBlurGray(dstRasGR8, srcRasGR8, blur, dx, dy); - else { - TRasterGR16P dstRasGR16 = dstRas; - TRasterGR16P srcRasGR16 = srcRas; - - if (dstRasGR16 && srcRasGR16) - doBlurGray(dstRasGR16, srcRasGR16, blur, dx, dy); - else - throw TException("TRop::blur unsupported pixel type"); - } - } - } +void TRop::blur(const TRasterP &dstRas, const TRasterP &srcRas, double blur, + int dx, int dy, bool useSSE) { + TRaster32P dstRas32 = dstRas; + TRaster32P srcRas32 = srcRas; + + if (dstRas32 && srcRas32) + doBlurRgb(dstRas32, srcRas32, blur, dx, dy, useSSE); + else { + TRaster64P dstRas64 = dstRas; + TRaster64P srcRas64 = srcRas; + if (dstRas64 && srcRas64) + doBlurRgb(dstRas64, srcRas64, blur, dx, dy, + useSSE); + else { + TRasterGR8P dstRasGR8 = dstRas; + TRasterGR8P srcRasGR8 = srcRas; + + if (dstRasGR8 && srcRasGR8) + doBlurGray(dstRasGR8, srcRasGR8, blur, dx, dy); + else { + TRasterGR16P dstRasGR16 = dstRas; + TRasterGR16P srcRasGR16 = srcRas; + + if (dstRasGR16 && srcRasGR16) + doBlurGray(dstRasGR16, srcRasGR16, blur, dx, dy); + else + throw TException("TRop::blur unsupported pixel type"); + } + } + } } diff --git a/toonz/sources/common/trop/tcheckboard.cpp b/toonz/sources/common/trop/tcheckboard.cpp index c1b831e..71afc4a 100644 --- a/toonz/sources/common/trop/tcheckboard.cpp +++ b/toonz/sources/common/trop/tcheckboard.cpp @@ -6,7 +6,8 @@ #define FLOOR(x) ((int)(x) > (x) ? (int)(x)-1 : (int)(x)) /* -inline bool isInFirstColor(const TDimensionD &dim,int x, int y,const TPointD &offset) +inline bool isInFirstColor(const TDimensionD &dim,int x, int y,const TPointD +&offset) { int lx=dim.lx; int ly=dim.ly; @@ -21,76 +22,74 @@ inline bool isInFirstColor(const TDimensionD &dim,int x, int y,const TPointD &of //----------------------------------------------------------------------------- -namespace -{ +namespace { template void do_checkBoard(TRasterPT rout, const PIXEL &pix1, const PIXEL &pix2, - const TDimensionD &dim, const TPointD &offset) -{ - assert(dim.lx > 0); - assert(dim.ly > 0); - - double freqX = 0.5 / dim.lx; - double freqY = 0.5 / dim.ly; - - double phaseX = 0; - if (offset.x >= 0) { - double q = offset.x * freqX; - phaseX = (q - floor(q)); - } else { - double q = (-offset.x * freqX); - phaseX = 1.0 - (q - floor(q)); - } - - double phaseY = 0; - if (offset.y >= 0) { - double q = offset.y * freqY; - phaseY = (q - floor(q)); - } else { - double q = (-offset.y * freqY); - phaseY = 1.0 - (q - floor(q)); - } - - int lx = rout->getLx(); - int ly = rout->getLy(); - - for (int y = 0; y < ly; y++) { - double yy = 2.0 * (phaseY + y * freqY); - int iy = FLOOR(yy); - assert(iy == (int)floor(yy)); - rout->lock(); - PIXEL *pix = rout->pixels(y); - for (int x = 0; x < lx; x++) { - double xx = 2.0 * (phaseX + x * freqX); - int ix = FLOOR(xx); - assert(ix == (int)floor(xx)); - if ((ix ^ iy) & 1) - *pix++ = pix1; - else - *pix++ = pix2; - } - rout->unlock(); - } + const TDimensionD &dim, const TPointD &offset) { + assert(dim.lx > 0); + assert(dim.ly > 0); + + double freqX = 0.5 / dim.lx; + double freqY = 0.5 / dim.ly; + + double phaseX = 0; + if (offset.x >= 0) { + double q = offset.x * freqX; + phaseX = (q - floor(q)); + } else { + double q = (-offset.x * freqX); + phaseX = 1.0 - (q - floor(q)); + } + + double phaseY = 0; + if (offset.y >= 0) { + double q = offset.y * freqY; + phaseY = (q - floor(q)); + } else { + double q = (-offset.y * freqY); + phaseY = 1.0 - (q - floor(q)); + } + + int lx = rout->getLx(); + int ly = rout->getLy(); + + for (int y = 0; y < ly; y++) { + double yy = 2.0 * (phaseY + y * freqY); + int iy = FLOOR(yy); + assert(iy == (int)floor(yy)); + rout->lock(); + PIXEL *pix = rout->pixels(y); + for (int x = 0; x < lx; x++) { + double xx = 2.0 * (phaseX + x * freqX); + int ix = FLOOR(xx); + assert(ix == (int)floor(xx)); + if ((ix ^ iy) & 1) + *pix++ = pix1; + else + *pix++ = pix2; + } + rout->unlock(); + } } -} //namespace +} // namespace //----------------------------------------------------------------------------- void TRop::checkBoard(TRasterP rout, const TPixel32 &pix1, const TPixel32 &pix2, - const TDimensionD &dim, const TPointD &offset) -{ - //assert(offset.x<=dim.lx && offset.y<=dim.ly); - - TRaster32P rout32 = rout; - if (rout32) - do_checkBoard(rout32, pix1, pix2, dim, offset); - else { - TRaster64P rout64 = rout; - if (rout64) - do_checkBoard(rout64, toPixel64(pix1), toPixel64(pix2), dim, offset); - else - throw TRopException("unsupported pixel type"); - } + const TDimensionD &dim, const TPointD &offset) { + // assert(offset.x<=dim.lx && offset.y<=dim.ly); + + TRaster32P rout32 = rout; + if (rout32) + do_checkBoard(rout32, pix1, pix2, dim, offset); + else { + TRaster64P rout64 = rout; + if (rout64) + do_checkBoard(rout64, toPixel64(pix1), toPixel64(pix2), dim, + offset); + else + throw TRopException("unsupported pixel type"); + } } diff --git a/toonz/sources/common/trop/tconvert.cpp b/toonz/sources/common/trop/tconvert.cpp index 9d3b749..83fe96e 100644 --- a/toonz/sources/common/trop/tconvert.cpp +++ b/toonz/sources/common/trop/tconvert.cpp @@ -11,400 +11,374 @@ // Conversion functions //****************************************************************** -void do_convert(const TRaster64P &dst, const TRaster32P &src) -{ - assert(dst->getSize() == src->getSize()); - int lx = src->getLx(); - for (int y = 0; y < src->getLy(); y++) { - TPixel64 *outPix = dst->pixels(y); - TPixel32 *inPix = src->pixels(y); - TPixel32 *inEndPix = inPix + lx; - for (; inPix < inEndPix; ++outPix, ++inPix) { - outPix->r = ushortFromByte(inPix->r); - outPix->g = ushortFromByte(inPix->g); - outPix->b = ushortFromByte(inPix->b); - outPix->m = ushortFromByte(inPix->m); - } - } +void do_convert(const TRaster64P &dst, const TRaster32P &src) { + assert(dst->getSize() == src->getSize()); + int lx = src->getLx(); + for (int y = 0; y < src->getLy(); y++) { + TPixel64 *outPix = dst->pixels(y); + TPixel32 *inPix = src->pixels(y); + TPixel32 *inEndPix = inPix + lx; + for (; inPix < inEndPix; ++outPix, ++inPix) { + outPix->r = ushortFromByte(inPix->r); + outPix->g = ushortFromByte(inPix->g); + outPix->b = ushortFromByte(inPix->b); + outPix->m = ushortFromByte(inPix->m); + } + } } //----------------------------------------------------------------------------- -void do_convert(const TRasterGR8P &dst, const TRaster32P &src) -{ - assert(dst->getSize() == src->getSize()); +void do_convert(const TRasterGR8P &dst, const TRaster32P &src) { + assert(dst->getSize() == src->getSize()); - int lx = src->getLx(); + int lx = src->getLx(); - for (int y = 0; y < src->getLy(); ++y) { - TPixelGR8 *outPix = dst->pixels(y); - TPixel32 *inPix = src->pixels(y), *inEndPix = inPix + lx; + for (int y = 0; y < src->getLy(); ++y) { + TPixelGR8 *outPix = dst->pixels(y); + TPixel32 *inPix = src->pixels(y), *inEndPix = inPix + lx; - for (; inPix < inEndPix; ++outPix, ++inPix) - *outPix = TPixelGR8::from(overPix(TPixel32::White, *inPix)); - } + for (; inPix < inEndPix; ++outPix, ++inPix) + *outPix = TPixelGR8::from(overPix(TPixel32::White, *inPix)); + } } //----------------------------------------------------------------------------- -void do_convert(const TRasterGR16P &dst, const TRaster32P &src) -{ - assert(dst->getSize() == src->getSize()); +void do_convert(const TRasterGR16P &dst, const TRaster32P &src) { + assert(dst->getSize() == src->getSize()); - int lx = src->getLx(); + int lx = src->getLx(); - for (int y = 0; y < src->getLy(); ++y) { - TPixelGR16 *outPix = dst->pixels(y); - TPixel32 *inPix = src->pixels(y), *inEndPix = inPix + lx; + for (int y = 0; y < src->getLy(); ++y) { + TPixelGR16 *outPix = dst->pixels(y); + TPixel32 *inPix = src->pixels(y), *inEndPix = inPix + lx; - for (; inPix < inEndPix; ++outPix, ++inPix) - outPix->value = 257 * (TPixelGR8::from(overPix(TPixel32::White, *inPix))).value; - } + for (; inPix < inEndPix; ++outPix, ++inPix) + outPix->value = + 257 * (TPixelGR8::from(overPix(TPixel32::White, *inPix))).value; + } } //----------------------------------------------------------------------------- -void do_convert(const TRasterGR16P &dst, const TRaster64P &src) -{ - assert(dst->getSize() == src->getSize()); - int lx = src->getLx(); - for (int y = 0; y < src->getLy(); y++) { - TPixelGR16 *outPix = dst->pixels(y); - TPixel64 *inPix = src->pixels(y); - TPixel64 *inEndPix = inPix + lx; - while (inPix < inEndPix) { - outPix->value = (inPix->r + 2 * inPix->g + inPix->b) >> 2; - outPix++; - inPix++; - } - } +void do_convert(const TRasterGR16P &dst, const TRaster64P &src) { + assert(dst->getSize() == src->getSize()); + int lx = src->getLx(); + for (int y = 0; y < src->getLy(); y++) { + TPixelGR16 *outPix = dst->pixels(y); + TPixel64 *inPix = src->pixels(y); + TPixel64 *inEndPix = inPix + lx; + while (inPix < inEndPix) { + outPix->value = (inPix->r + 2 * inPix->g + inPix->b) >> 2; + outPix++; + inPix++; + } + } } //----------------------------------------------------------------------------- -void do_convert(const TRaster32P &dst, const TRasterGR8P &src) -{ - assert(dst->getSize() == src->getSize()); - int lx = src->getLx(); - for (int y = 0; y < src->getLy(); y++) { - TPixel32 *outPix = dst->pixels(y); - TPixelGR8 *inPix = src->pixels(y); - TPixelGR8 *inEndPix = inPix + lx; - while (inPix < inEndPix) { - outPix->r = inPix->value; - outPix->g = inPix->value; - outPix->b = inPix->value; - outPix->m = 0xff; - outPix++; - inPix++; - } - } +void do_convert(const TRaster32P &dst, const TRasterGR8P &src) { + assert(dst->getSize() == src->getSize()); + int lx = src->getLx(); + for (int y = 0; y < src->getLy(); y++) { + TPixel32 *outPix = dst->pixels(y); + TPixelGR8 *inPix = src->pixels(y); + TPixelGR8 *inEndPix = inPix + lx; + while (inPix < inEndPix) { + outPix->r = inPix->value; + outPix->g = inPix->value; + outPix->b = inPix->value; + outPix->m = 0xff; + outPix++; + inPix++; + } + } } //----------------------------------------------------------------------------- #define USHORT2BYTE_MAGICFAC (256U * 255U + 1U) -inline UCHAR ditherUcharFromUshort(USHORT in, UINT rndNum) -{ - return ((((in * USHORT2BYTE_MAGICFAC) - ((in * USHORT2BYTE_MAGICFAC) >> 24)) + rndNum) >> 24); +inline UCHAR ditherUcharFromUshort(USHORT in, UINT rndNum) { + return ((((in * USHORT2BYTE_MAGICFAC) - ((in * USHORT2BYTE_MAGICFAC) >> 24)) + + rndNum) >> + 24); } -inline void ditherRgbmFromRgbm64(TPixel32 &out, const TPixel64 &in, TRandom &rnd) -{ - UINT randomRound; - randomRound = rnd.getUInt() & ((1U << 24) - 1); +inline void ditherRgbmFromRgbm64(TPixel32 &out, const TPixel64 &in, + TRandom &rnd) { + UINT randomRound; + randomRound = rnd.getUInt() & ((1U << 24) - 1); - out.r = ditherUcharFromUshort(in.r, randomRound); - out.g = ditherUcharFromUshort(in.g, randomRound); - out.b = ditherUcharFromUshort(in.b, randomRound); - out.m = ditherUcharFromUshort(in.m, randomRound); + out.r = ditherUcharFromUshort(in.r, randomRound); + out.g = ditherUcharFromUshort(in.g, randomRound); + out.b = ditherUcharFromUshort(in.b, randomRound); + out.m = ditherUcharFromUshort(in.m, randomRound); } //----------------------------------------------------------------------------- -inline void ditherConvert(TRaster64P inRas, TRaster32P outRas) -{ - int inWrap = inRas->getWrap(); - int outWrap = outRas->getWrap(); - - TPixel64 *inPix = 0, *inRow = inRas->pixels(); - TPixel32 *outPix, *outRow = outRas->pixels(); - TPixel64 *endPix; - int inLx = inRas->getLx(); - TPixel64 *lastPix = inRow + inWrap * (inRas->getLy() - 1) + inLx; - - TRandom rnd(130266); - - while (inPix < lastPix) { - inPix = inRow; - outPix = outRow; - endPix = inPix + inLx; - while (inPix < endPix) { - ditherRgbmFromRgbm64(*outPix, *inPix, rnd); - inPix++; - outPix++; - } - inRow += inWrap; - outRow += outWrap; - } +inline void ditherConvert(TRaster64P inRas, TRaster32P outRas) { + int inWrap = inRas->getWrap(); + int outWrap = outRas->getWrap(); + + TPixel64 *inPix = 0, *inRow = inRas->pixels(); + TPixel32 *outPix, *outRow = outRas->pixels(); + TPixel64 *endPix; + int inLx = inRas->getLx(); + TPixel64 *lastPix = inRow + inWrap * (inRas->getLy() - 1) + inLx; + + TRandom rnd(130266); + + while (inPix < lastPix) { + inPix = inRow; + outPix = outRow; + endPix = inPix + inLx; + while (inPix < endPix) { + ditherRgbmFromRgbm64(*outPix, *inPix, rnd); + inPix++; + outPix++; + } + inRow += inWrap; + outRow += outWrap; + } } //****************************************************************** // Obsolete conversion functions //****************************************************************** -void do_convert(const TRasterCM32P &dst, const TRasterGR8P &src) -{ - assert(dst->getSize() == src->getSize()); - TPixelCM32 bg = TPixelCM32(0, 0, TPixelCM32::getMaxTone()); - - int lx = src->getLx(); - for (int y = 0; y < src->getLy(); y++) { - TPixelCM32 *outPix = dst->pixels(y); - TPixelGR8 *inPix = src->pixels(y); - TPixelGR8 *inEndPix = inPix + lx; - while (inPix < inEndPix) { - *outPix = (inPix->value == 255) ? bg : TPixelCM32(1, 0, inPix->value); - outPix++; - inPix++; - } - } +void do_convert(const TRasterCM32P &dst, const TRasterGR8P &src) { + assert(dst->getSize() == src->getSize()); + TPixelCM32 bg = TPixelCM32(0, 0, TPixelCM32::getMaxTone()); + + int lx = src->getLx(); + for (int y = 0; y < src->getLy(); y++) { + TPixelCM32 *outPix = dst->pixels(y); + TPixelGR8 *inPix = src->pixels(y); + TPixelGR8 *inEndPix = inPix + lx; + while (inPix < inEndPix) { + *outPix = (inPix->value == 255) ? bg : TPixelCM32(1, 0, inPix->value); + outPix++; + inPix++; + } + } } //----------------------------------------------------------------------------- -void do_convert(const TRasterCM32P &dst, const TRaster32P &src) -{ - assert(dst->getSize() == src->getSize()); - TPixelCM32 bg = TPixelCM32(0, 0, TPixelCM32::getMaxTone()); - - int lx = src->getLx(); - - bool isOverlay = false; - - for (int y = 0; y < src->getLy(); y++) //if it is an overlay, I use the matte value for inks, otherwise I use the brightness. - { - TPixel32 *inPix = src->pixels(y); - TPixel32 *inEndPix = inPix + lx; - while (inPix < inEndPix) { - if (inPix->m != 255) { - isOverlay = true; - break; - } - inPix++; - } - if (isOverlay) - break; - } - - if (isOverlay) - for (int y = 0; y < src->getLy(); y++) { - TPixelCM32 *outPix = dst->pixels(y); - TPixel32 *inPix = src->pixels(y); - TPixel32 *inEndPix = inPix + lx; - while (inPix < inEndPix) { - *outPix = (inPix->m == 0) ? bg : TPixelCM32(1, 0, 255 - inPix->m); - outPix++; - inPix++; - } - } - else - for (int y = 0; y < src->getLy(); y++) { - TPixelCM32 *outPix = dst->pixels(y); - TPixel32 *inPix = src->pixels(y); - TPixel32 *inEndPix = inPix + lx; - while (inPix < inEndPix) { - UCHAR val = TPixelGR8::from(*inPix).value; - *outPix = (val == 255) ? bg : TPixelCM32(1, 0, val); - outPix++; - inPix++; - } - } +void do_convert(const TRasterCM32P &dst, const TRaster32P &src) { + assert(dst->getSize() == src->getSize()); + TPixelCM32 bg = TPixelCM32(0, 0, TPixelCM32::getMaxTone()); + + int lx = src->getLx(); + + bool isOverlay = false; + + for (int y = 0; y < src->getLy(); y++) // if it is an overlay, I use the + // matte value for inks, otherwise I + // use the brightness. + { + TPixel32 *inPix = src->pixels(y); + TPixel32 *inEndPix = inPix + lx; + while (inPix < inEndPix) { + if (inPix->m != 255) { + isOverlay = true; + break; + } + inPix++; + } + if (isOverlay) break; + } + + if (isOverlay) + for (int y = 0; y < src->getLy(); y++) { + TPixelCM32 *outPix = dst->pixels(y); + TPixel32 *inPix = src->pixels(y); + TPixel32 *inEndPix = inPix + lx; + while (inPix < inEndPix) { + *outPix = (inPix->m == 0) ? bg : TPixelCM32(1, 0, 255 - inPix->m); + outPix++; + inPix++; + } + } + else + for (int y = 0; y < src->getLy(); y++) { + TPixelCM32 *outPix = dst->pixels(y); + TPixel32 *inPix = src->pixels(y); + TPixel32 *inEndPix = inPix + lx; + while (inPix < inEndPix) { + UCHAR val = TPixelGR8::from(*inPix).value; + *outPix = (val == 255) ? bg : TPixelCM32(1, 0, val); + outPix++; + inPix++; + } + } } //----------------------------------------------------------------------------- -void do_convert(const TRasterYUV422P &dst, const TRaster32P &src) -{ - assert(src->getLx() & 0); - long y1, y2, u, v, u1, u2, v1, v2; - TPixel32 *pix = (TPixel32 *)src->pixels(); - TPixel32 *lastPix = &(src->pixels(src->getLy() - 1)[src->getLx() - 1]); - - UCHAR *out = dst->getRawData(); - - while (pix < lastPix) { - /* first pixel gives Y and 0.5 of chroma */ - - y1 = 16829 * pix->r + 33039 * pix->g + 6416 * pix->b; - u1 = -4831 * pix->r + -9488 * pix->g + 14319 * pix->b; - v1 = 14322 * pix->r + -11992 * pix->g + -2330 * pix->b; - - /* second pixel gives Y and 0.5 of chroma */ - ++pix; - - y2 = 16829 * pix->r + 33039 * pix->g + 6416 * pix->b; - u2 = -4831 * pix->r + -9488 * pix->g + 14319 * pix->b; - v2 = 14322 * pix->r + -11992 * pix->g + -2330 * pix->b; - - /* average the chroma */ - u = u1 + u2; - v = v1 + v2; - - /* round the chroma */ - u1 = (u + 0x008000) >> 16; - v1 = (v + 0x008000) >> 16; - - /* limit the chroma */ - if (u1 < -112) - u1 = -112; - if (u1 > 111) - u1 = 111; - if (v1 < -112) - v1 = -112; - if (v1 > 111) - v1 = 111; - - /* limit the lum */ - if (y1 > 0x00dbffff) - y1 = 0x00dbffff; - if (y2 > 0x00dbffff) - y2 = 0x00dbffff; - - /* save the results */ - *out++ = (UCHAR)(u1 + 128); - *out++ = (UCHAR)((y1 >> 16) + 16); - *out++ = (UCHAR)(v1 + 128); - *out++ = (UCHAR)((y2 >> 16) + 16); - ++pix; - } +void do_convert(const TRasterYUV422P &dst, const TRaster32P &src) { + assert(src->getLx() & 0); + long y1, y2, u, v, u1, u2, v1, v2; + TPixel32 *pix = (TPixel32 *)src->pixels(); + TPixel32 *lastPix = &(src->pixels(src->getLy() - 1)[src->getLx() - 1]); + + UCHAR *out = dst->getRawData(); + + while (pix < lastPix) { + /* first pixel gives Y and 0.5 of chroma */ + + y1 = 16829 * pix->r + 33039 * pix->g + 6416 * pix->b; + u1 = -4831 * pix->r + -9488 * pix->g + 14319 * pix->b; + v1 = 14322 * pix->r + -11992 * pix->g + -2330 * pix->b; + + /* second pixel gives Y and 0.5 of chroma */ + ++pix; + + y2 = 16829 * pix->r + 33039 * pix->g + 6416 * pix->b; + u2 = -4831 * pix->r + -9488 * pix->g + 14319 * pix->b; + v2 = 14322 * pix->r + -11992 * pix->g + -2330 * pix->b; + + /* average the chroma */ + u = u1 + u2; + v = v1 + v2; + + /* round the chroma */ + u1 = (u + 0x008000) >> 16; + v1 = (v + 0x008000) >> 16; + + /* limit the chroma */ + if (u1 < -112) u1 = -112; + if (u1 > 111) u1 = 111; + if (v1 < -112) v1 = -112; + if (v1 > 111) v1 = 111; + + /* limit the lum */ + if (y1 > 0x00dbffff) y1 = 0x00dbffff; + if (y2 > 0x00dbffff) y2 = 0x00dbffff; + + /* save the results */ + *out++ = (UCHAR)(u1 + 128); + *out++ = (UCHAR)((y1 >> 16) + 16); + *out++ = (UCHAR)(v1 + 128); + *out++ = (UCHAR)((y2 >> 16) + 16); + ++pix; + } } //----------------------------------------------------------------------------- -void do_convert(const TRaster32P &dst, const TRasterYUV422P &src) -{ - int long r, g, b, y1, y2, u, v; - TPixel32 *buf = dst->pixels(); - const UCHAR *in = src->getRawData(); - const UCHAR *last = in + src->getRowSize() * src->getLy() - 1; - - while (in < last) { - u = *in; - u -= 128; - in++; - y1 = *in; - y1 -= 16; - in++; - v = *in; - v -= 128; - in++; - y2 = *in; - y2 -= 16; - in++; - - r = 76310 * y1 + 104635 * v; - if (r > 0xFFFFFF) - r = 0xFFFFFF; - if (r <= 0xFFFF) - r = 0; - - g = 76310 * y1 + -25690 * u + -53294 * v; - if (g > 0xFFFFFF) - g = 0xFFFFFF; - if (g <= 0xFFFF) - g = 0; - - b = 76310 * y1 + 132278 * u; - if (b > 0xFFFFFF) - b = 0xFFFFFF; - if (b <= 0xFFFF) - b = 0; - - buf->r = (UCHAR)(r >> 16); - buf->g = (UCHAR)(g >> 16); - buf->b = (UCHAR)(b >> 16); - buf->m = (UCHAR)255; - buf++; - - r = 76310 * y2 + 104635 * v; - if (r > 0xFFFFFF) - r = 0xFFFFFF; - if (r <= 0xFFFF) - r = 0; - - g = 76310 * y2 + -25690 * u + -53294 * v; - if (g > 0xFFFFFF) - g = 0xFFFFFF; - if (g <= 0xFFFF) - g = 0; - - b = 76310 * y2 + 132278 * u; - if (b > 0xFFFFFF) - b = 0xFFFFFF; - if (b <= 0xFFFF) - b = 0; - - buf->r = (UCHAR)(r >> 16); - buf->g = (UCHAR)(g >> 16); - buf->b = (UCHAR)(b >> 16); - buf->m = (UCHAR)255; - buf++; - } +void do_convert(const TRaster32P &dst, const TRasterYUV422P &src) { + int long r, g, b, y1, y2, u, v; + TPixel32 *buf = dst->pixels(); + const UCHAR *in = src->getRawData(); + const UCHAR *last = in + src->getRowSize() * src->getLy() - 1; + + while (in < last) { + u = *in; + u -= 128; + in++; + y1 = *in; + y1 -= 16; + in++; + v = *in; + v -= 128; + in++; + y2 = *in; + y2 -= 16; + in++; + + r = 76310 * y1 + 104635 * v; + if (r > 0xFFFFFF) r = 0xFFFFFF; + if (r <= 0xFFFF) r = 0; + + g = 76310 * y1 + -25690 * u + -53294 * v; + if (g > 0xFFFFFF) g = 0xFFFFFF; + if (g <= 0xFFFF) g = 0; + + b = 76310 * y1 + 132278 * u; + if (b > 0xFFFFFF) b = 0xFFFFFF; + if (b <= 0xFFFF) b = 0; + + buf->r = (UCHAR)(r >> 16); + buf->g = (UCHAR)(g >> 16); + buf->b = (UCHAR)(b >> 16); + buf->m = (UCHAR)255; + buf++; + + r = 76310 * y2 + 104635 * v; + if (r > 0xFFFFFF) r = 0xFFFFFF; + if (r <= 0xFFFF) r = 0; + + g = 76310 * y2 + -25690 * u + -53294 * v; + if (g > 0xFFFFFF) g = 0xFFFFFF; + if (g <= 0xFFFF) g = 0; + + b = 76310 * y2 + 132278 * u; + if (b > 0xFFFFFF) b = 0xFFFFFF; + if (b <= 0xFFFF) b = 0; + + buf->r = (UCHAR)(r >> 16); + buf->g = (UCHAR)(g >> 16); + buf->b = (UCHAR)(b >> 16); + buf->m = (UCHAR)255; + buf++; + } } //****************************************************************** // Main conversion function //****************************************************************** -void TRop::convert(TRasterP dst, const TRasterP &src) -{ - if (dst->getSize() != src->getSize()) - throw TRopException("convert: size mismatch"); - - TRaster32P dst32 = dst; - TRasterGR8P dst8 = dst; - TRasterGR16P dst16 = dst; - TRaster64P dst64 = dst; - TRasterCM32P dstCm = dst; - - TRaster32P src32 = src; - TRasterGR8P src8 = src; - TRaster64P src64 = src; - TRasterYUV422P srcYUV = src; - TRasterYUV422P dstYUV = dst; - - src->lock(); - dst->lock(); - - if (dst64 && src32) - do_convert(dst64, src32); - else if (dst8 && src32) - do_convert(dst8, src32); - else if (dst16 && src32) - do_convert(dst16, src32); - else if (dst32 && src64) - ditherConvert(src64, dst32); - else if (dst16 && src64) - do_convert(dst16, src64); - else if (dst32 && src8) - do_convert(dst32, src8); - else if (dstYUV && src32) - do_convert(dstYUV, src32); // Obsolete conversions - else if (dst32 && srcYUV) - do_convert(dst32, srcYUV); // - else if (dstCm && src32) - do_convert(dstCm, src32); // - else if (dstCm && src8) - do_convert(dstCm, src8); // - else { - dst->unlock(); - src->unlock(); - - throw TRopException("unsupported pixel type"); - } - - dst->unlock(); - src->unlock(); +void TRop::convert(TRasterP dst, const TRasterP &src) { + if (dst->getSize() != src->getSize()) + throw TRopException("convert: size mismatch"); + + TRaster32P dst32 = dst; + TRasterGR8P dst8 = dst; + TRasterGR16P dst16 = dst; + TRaster64P dst64 = dst; + TRasterCM32P dstCm = dst; + + TRaster32P src32 = src; + TRasterGR8P src8 = src; + TRaster64P src64 = src; + TRasterYUV422P srcYUV = src; + TRasterYUV422P dstYUV = dst; + + src->lock(); + dst->lock(); + + if (dst64 && src32) + do_convert(dst64, src32); + else if (dst8 && src32) + do_convert(dst8, src32); + else if (dst16 && src32) + do_convert(dst16, src32); + else if (dst32 && src64) + ditherConvert(src64, dst32); + else if (dst16 && src64) + do_convert(dst16, src64); + else if (dst32 && src8) + do_convert(dst32, src8); + else if (dstYUV && src32) + do_convert(dstYUV, src32); // Obsolete conversions + else if (dst32 && srcYUV) + do_convert(dst32, srcYUV); // + else if (dstCm && src32) + do_convert(dstCm, src32); // + else if (dstCm && src8) + do_convert(dstCm, src8); // + else { + dst->unlock(); + src->unlock(); + + throw TRopException("unsupported pixel type"); + } + + dst->unlock(); + src->unlock(); } diff --git a/toonz/sources/common/trop/tconvolve.cpp b/toonz/sources/common/trop/tconvolve.cpp index e7f2eed..7eb4a07 100644 --- a/toonz/sources/common/trop/tconvolve.cpp +++ b/toonz/sources/common/trop/tconvolve.cpp @@ -12,644 +12,633 @@ //------------------------------------------------------------------------------ -namespace -{ +namespace { //------------------------------------------------------------------------------ template -void doConvolve_row_9_i(PIXOUT *pixout, int n, PIXIN *pixarr[], long w[]) -{ - long w1, w2, w3, w4, w5, w6, w7, w8, w9; - PIXIN *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9; - w1 = w[0]; - w2 = w[1]; - w3 = w[2]; - w4 = w[3]; - w5 = w[4]; - w6 = w[5]; - w7 = w[6]; - w8 = w[7]; - w9 = w[8]; - p1 = pixarr[0]; - p2 = pixarr[1]; - p3 = pixarr[2]; - p4 = pixarr[3]; - p5 = pixarr[4]; - p6 = pixarr[5]; - p7 = pixarr[6]; - p8 = pixarr[7]; - p9 = pixarr[8]; - - int rightShift = 16 + ((int)sizeof(typename PIXIN::Channel) - (int)sizeof(typename PIXOUT::Channel)) * 8; - - while (n-- > 0) { - pixout->r = (typename PIXOUT::Channel)((p1->r * w1 + p2->r * w2 + p3->r * w3 + - p4->r * w4 + p5->r * w5 + p6->r * w6 + - p7->r * w7 + p8->r * w8 + p9->r * w9 + (1 << 15)) >> - rightShift); - pixout->g = (typename PIXOUT::Channel)((p1->g * w1 + p2->g * w2 + p3->g * w3 + - p4->g * w4 + p5->g * w5 + p6->g * w6 + - p7->g * w7 + p8->g * w8 + p9->g * w9 + (1 << 15)) >> - rightShift); - pixout->b = (typename PIXOUT::Channel)((p1->b * w1 + p2->b * w2 + p3->b * w3 + - p4->b * w4 + p5->b * w5 + p6->b * w6 + - p7->b * w7 + p8->b * w8 + p9->b * w9 + (1 << 15)) >> - rightShift); - pixout->m = (typename PIXOUT::Channel)((p1->m * w1 + p2->m * w2 + p3->m * w3 + - p4->m * w4 + p5->m * w5 + p6->m * w6 + - p7->m * w7 + p8->m * w8 + p9->m * w9 + (1 << 15)) >> - rightShift); - - p1++; - p2++; - p3++; - p4++; - p5++; - p6++; - p7++; - p8++; - p9++; - pixout++; - } +void doConvolve_row_9_i(PIXOUT *pixout, int n, PIXIN *pixarr[], long w[]) { + long w1, w2, w3, w4, w5, w6, w7, w8, w9; + PIXIN *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9; + w1 = w[0]; + w2 = w[1]; + w3 = w[2]; + w4 = w[3]; + w5 = w[4]; + w6 = w[5]; + w7 = w[6]; + w8 = w[7]; + w9 = w[8]; + p1 = pixarr[0]; + p2 = pixarr[1]; + p3 = pixarr[2]; + p4 = pixarr[3]; + p5 = pixarr[4]; + p6 = pixarr[5]; + p7 = pixarr[6]; + p8 = pixarr[7]; + p9 = pixarr[8]; + + int rightShift = 16 + + ((int)sizeof(typename PIXIN::Channel) - + (int)sizeof(typename PIXOUT::Channel)) * + 8; + + while (n-- > 0) { + pixout->r = (typename PIXOUT::Channel)( + (p1->r * w1 + p2->r * w2 + p3->r * w3 + p4->r * w4 + p5->r * w5 + + p6->r * w6 + p7->r * w7 + p8->r * w8 + p9->r * w9 + (1 << 15)) >> + rightShift); + pixout->g = (typename PIXOUT::Channel)( + (p1->g * w1 + p2->g * w2 + p3->g * w3 + p4->g * w4 + p5->g * w5 + + p6->g * w6 + p7->g * w7 + p8->g * w8 + p9->g * w9 + (1 << 15)) >> + rightShift); + pixout->b = (typename PIXOUT::Channel)( + (p1->b * w1 + p2->b * w2 + p3->b * w3 + p4->b * w4 + p5->b * w5 + + p6->b * w6 + p7->b * w7 + p8->b * w8 + p9->b * w9 + (1 << 15)) >> + rightShift); + pixout->m = (typename PIXOUT::Channel)( + (p1->m * w1 + p2->m * w2 + p3->m * w3 + p4->m * w4 + p5->m * w5 + + p6->m * w6 + p7->m * w7 + p8->m * w8 + p9->m * w9 + (1 << 15)) >> + rightShift); + + p1++; + p2++; + p3++; + p4++; + p5++; + p6++; + p7++; + p8++; + p9++; + pixout++; + } } //------------------------------------------------------------------------------ template -void doConvolve_cm32_row_9_i(PIXOUT *pixout, int n, - TPixelCM32 *pixarr[], long w[], - const std::vector &paints, - const std::vector &inks) -{ - long w1, w2, w3, w4, w5, w6, w7, w8, w9; - TPixelCM32 *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9; - TPixel32 val[9]; - - w1 = w[0]; - w2 = w[1]; - w3 = w[2]; - w4 = w[3]; - w5 = w[4]; - w6 = w[5]; - w7 = w[6]; - w8 = w[7]; - w9 = w[8]; - p1 = pixarr[0]; - p2 = pixarr[1]; - p3 = pixarr[2]; - p4 = pixarr[3]; - p5 = pixarr[4]; - p6 = pixarr[5]; - p7 = pixarr[6]; - p8 = pixarr[7]; - p9 = pixarr[8]; - while (n-- > 0) { - for (int i = 0; i < 9; ++i) { - int tone = p1->getTone(); - int paint = p1->getPaint(); - int ink = p1->getInk(); - if (tone == TPixelCM32::getMaxTone()) - val[i] = paints[paint]; - else if (tone == 0) - val[i] = inks[ink]; - else - val[i] = blend(inks[ink], paints[paint], tone, TPixelCM32::getMaxTone()); - } - - pixout->r = (typename PIXOUT::Channel)((val[1].r * w1 + val[2].r * w2 + val[3].r * w3 + - val[4].r * w4 + val[5].r * w5 + val[6].r * w6 + - val[7].r * w7 + val[8].r * w8 + val[9].r * w9 + (1 << 15)) >> - 16); - pixout->g = (typename PIXOUT::Channel)((val[1].g * w1 + val[2].g * w2 + val[3].g * w3 + - val[4].g * w4 + val[5].g * w5 + val[6].g * w6 + - val[7].g * w7 + val[8].g * w8 + val[9].g * w9 + (1 << 15)) >> - 16); - pixout->b = (typename PIXOUT::Channel)((val[1].b * w1 + val[2].b * w2 + val[3].b * w3 + - val[4].b * w4 + val[5].b * w5 + val[6].b * w6 + - val[7].b * w7 + val[8].b * w8 + val[9].b * w9 + (1 << 15)) >> - 16); - pixout->m = (typename PIXOUT::Channel)((val[1].m * w1 + val[2].m * w2 + val[3].m * w3 + - val[4].m * w4 + val[5].m * w5 + val[6].m * w6 + - val[7].m * w7 + val[8].m * w8 + val[9].m * w9 + (1 << 15)) >> - 16); - p1++; - p2++; - p3++; - p4++; - p5++; - p6++; - p7++; - p8++; - p9++; - pixout++; - } +void doConvolve_cm32_row_9_i(PIXOUT *pixout, int n, TPixelCM32 *pixarr[], + long w[], const std::vector &paints, + const std::vector &inks) { + long w1, w2, w3, w4, w5, w6, w7, w8, w9; + TPixelCM32 *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9; + TPixel32 val[9]; + + w1 = w[0]; + w2 = w[1]; + w3 = w[2]; + w4 = w[3]; + w5 = w[4]; + w6 = w[5]; + w7 = w[6]; + w8 = w[7]; + w9 = w[8]; + p1 = pixarr[0]; + p2 = pixarr[1]; + p3 = pixarr[2]; + p4 = pixarr[3]; + p5 = pixarr[4]; + p6 = pixarr[5]; + p7 = pixarr[6]; + p8 = pixarr[7]; + p9 = pixarr[8]; + while (n-- > 0) { + for (int i = 0; i < 9; ++i) { + int tone = p1->getTone(); + int paint = p1->getPaint(); + int ink = p1->getInk(); + if (tone == TPixelCM32::getMaxTone()) + val[i] = paints[paint]; + else if (tone == 0) + val[i] = inks[ink]; + else + val[i] = + blend(inks[ink], paints[paint], tone, TPixelCM32::getMaxTone()); + } + + pixout->r = (typename PIXOUT::Channel)( + (val[1].r * w1 + val[2].r * w2 + val[3].r * w3 + val[4].r * w4 + + val[5].r * w5 + val[6].r * w6 + val[7].r * w7 + val[8].r * w8 + + val[9].r * w9 + (1 << 15)) >> + 16); + pixout->g = (typename PIXOUT::Channel)( + (val[1].g * w1 + val[2].g * w2 + val[3].g * w3 + val[4].g * w4 + + val[5].g * w5 + val[6].g * w6 + val[7].g * w7 + val[8].g * w8 + + val[9].g * w9 + (1 << 15)) >> + 16); + pixout->b = (typename PIXOUT::Channel)( + (val[1].b * w1 + val[2].b * w2 + val[3].b * w3 + val[4].b * w4 + + val[5].b * w5 + val[6].b * w6 + val[7].b * w7 + val[8].b * w8 + + val[9].b * w9 + (1 << 15)) >> + 16); + pixout->m = (typename PIXOUT::Channel)( + (val[1].m * w1 + val[2].m * w2 + val[3].m * w3 + val[4].m * w4 + + val[5].m * w5 + val[6].m * w6 + val[7].m * w7 + val[8].m * w8 + + val[9].m * w9 + (1 << 15)) >> + 16); + p1++; + p2++; + p3++; + p4++; + p5++; + p6++; + p7++; + p8++; + p9++; + pixout++; + } } //------------------------------------------------------------------------------ template -void doConvolve_row_i(PIXOUT *pixout, int n, - PIXIN *pixarr[], long w[], int pixn) -{ - long ar, ag, ab, am; - int i; - - int rightShift = 16 + ((int)sizeof(typename PIXIN::Channel) - (int)sizeof(typename PIXOUT::Channel)) * 8; - - while (n-- > 0) { - ar = ag = ab = am = 0; - for (i = 0; i < pixn; i++) { - ar += pixarr[i]->r * w[i]; - ag += pixarr[i]->g * w[i]; - ab += pixarr[i]->b * w[i]; - am += pixarr[i]->m * w[i]; - pixarr[i]++; - } - pixout->r = (typename PIXOUT::Channel)((ar + (1 << 15)) >> rightShift); - pixout->g = (typename PIXOUT::Channel)((ag + (1 << 15)) >> rightShift); - pixout->b = (typename PIXOUT::Channel)((ab + (1 << 15)) >> rightShift); - pixout->m = (typename PIXOUT::Channel)((am + (1 << 15)) >> rightShift); - - pixout++; - } +void doConvolve_row_i(PIXOUT *pixout, int n, PIXIN *pixarr[], long w[], + int pixn) { + long ar, ag, ab, am; + int i; + + int rightShift = 16 + + ((int)sizeof(typename PIXIN::Channel) - + (int)sizeof(typename PIXOUT::Channel)) * + 8; + + while (n-- > 0) { + ar = ag = ab = am = 0; + for (i = 0; i < pixn; i++) { + ar += pixarr[i]->r * w[i]; + ag += pixarr[i]->g * w[i]; + ab += pixarr[i]->b * w[i]; + am += pixarr[i]->m * w[i]; + pixarr[i]++; + } + pixout->r = (typename PIXOUT::Channel)((ar + (1 << 15)) >> rightShift); + pixout->g = (typename PIXOUT::Channel)((ag + (1 << 15)) >> rightShift); + pixout->b = (typename PIXOUT::Channel)((ab + (1 << 15)) >> rightShift); + pixout->m = (typename PIXOUT::Channel)((am + (1 << 15)) >> rightShift); + + pixout++; + } } //------------------------------------------------------------------------------ template -void doConvolve_cm32_row_i(PIXOUT *pixout, int n, - TPixelCM32 *pixarr[], long w[], int pixn, - const std::vector &paints, - const std::vector &inks) -{ - long ar, ag, ab, am; - int i; - - while (n-- > 0) { - ar = ag = ab = am = 0; - for (i = 0; i < pixn; i++) { - TPixel32 val; - int tone = pixarr[i]->getTone(); - int paint = pixarr[i]->getPaint(); - int ink = pixarr[i]->getInk(); - if (tone == TPixelCM32::getMaxTone()) - val = paints[paint]; - else if (tone == 0) - val = inks[ink]; - else - val = blend(inks[ink], paints[paint], tone, TPixelCM32::getMaxTone()); - - ar += val.r * w[i]; - ag += val.g * w[i]; - ab += val.b * w[i]; - am += val.m * w[i]; - pixarr[i]++; - } - pixout->r = (typename PIXOUT::Channel)((ar + (1 << 15)) >> 16); - pixout->g = (typename PIXOUT::Channel)((ag + (1 << 15)) >> 16); - pixout->b = (typename PIXOUT::Channel)((ab + (1 << 15)) >> 16); - pixout->m = (typename PIXOUT::Channel)((am + (1 << 15)) >> 16); - pixout++; - } +void doConvolve_cm32_row_i(PIXOUT *pixout, int n, TPixelCM32 *pixarr[], + long w[], int pixn, + const std::vector &paints, + const std::vector &inks) { + long ar, ag, ab, am; + int i; + + while (n-- > 0) { + ar = ag = ab = am = 0; + for (i = 0; i < pixn; i++) { + TPixel32 val; + int tone = pixarr[i]->getTone(); + int paint = pixarr[i]->getPaint(); + int ink = pixarr[i]->getInk(); + if (tone == TPixelCM32::getMaxTone()) + val = paints[paint]; + else if (tone == 0) + val = inks[ink]; + else + val = blend(inks[ink], paints[paint], tone, TPixelCM32::getMaxTone()); + + ar += val.r * w[i]; + ag += val.g * w[i]; + ab += val.b * w[i]; + am += val.m * w[i]; + pixarr[i]++; + } + pixout->r = (typename PIXOUT::Channel)((ar + (1 << 15)) >> 16); + pixout->g = (typename PIXOUT::Channel)((ag + (1 << 15)) >> 16); + pixout->b = (typename PIXOUT::Channel)((ab + (1 << 15)) >> 16); + pixout->m = (typename PIXOUT::Channel)((am + (1 << 15)) >> 16); + pixout++; + } } //------------------------------------------------------------------------------ template -void doConvolve_3_i(TRasterPT rout, - TRasterPT rin, - int dx, int dy, - double conv[]) -{ - PIXIN *bufferin; - PIXOUT *bufferout; - PIXIN *pixin; - PIXOUT *pixout; - - PIXIN *pixarr[9]; - long w[9]; - int pixn; - int wrapin, wrapout; - int x, y, n; - int x1, y1, x2, y2; - int fx1, fy1, fx2, fy2, fx, fy; - - rout->clear(); - - wrapin = rin->getWrap(); - wrapout = rout->getWrap(); - - /* calcolo l'area di output interessata */ - x1 = std::max(0, -dx - 1); - y1 = std::max(0, -dy - 1); - x2 = std::min(rout->getLx() - 1, -dx + rin->getLx()); - y2 = std::min(rout->getLy() - 1, -dy + rin->getLy()); - - rin->lock(); - rout->lock(); - bufferin = rin->pixels(); - bufferout = rout->pixels(); - - for (y = y1; y <= y2; y++) { - fy1 = std::max(-1, -dy - y); - fy2 = std::min(1, -dy + rin->getLy() - 1 - y); - if (fy1 > fy2) - continue; - x = x1; - pixout = bufferout + wrapout * y + x; - pixin = bufferin + wrapin * (y + dy) + (x + dx); - - while (x <= x2) { - fx1 = std::max(-1, -dx - x); - fx2 = std::min(1, -dx + rin->getLx() - 1 - x); - if (x > -dx && x < -dx + rin->getLx() - 1) - n = std::min(-dx + rin->getLx() - 1 - x, x2 - x + 1); - else - n = 1; - if (n < 1) - break; - pixn = 0; - for (fy = fy1; fy <= fy2; fy++) - for (fx = fx1; fx <= fx2; fx++) { - pixarr[pixn] = pixin + fy * wrapin + fx; - w[pixn] = (long)(conv[(fy + 1) * 3 + fx + 1] * (1 << 16)); - pixn++; - } - if (pixn == 9) - doConvolve_row_9_i(pixout, n, pixarr, w); - else - doConvolve_row_i(pixout, n, pixarr, w, pixn); - x += n; - pixin += n; - pixout += n; - } - } - rin->unlock(); - rout->unlock(); +void doConvolve_3_i(TRasterPT rout, TRasterPT rin, int dx, + int dy, double conv[]) { + PIXIN *bufferin; + PIXOUT *bufferout; + PIXIN *pixin; + PIXOUT *pixout; + + PIXIN *pixarr[9]; + long w[9]; + int pixn; + int wrapin, wrapout; + int x, y, n; + int x1, y1, x2, y2; + int fx1, fy1, fx2, fy2, fx, fy; + + rout->clear(); + + wrapin = rin->getWrap(); + wrapout = rout->getWrap(); + + /* calcolo l'area di output interessata */ + x1 = std::max(0, -dx - 1); + y1 = std::max(0, -dy - 1); + x2 = std::min(rout->getLx() - 1, -dx + rin->getLx()); + y2 = std::min(rout->getLy() - 1, -dy + rin->getLy()); + + rin->lock(); + rout->lock(); + bufferin = rin->pixels(); + bufferout = rout->pixels(); + + for (y = y1; y <= y2; y++) { + fy1 = std::max(-1, -dy - y); + fy2 = std::min(1, -dy + rin->getLy() - 1 - y); + if (fy1 > fy2) continue; + x = x1; + pixout = bufferout + wrapout * y + x; + pixin = bufferin + wrapin * (y + dy) + (x + dx); + + while (x <= x2) { + fx1 = std::max(-1, -dx - x); + fx2 = std::min(1, -dx + rin->getLx() - 1 - x); + if (x > -dx && x < -dx + rin->getLx() - 1) + n = std::min(-dx + rin->getLx() - 1 - x, x2 - x + 1); + else + n = 1; + if (n < 1) break; + pixn = 0; + for (fy = fy1; fy <= fy2; fy++) + for (fx = fx1; fx <= fx2; fx++) { + pixarr[pixn] = pixin + fy * wrapin + fx; + w[pixn] = (long)(conv[(fy + 1) * 3 + fx + 1] * (1 << 16)); + pixn++; + } + if (pixn == 9) + doConvolve_row_9_i(pixout, n, pixarr, w); + else + doConvolve_row_i(pixout, n, pixarr, w, pixn); + x += n; + pixin += n; + pixout += n; + } + } + rin->unlock(); + rout->unlock(); } //------------------------------------------------------------------------------ template -void doConvolve_i(TRasterPT rout, - TRasterPT rin, - int dx, int dy, - double conv[], int radius) -{ - PIXIN *bufferin; - PIXOUT *bufferout; - PIXIN *pixin; - PIXOUT *pixout; - - int radiusSquare = sq(radius); - std::unique_ptr pixarr(new PIXIN *[radiusSquare]); - std::unique_ptr w(new long[radiusSquare]); - int pixn; - int wrapin, wrapout; - int x, y, n; - int x1, y1, x2, y2; - int fx1, fy1, fx2, fy2, fx, fy; - int radius1 = radius / 2; - int radius0 = radius1 - radius + 1; - - rout->clear(); - - wrapin = rin->getWrap(); - wrapout = rout->getWrap(); - - /* calcolo l'area di output interessata */ - x1 = std::max(0, -dx - 1); - y1 = std::max(0, -dy - 1); - x2 = std::min(rout->getLx() - 1, -dx + rin->getLx()); - y2 = std::min(rout->getLy() - 1, -dy + rin->getLy()); - - rin->lock(); - rout->lock(); - bufferin = rin->pixels(); - bufferout = rout->pixels(); - - for (y = y1; y <= y2; y++) { - fy1 = std::max(radius0, -dy - y); - fy2 = std::min(radius1, -dy - y + rin->getLy() - 1); - if (fy1 > fy2) - continue; - x = x1; - pixout = bufferout + wrapout * y + x; - pixin = bufferin + wrapin * (y + dy) + (x + dx); - - while (x <= x2) { - fx1 = std::max(radius0, -dx - x); - fx2 = std::min(radius1, -dx - x + rin->getLx() - 1); - if (x > -dx && x < -dx + rin->getLx() - 1) - n = std::min(-dx + rin->getLx() - 1 - x, x2 - x + 1); - else - n = 1; - if (n < 1) - break; - pixn = 0; - for (fy = fy1; fy <= fy2; fy++) - for (fx = fx1; fx <= fx2; fx++) { - pixarr[pixn] = pixin + fy * wrapin + fx; - w[pixn] = (long)(conv[(fy - radius0) * radius + fx - radius0] * (1 << 16)); - pixn++; - } - - doConvolve_row_i(pixout, n, pixarr.get(), w.get(), pixn); - - x += n; - pixin += n; - pixout += n; - } - } - - rin->unlock(); - rout->unlock(); +void doConvolve_i(TRasterPT rout, TRasterPT rin, int dx, int dy, + double conv[], int radius) { + PIXIN *bufferin; + PIXOUT *bufferout; + PIXIN *pixin; + PIXOUT *pixout; + + int radiusSquare = sq(radius); + std::unique_ptr pixarr(new PIXIN *[radiusSquare]); + std::unique_ptr w(new long[radiusSquare]); + int pixn; + int wrapin, wrapout; + int x, y, n; + int x1, y1, x2, y2; + int fx1, fy1, fx2, fy2, fx, fy; + int radius1 = radius / 2; + int radius0 = radius1 - radius + 1; + + rout->clear(); + + wrapin = rin->getWrap(); + wrapout = rout->getWrap(); + + /* calcolo l'area di output interessata */ + x1 = std::max(0, -dx - 1); + y1 = std::max(0, -dy - 1); + x2 = std::min(rout->getLx() - 1, -dx + rin->getLx()); + y2 = std::min(rout->getLy() - 1, -dy + rin->getLy()); + + rin->lock(); + rout->lock(); + bufferin = rin->pixels(); + bufferout = rout->pixels(); + + for (y = y1; y <= y2; y++) { + fy1 = std::max(radius0, -dy - y); + fy2 = std::min(radius1, -dy - y + rin->getLy() - 1); + if (fy1 > fy2) continue; + x = x1; + pixout = bufferout + wrapout * y + x; + pixin = bufferin + wrapin * (y + dy) + (x + dx); + + while (x <= x2) { + fx1 = std::max(radius0, -dx - x); + fx2 = std::min(radius1, -dx - x + rin->getLx() - 1); + if (x > -dx && x < -dx + rin->getLx() - 1) + n = std::min(-dx + rin->getLx() - 1 - x, x2 - x + 1); + else + n = 1; + if (n < 1) break; + pixn = 0; + for (fy = fy1; fy <= fy2; fy++) + for (fx = fx1; fx <= fx2; fx++) { + pixarr[pixn] = pixin + fy * wrapin + fx; + w[pixn] = + (long)(conv[(fy - radius0) * radius + fx - radius0] * (1 << 16)); + pixn++; + } + + doConvolve_row_i(pixout, n, pixarr.get(), w.get(), pixn); + + x += n; + pixin += n; + pixout += n; + } + } + + rin->unlock(); + rout->unlock(); } //------------------------------------------------------------------------------ template -void doConvolve_cm32_3_i(TRasterPT rout, - TRasterCM32P rin, - const TPaletteP &palette, - int dx, int dy, - double conv[]) -{ - TPixelCM32 *pixin; - PIXOUT *pixout; - TPixelCM32 *pixarr[9]; - long w[9]; - int pixn; - int wrapin, wrapout; - int x, y, n; - int x1, y1, x2, y2; - int fx1, fy1, fx2, fy2, fx, fy; - - rout->clear(); - - wrapin = rin->getWrap(); - wrapout = rout->getWrap(); - - /* calcolo l'area di output interessata */ - x1 = std::max(0, -dx - 1); - y1 = std::max(0, -dy - 1); - x2 = std::min(rout->getLx() - 1, -dx + rin->getLx()); - y2 = std::min(rout->getLy() - 1, -dy + rin->getLy()); - - int colorCount = palette->getStyleCount(); - colorCount = std::max({colorCount, TPixelCM32::getMaxInk(), TPixelCM32::getMaxPaint()}); - - std::vector paints(colorCount); - std::vector inks(colorCount); - - rin->lock(); - rout->lock(); - TPixelCM32 *bufferin = rin->pixels(); - PIXOUT *bufferout = rout->pixels(); - - for (int i = 0; i < palette->getStyleCount(); i++) - paints[i] = inks[i] = palette->getStyle(i)->getAverageColor(); - - for (y = y1; y <= y2; y++) { - fy1 = std::max(-1, -dy - y); - fy2 = std::min(1, -dy + rin->getLy() - 1 - y); - if (fy1 > fy2) - continue; - x = x1; - pixout = bufferout + wrapout * y + x; - pixin = bufferin + wrapin * (y + dy) + (x + dx); - - while (x <= x2) { - fx1 = std::max(-1, -dx - x); - fx2 = std::min(1, -dx + rin->getLx() - 1 - x); - if (x > -dx && x < -dx + rin->getLx() - 1) - n = std::min(-dx + rin->getLx() - 1 - x, x2 - x + 1); - else - n = 1; - if (n < 1) - break; - pixn = 0; - for (fy = fy1; fy <= fy2; fy++) - for (fx = fx1; fx <= fx2; fx++) { - pixarr[pixn] = pixin + fy * wrapin + fx; - w[pixn] = (long)(conv[(fy + 1) * 3 + fx + 1] * (1 << 16)); - pixn++; - } - if (pixn == 9) - doConvolve_cm32_row_9_i(pixout, n, pixarr, w, paints, inks); - else - doConvolve_cm32_row_i(pixout, n, pixarr, w, pixn, paints, inks); - x += n; - pixin += n; - pixout += n; - } - } - rin->unlock(); - rout->unlock(); +void doConvolve_cm32_3_i(TRasterPT rout, TRasterCM32P rin, + const TPaletteP &palette, int dx, int dy, + double conv[]) { + TPixelCM32 *pixin; + PIXOUT *pixout; + TPixelCM32 *pixarr[9]; + long w[9]; + int pixn; + int wrapin, wrapout; + int x, y, n; + int x1, y1, x2, y2; + int fx1, fy1, fx2, fy2, fx, fy; + + rout->clear(); + + wrapin = rin->getWrap(); + wrapout = rout->getWrap(); + + /* calcolo l'area di output interessata */ + x1 = std::max(0, -dx - 1); + y1 = std::max(0, -dy - 1); + x2 = std::min(rout->getLx() - 1, -dx + rin->getLx()); + y2 = std::min(rout->getLy() - 1, -dy + rin->getLy()); + + int colorCount = palette->getStyleCount(); + colorCount = std::max( + {colorCount, TPixelCM32::getMaxInk(), TPixelCM32::getMaxPaint()}); + + std::vector paints(colorCount); + std::vector inks(colorCount); + + rin->lock(); + rout->lock(); + TPixelCM32 *bufferin = rin->pixels(); + PIXOUT *bufferout = rout->pixels(); + + for (int i = 0; i < palette->getStyleCount(); i++) + paints[i] = inks[i] = palette->getStyle(i)->getAverageColor(); + + for (y = y1; y <= y2; y++) { + fy1 = std::max(-1, -dy - y); + fy2 = std::min(1, -dy + rin->getLy() - 1 - y); + if (fy1 > fy2) continue; + x = x1; + pixout = bufferout + wrapout * y + x; + pixin = bufferin + wrapin * (y + dy) + (x + dx); + + while (x <= x2) { + fx1 = std::max(-1, -dx - x); + fx2 = std::min(1, -dx + rin->getLx() - 1 - x); + if (x > -dx && x < -dx + rin->getLx() - 1) + n = std::min(-dx + rin->getLx() - 1 - x, x2 - x + 1); + else + n = 1; + if (n < 1) break; + pixn = 0; + for (fy = fy1; fy <= fy2; fy++) + for (fx = fx1; fx <= fx2; fx++) { + pixarr[pixn] = pixin + fy * wrapin + fx; + w[pixn] = (long)(conv[(fy + 1) * 3 + fx + 1] * (1 << 16)); + pixn++; + } + if (pixn == 9) + doConvolve_cm32_row_9_i(pixout, n, pixarr, w, paints, inks); + else + doConvolve_cm32_row_i(pixout, n, pixarr, w, pixn, paints, inks); + x += n; + pixin += n; + pixout += n; + } + } + rin->unlock(); + rout->unlock(); } //------------------------------------------------------------------------------ template -void doConvolve_cm32_i(TRasterPT rout, - TRasterCM32P rin, - const TPaletteP &palette, - int dx, int dy, - double conv[], int radius) -{ - TPixelCM32 *pixin; - PIXOUT *pixout; - int radiusSquare = sq(radius); - std::unique_ptr pixarr(new TPixelCM32*[radiusSquare]); - std::unique_ptr w(new long[radiusSquare]); - int pixn; - int wrapin, wrapout; - int x, y, n; - int x1, y1, x2, y2; - int fx1, fy1, fx2, fy2, fx, fy; - int radius1 = radius / 2; - int radius0 = radius1 - radius + 1; - - rout->clear(); - - wrapin = rin->getWrap(); - wrapout = rout->getWrap(); - - /* calcolo l'area di output interessata */ - x1 = std::max(0, -dx - 1); - y1 = std::max(0, -dy - 1); - x2 = std::min(rout->getLx() - 1, -dx + rin->getLx()); - y2 = std::min(rout->getLy() - 1, -dy + rin->getLy()); - - int colorCount = palette->getStyleCount(); - colorCount = std::max({colorCount, TPixelCM32::getMaxInk(), TPixelCM32::getMaxPaint()}); - - std::vector paints(colorCount); - std::vector inks(colorCount); - - rin->lock(); - rout->lock(); - TPixelCM32 *bufferin = rin->pixels(); - PIXOUT *bufferout = rout->pixels(); - - for (int i = 0; i < palette->getStyleCount(); i++) - paints[i] = inks[i] = palette->getStyle(i)->getAverageColor(); - - for (y = y1; y <= y2; y++) { - fy1 = std::max(radius0, -dy - y); - fy2 = std::min(radius1, -dy + rin->getLy() - 1 - y); - if (fy1 > fy2) - continue; - x = x1; - pixout = bufferout + wrapout * y + x; - pixin = bufferin + wrapin * (y + dy) + (x + dx); - - while (x <= x2) { - fx1 = std::max(radius0, -dx - x); - fx2 = std::min(radius1, -dx + rin->getLx() - 1 - x); - if (x > -dx && x < -dx + rin->getLx() - 1) - n = std::min(-dx + rin->getLx() - 1 - x, x2 - x + 1); - else - n = 1; - if (n < 1) - break; - pixn = 0; - for (fy = fy1; fy <= fy2; fy++) - for (fx = fx1; fx <= fx2; fx++) { - pixarr[pixn] = pixin + fy * wrapin + fx; - w[pixn] = (long)(conv[(fy - radius0) * radius + fx - radius0] * (1 << 16)); - pixn++; - } - - doConvolve_cm32_row_i(pixout, n, pixarr.get(), w.get(), pixn, paints, inks); - - x += n; - pixin += n; - pixout += n; - } - } - - rin->unlock(); - rout->unlock(); +void doConvolve_cm32_i(TRasterPT rout, TRasterCM32P rin, + const TPaletteP &palette, int dx, int dy, double conv[], + int radius) { + TPixelCM32 *pixin; + PIXOUT *pixout; + int radiusSquare = sq(radius); + std::unique_ptr pixarr(new TPixelCM32 *[radiusSquare]); + std::unique_ptr w(new long[radiusSquare]); + int pixn; + int wrapin, wrapout; + int x, y, n; + int x1, y1, x2, y2; + int fx1, fy1, fx2, fy2, fx, fy; + int radius1 = radius / 2; + int radius0 = radius1 - radius + 1; + + rout->clear(); + + wrapin = rin->getWrap(); + wrapout = rout->getWrap(); + + /* calcolo l'area di output interessata */ + x1 = std::max(0, -dx - 1); + y1 = std::max(0, -dy - 1); + x2 = std::min(rout->getLx() - 1, -dx + rin->getLx()); + y2 = std::min(rout->getLy() - 1, -dy + rin->getLy()); + + int colorCount = palette->getStyleCount(); + colorCount = std::max( + {colorCount, TPixelCM32::getMaxInk(), TPixelCM32::getMaxPaint()}); + + std::vector paints(colorCount); + std::vector inks(colorCount); + + rin->lock(); + rout->lock(); + TPixelCM32 *bufferin = rin->pixels(); + PIXOUT *bufferout = rout->pixels(); + + for (int i = 0; i < palette->getStyleCount(); i++) + paints[i] = inks[i] = palette->getStyle(i)->getAverageColor(); + + for (y = y1; y <= y2; y++) { + fy1 = std::max(radius0, -dy - y); + fy2 = std::min(radius1, -dy + rin->getLy() - 1 - y); + if (fy1 > fy2) continue; + x = x1; + pixout = bufferout + wrapout * y + x; + pixin = bufferin + wrapin * (y + dy) + (x + dx); + + while (x <= x2) { + fx1 = std::max(radius0, -dx - x); + fx2 = std::min(radius1, -dx + rin->getLx() - 1 - x); + if (x > -dx && x < -dx + rin->getLx() - 1) + n = std::min(-dx + rin->getLx() - 1 - x, x2 - x + 1); + else + n = 1; + if (n < 1) break; + pixn = 0; + for (fy = fy1; fy <= fy2; fy++) + for (fx = fx1; fx <= fx2; fx++) { + pixarr[pixn] = pixin + fy * wrapin + fx; + w[pixn] = + (long)(conv[(fy - radius0) * radius + fx - radius0] * (1 << 16)); + pixn++; + } + + doConvolve_cm32_row_i(pixout, n, pixarr.get(), w.get(), pixn, + paints, inks); + + x += n; + pixin += n; + pixout += n; + } + } + + rin->unlock(); + rout->unlock(); } -} // anonymous namespace +} // anonymous namespace //------------------------------------------------------------------------------ -void TRop::convolve_3_i(TRasterP rout, TRasterP rin, int dx, int dy, double conv[]) -{ - TRaster32P rin32 = rin; - - if (rin32) { - TRaster32P rout32 = rout; - if (rout32) { - doConvolve_3_i(rout32, rin32, dx, dy, conv); - return; - } - - TRaster64P rout64 = rout; - if (rout64) { - doConvolve_3_i(rout64, rin32, dx, dy, conv); - return; - } - } else { - TRaster64P rin64 = rin; - if (rin64) { - TRaster32P rout32 = rout; - if (rout32) { - doConvolve_3_i(rout32, rin64, dx, dy, conv); - return; - } - - TRaster64P rout64 = rout; - if (rout64) { - doConvolve_3_i(rout64, rin64, dx, dy, conv); - return; - } - } - } - - throw TRopException("TRop::convolve_3_i: unsupported pixel type"); +void TRop::convolve_3_i(TRasterP rout, TRasterP rin, int dx, int dy, + double conv[]) { + TRaster32P rin32 = rin; + + if (rin32) { + TRaster32P rout32 = rout; + if (rout32) { + doConvolve_3_i(rout32, rin32, dx, dy, conv); + return; + } + + TRaster64P rout64 = rout; + if (rout64) { + doConvolve_3_i(rout64, rin32, dx, dy, conv); + return; + } + } else { + TRaster64P rin64 = rin; + if (rin64) { + TRaster32P rout32 = rout; + if (rout32) { + doConvolve_3_i(rout32, rin64, dx, dy, conv); + return; + } + + TRaster64P rout64 = rout; + if (rout64) { + doConvolve_3_i(rout64, rin64, dx, dy, conv); + return; + } + } + } + + throw TRopException("TRop::convolve_3_i: unsupported pixel type"); } //------------------------------------------------------------------------------ -void TRop::convolve_3_i(TRasterP rout, TRasterCM32P rin, const TPaletteP &palette, - int dx, int dy, double conv[]) -{ - TRaster32P rout32 = rout; +void TRop::convolve_3_i(TRasterP rout, TRasterCM32P rin, + const TPaletteP &palette, int dx, int dy, + double conv[]) { + TRaster32P rout32 = rout; - if (rout32) { - doConvolve_cm32_3_i(rout32, rin, palette, dx, dy, conv); - return; - } + if (rout32) { + doConvolve_cm32_3_i(rout32, rin, palette, dx, dy, conv); + return; + } - TRaster64P rout64 = rout; - if (rout64) { - doConvolve_cm32_3_i(rout64, rin, palette, dx, dy, conv); - return; - } + TRaster64P rout64 = rout; + if (rout64) { + doConvolve_cm32_3_i(rout64, rin, palette, dx, dy, conv); + return; + } - throw TRopException("TRop::convolve_3_i: unsupported pixel type"); + throw TRopException("TRop::convolve_3_i: unsupported pixel type"); } //------------------------------------------------------------------------------ -void TRop::convolve_i(TRasterP rout, TRasterP rin, int dx, int dy, double conv[], int radius) -{ - TRaster32P rin32 = rin; - - if (rin32) { - TRaster32P rout32 = rout; - if (rout32) { - doConvolve_i(rout32, rin32, dx, dy, conv, radius); - return; - } - - TRaster64P rout64 = rout; - if (rout64) { - doConvolve_i(rout64, rin32, dx, dy, conv, radius); - return; - } - } else { - TRaster64P rin64 = rin; - if (rin64) { - TRaster32P rout32 = rout; - if (rout32) { - doConvolve_i(rout32, rin64, dx, dy, conv, radius); - return; - } - - TRaster64P rout64 = rout; - if (rout64) { - doConvolve_i(rout64, rin64, dx, dy, conv, radius); - return; - } - } - } - - throw TRopException("TRop::convolve_i: unsupported pixel type"); +void TRop::convolve_i(TRasterP rout, TRasterP rin, int dx, int dy, + double conv[], int radius) { + TRaster32P rin32 = rin; + + if (rin32) { + TRaster32P rout32 = rout; + if (rout32) { + doConvolve_i(rout32, rin32, dx, dy, conv, radius); + return; + } + + TRaster64P rout64 = rout; + if (rout64) { + doConvolve_i(rout64, rin32, dx, dy, conv, radius); + return; + } + } else { + TRaster64P rin64 = rin; + if (rin64) { + TRaster32P rout32 = rout; + if (rout32) { + doConvolve_i(rout32, rin64, dx, dy, conv, radius); + return; + } + + TRaster64P rout64 = rout; + if (rout64) { + doConvolve_i(rout64, rin64, dx, dy, conv, radius); + return; + } + } + } + + throw TRopException("TRop::convolve_i: unsupported pixel type"); } //------------------------------------------------------------------------------ void TRop::convolve_i(TRasterP rout, TRasterCM32P rin, const TPaletteP &palette, - int dx, int dy, double conv[], int radius) -{ - TRaster32P rout32 = rout; - - if (rout32) { - doConvolve_cm32_i(rout32, rin, palette, dx, dy, conv, radius); - return; - } - - TRaster64P rout64 = rout; - if (rout64) { - doConvolve_cm32_i(rout64, rin, palette, dx, dy, conv, radius); - return; - } - - throw TRopException("TRop::convolve_i: unsupported pixel type"); + int dx, int dy, double conv[], int radius) { + TRaster32P rout32 = rout; + + if (rout32) { + doConvolve_cm32_i(rout32, rin, palette, dx, dy, conv, radius); + return; + } + + TRaster64P rout64 = rout; + if (rout64) { + doConvolve_cm32_i(rout64, rin, palette, dx, dy, conv, radius); + return; + } + + throw TRopException("TRop::convolve_i: unsupported pixel type"); } diff --git a/toonz/sources/common/trop/tdespeckle.cpp b/toonz/sources/common/trop/tdespeckle.cpp index 6349665..c9c6cb6 100644 --- a/toonz/sources/common/trop/tdespeckle.cpp +++ b/toonz/sources/common/trop/tdespeckle.cpp @@ -24,98 +24,117 @@ Explanation - Despeckling is a noise-removal procedure which aims at eliminating small blots of color + Despeckling is a noise-removal procedure which aims at eliminating small blots +of color from an image. - We will assume that speckles are recognized with uniform color (which means - image + We will assume that speckles are recognized with uniform color (which means - +image discretization should be externally performed). - We will currently assume that the despeckling procedure works only on the ink or paint plane of a + We will currently assume that the despeckling procedure works only on the ink +or paint plane of a TRasterCM32 instance, not both (should be extended in the future). - The image is traversed to isolate regions with the same color and, if their area is + The image is traversed to isolate regions with the same color and, if their +area is below the specified threshold, they get removed or changed of color. - Color change looks at the area's neighbouring pixels for the most used color to use for - replacement. If NO neighbouring color can be found, the area is made transparent. + Color change looks at the area's neighbouring pixels for the most used color +to use for + replacement. If NO neighbouring color can be found, the area is made +transparent. ==============================================================================================*/ using namespace TRop::borders; -namespace -{ +namespace { //************************************************************************ // Pixel Selectors //************************************************************************ -class InkSelectorCM32 -{ +class InkSelectorCM32 { public: - typedef TPixelCM32 pixel_type; - typedef TUINT32 value_type; + typedef TPixelCM32 pixel_type; + typedef TUINT32 value_type; public: - InkSelectorCM32() {} + InkSelectorCM32() {} - value_type transparent() const { return 0; } - bool transparent(const pixel_type &pix) const { return value(pix) == 0; } + value_type transparent() const { return 0; } + bool transparent(const pixel_type &pix) const { return value(pix) == 0; } - value_type value(const pixel_type &pix) const { return pix.getInk(); } - bool equal(const pixel_type &a, const pixel_type &b) const { return value(a) == value(b); } + value_type value(const pixel_type &pix) const { return pix.getInk(); } + bool equal(const pixel_type &a, const pixel_type &b) const { + return value(a) == value(b); + } - bool skip(const value_type &prevLeftValue, const value_type &leftValue) const { return true; } + bool skip(const value_type &prevLeftValue, + const value_type &leftValue) const { + return true; + } }; //------------------------------------------------------------------------------------------ template -class InkSelectorRGBM -{ - bool m_transparentIsWhite; +class InkSelectorRGBM { + bool m_transparentIsWhite; public: - typedef PIXEL pixel_type; - typedef CHANNEL value_type; + typedef PIXEL pixel_type; + typedef CHANNEL value_type; public: - InkSelectorRGBM(bool transparentIsWhite) : m_transparentIsWhite(transparentIsWhite) {} - - value_type transparent() const { return 0; } - bool transparent(const pixel_type &pix) const { return value(pix) == 0; } - - value_type value(const pixel_type &pix) const - { - if (m_transparentIsWhite) - return (pix == PIXEL::White) ? 0 : 1; - else - return (pix.m == 0) ? 0 : 1; - } - bool equal(const pixel_type &a, const pixel_type &b) const { return value(a) == value(b); } - - bool skip(const value_type &prevLeftValue, const value_type &leftValue) const { return true; } + InkSelectorRGBM(bool transparentIsWhite) + : m_transparentIsWhite(transparentIsWhite) {} + + value_type transparent() const { return 0; } + bool transparent(const pixel_type &pix) const { return value(pix) == 0; } + + value_type value(const pixel_type &pix) const { + if (m_transparentIsWhite) + return (pix == PIXEL::White) ? 0 : 1; + else + return (pix.m == 0) ? 0 : 1; + } + bool equal(const pixel_type &a, const pixel_type &b) const { + return value(a) == value(b); + } + + bool skip(const value_type &prevLeftValue, + const value_type &leftValue) const { + return true; + } }; //------------------------------------------------------------------------------------------ template -class InkSelectorGR -{ +class InkSelectorGR { public: - typedef PIXEL pixel_type; - typedef CHANNEL value_type; + typedef PIXEL pixel_type; + typedef CHANNEL value_type; public: - InkSelectorGR() {} - - value_type transparent() const { return PIXEL::maxChannelValue; } - bool transparent(const pixel_type &pix) const { return value(pix) == 0; } - - value_type value(const pixel_type &pix) const { return (pix.value == PIXEL::maxChannelValue) ? 0 : 1; } - bool equal(const pixel_type &a, const pixel_type &b) const { return value(a) == value(b); } - - bool skip(const value_type &prevLeftValue, const value_type &leftValue) const { return true; } + InkSelectorGR() {} + + value_type transparent() const { return PIXEL::maxChannelValue; } + bool transparent(const pixel_type &pix) const { return value(pix) == 0; } + + value_type value(const pixel_type &pix) const { + return (pix.value == PIXEL::maxChannelValue) ? 0 : 1; + } + bool equal(const pixel_type &a, const pixel_type &b) const { + return value(a) == value(b); + } + + bool skip(const value_type &prevLeftValue, + const value_type &leftValue) const { + return true; + } }; //************************************************************************ @@ -123,32 +142,31 @@ public: //************************************************************************ struct Border { - std::vector m_points; - int m_x0, m_y0, m_x1, m_y1; - - Border() : m_x0((std::numeric_limits::max)()), m_y0(m_x0), m_x1(-m_x0), m_y1(m_x1) {} - - void addPoint(const TPoint &p) - { - //Update the region box - if (p.x < m_x0) - m_x0 = p.x; - if (p.x > m_x1) - m_x1 = p.x; - if (p.y < m_y0) - m_y0 = p.y; - if (p.y > m_y1) - m_y1 = p.y; - - //Add the vertex - m_points.push_back(p); - } - - void clear() - { - m_points.clear(); - m_x0 = (std::numeric_limits::max)(), m_y0 = m_x0, m_x1 = -m_x0, m_y1 = m_x1; - } + std::vector m_points; + int m_x0, m_y0, m_x1, m_y1; + + Border() + : m_x0((std::numeric_limits::max)()) + , m_y0(m_x0) + , m_x1(-m_x0) + , m_y1(m_x1) {} + + void addPoint(const TPoint &p) { + // Update the region box + if (p.x < m_x0) m_x0 = p.x; + if (p.x > m_x1) m_x1 = p.x; + if (p.y < m_y0) m_y0 = p.y; + if (p.y > m_y1) m_y1 = p.y; + + // Add the vertex + m_points.push_back(p); + } + + void clear() { + m_points.clear(); + m_x0 = (std::numeric_limits::max)(), m_y0 = m_x0, m_x1 = -m_x0, + m_y1 = m_x1; + } }; //************************************************************************ @@ -160,136 +178,121 @@ struct Border { //======================================================================== template -class BordersPainter -{ +class BordersPainter { public: - typedef Pix pixel_type; + typedef Pix pixel_type; protected: - TRasterPT m_ras; - RunsMapP m_runsMap; + TRasterPT m_ras; + RunsMapP m_runsMap; public: - BordersPainter(const TRasterPT &ras) : m_ras(ras) {} + BordersPainter(const TRasterPT &ras) : m_ras(ras) {} - const TRasterPT &ras() { return m_ras; } - RunsMapP &runsMap() { return m_runsMap; } + const TRasterPT &ras() { return m_ras; } + RunsMapP &runsMap() { return m_runsMap; } - void paintLine(int x, int y0, int y1) const; - void paintBorder(const Border &border) const; - void paintBorders(const std::deque &borders) const - { - size_t i, size = borders.size(); - for (i = 0; i < size; ++i) - paintBorder(*borders[i]); - } + void paintLine(int x, int y0, int y1) const; + void paintBorder(const Border &border) const; + void paintBorders(const std::deque &borders) const { + size_t i, size = borders.size(); + for (i = 0; i < size; ++i) paintBorder(*borders[i]); + } protected: - virtual void paintPixel(pixel_type *pix) const = 0; + virtual void paintPixel(pixel_type *pix) const = 0; }; //--------------------------------------------------------------------------------------------- template -void BordersPainter::paintBorder(const Border &border) const -{ - const std::vector &points = border.m_points; - - size_t i, size_1 = points.size() - 1; - for (i = 0; i < size_1; ++i) { - const TPoint &p = points[i]; - paintLine(p.x, p.y, points[i + 1].y); - } - paintLine(points[size_1].x, points[size_1].y, points[0].y); +void BordersPainter::paintBorder(const Border &border) const { + const std::vector &points = border.m_points; + + size_t i, size_1 = points.size() - 1; + for (i = 0; i < size_1; ++i) { + const TPoint &p = points[i]; + paintLine(p.x, p.y, points[i + 1].y); + } + paintLine(points[size_1].x, points[size_1].y, points[0].y); } //--------------------------------------------------------------------------------------------- template -void BordersPainter::paintLine(int x, int y0, int y1) const -{ - for (int j = y0; j < y1; ++j) { - TPixelGR8 *runPix = m_runsMap->pixels(j) + x; - int l, runLength = 0, hierarchy = 0; +void BordersPainter::paintLine(int x, int y0, int y1) const { + for (int j = y0; j < y1; ++j) { + TPixelGR8 *runPix = m_runsMap->pixels(j) + x; + int l, runLength = 0, hierarchy = 0; - do { - if (runPix->value & TRop::borders::_HIERARCHY_INCREASE) - ++hierarchy; + do { + if (runPix->value & TRop::borders::_HIERARCHY_INCREASE) ++hierarchy; - //Update vars - runLength += l = m_runsMap->runLength(runPix); - runPix += l; + // Update vars + runLength += l = m_runsMap->runLength(runPix); + runPix += l; - if ((runPix - 1)->value & TRop::borders::_HIERARCHY_DECREASE) - --hierarchy; - } while (hierarchy > 0); + if ((runPix - 1)->value & TRop::borders::_HIERARCHY_DECREASE) --hierarchy; + } while (hierarchy > 0); - pixel_type *pix = m_ras->pixels(j) + x, *pixEnd = pix + runLength; + pixel_type *pix = m_ras->pixels(j) + x, *pixEnd = pix + runLength; - for (; pix < pixEnd; ++pix) - paintPixel(pix); - } + for (; pix < pixEnd; ++pix) paintPixel(pix); + } } //======================================================================== // Despeckling Reader //======================================================================== -class DespecklingReader -{ +class DespecklingReader { protected: - std::deque m_borders; - Border m_border; + std::deque m_borders; + Border m_border; - int m_sizeTol; + int m_sizeTol; public: - DespecklingReader(int sizeTol) : m_sizeTol(sizeTol) {} - ~DespecklingReader(); - - int sizeTol() const { return m_sizeTol; } - bool isSpeckle(const Border &border) - { - return border.m_x1 - border.m_x0 <= m_sizeTol && - border.m_y1 - border.m_y0 <= m_sizeTol; - } - - void openContainer(const TPoint &pos); - void addElement(const TPoint &pos); - virtual void closeContainer(); - - const std::deque &borders() const { return m_borders; } - std::deque &borders() { return m_borders; } + DespecklingReader(int sizeTol) : m_sizeTol(sizeTol) {} + ~DespecklingReader(); + + int sizeTol() const { return m_sizeTol; } + bool isSpeckle(const Border &border) { + return border.m_x1 - border.m_x0 <= m_sizeTol && + border.m_y1 - border.m_y0 <= m_sizeTol; + } + + void openContainer(const TPoint &pos); + void addElement(const TPoint &pos); + virtual void closeContainer(); + + const std::deque &borders() const { return m_borders; } + std::deque &borders() { return m_borders; } }; //--------------------------------------------------------------------------------------------- -DespecklingReader::~DespecklingReader() -{ - std::for_each(m_borders.begin(), m_borders.end(), tcg::deleter()); +DespecklingReader::~DespecklingReader() { + std::for_each(m_borders.begin(), m_borders.end(), tcg::deleter()); } //--------------------------------------------------------------------------------------------- -void DespecklingReader::openContainer(const TPoint &pos) -{ - m_border.clear(); - m_border.addPoint(pos); +void DespecklingReader::openContainer(const TPoint &pos) { + m_border.clear(); + m_border.addPoint(pos); } //--------------------------------------------------------------------------------------------- -void DespecklingReader::addElement(const TPoint &pos) -{ - m_border.addPoint(pos); +void DespecklingReader::addElement(const TPoint &pos) { + m_border.addPoint(pos); } //--------------------------------------------------------------------------------------------- -void DespecklingReader::closeContainer() -{ - if (isSpeckle(m_border)) - m_borders.push_back(new Border(m_border)); +void DespecklingReader::closeContainer() { + if (isSpeckle(m_border)) m_borders.push_back(new Border(m_border)); } //************************************************************************ @@ -301,43 +304,47 @@ void DespecklingReader::closeContainer() //======================================================================== template -class ReplacePainter : public BordersPainter -{ - typename ReplacePainter::pixel_type m_color; +class ReplacePainter : public BordersPainter { + typename ReplacePainter::pixel_type m_color; public: - ReplacePainter(const TRasterPT &ras) - : BordersPainter(ras) {} - ReplacePainter(const TRasterPT &ras, const typename ReplacePainter::pixel_type &color) - : BordersPainter(ras), m_color(color) {} - - const typename ReplacePainter::pixel_type &color() const { return m_color; } - typename ReplacePainter::pixel_type &color() { return m_color; } - - void paintPixel(typename ReplacePainter::pixel_type *pix) const { *pix = m_color; } + ReplacePainter(const TRasterPT &ras) + : BordersPainter(ras) {} + ReplacePainter(const TRasterPT &ras, + const typename ReplacePainter::pixel_type &color) + : BordersPainter(ras), m_color(color) {} + + const typename ReplacePainter::pixel_type &color() const { return m_color; } + typename ReplacePainter::pixel_type &color() { return m_color; } + + void paintPixel(typename ReplacePainter::pixel_type *pix) const { + *pix = m_color; + } }; //--------------------------------------------------------------------------------------------- template <> -class ReplacePainter : public BordersPainter -{ - TUINT32 m_value; - TUINT32 m_keepMask; +class ReplacePainter : public BordersPainter { + TUINT32 m_value; + TUINT32 m_keepMask; public: - ReplacePainter(const TRasterPT &ras) - : BordersPainter(ras), m_value(0), m_keepMask(0) {} - ReplacePainter(const TRasterPT &ras, TUINT32 value, TUINT32 keepMask) - : BordersPainter(ras), m_value(value), m_keepMask(keepMask) {} + ReplacePainter(const TRasterPT &ras) + : BordersPainter(ras), m_value(0), m_keepMask(0) {} + ReplacePainter(const TRasterPT &ras, TUINT32 value, + TUINT32 keepMask) + : BordersPainter(ras), m_value(value), m_keepMask(keepMask) {} - const TUINT32 &value() const { return m_value; } - TUINT32 &value() { return m_value; } + const TUINT32 &value() const { return m_value; } + TUINT32 &value() { return m_value; } - const TUINT32 &keepMask() const { return m_keepMask; } - TUINT32 &keepMask() { return m_keepMask; } + const TUINT32 &keepMask() const { return m_keepMask; } + TUINT32 &keepMask() { return m_keepMask; } - void paintPixel(pixel_type *pix) const { *pix = TPixelCM32(m_value | (pix->getValue() & m_keepMask)); } + void paintPixel(pixel_type *pix) const { + *pix = TPixelCM32(m_value | (pix->getValue() & m_keepMask)); + } }; //======================================================================== @@ -345,146 +352,143 @@ public: //======================================================================== template -class IsolatedReader : public DespecklingReader -{ +class IsolatedReader : public DespecklingReader { public: - typedef typename PixelSelector::pixel_type pixel_type; - typedef typename PixelSelector::value_type value_type; + typedef typename PixelSelector::pixel_type pixel_type; + typedef typename PixelSelector::value_type value_type; private: - const PixelSelector &m_selector; - bool m_ok; + const PixelSelector &m_selector; + bool m_ok; public: - IsolatedReader(const PixelSelector &selector, int sizeTol); + IsolatedReader(const PixelSelector &selector, int sizeTol); - void openContainer(const RasterEdgeIterator &it); - void addElement(const RasterEdgeIterator &it); - void closeContainer(); + void openContainer(const RasterEdgeIterator &it); + void addElement(const RasterEdgeIterator &it); + void closeContainer(); }; //--------------------------------------------------------------------------------------------- template -IsolatedReader::IsolatedReader(const PixelSelector &selector, int sizeTol) - : DespecklingReader(sizeTol), m_selector(selector) -{ -} +IsolatedReader::IsolatedReader(const PixelSelector &selector, + int sizeTol) + : DespecklingReader(sizeTol), m_selector(selector) {} //--------------------------------------------------------------------------------------------- template -void IsolatedReader::openContainer(const RasterEdgeIterator &it) -{ - m_ok = (it.leftColor() == m_selector.transparent()); - if (!m_ok) - return; +void IsolatedReader::openContainer( + const RasterEdgeIterator &it) { + m_ok = (it.leftColor() == m_selector.transparent()); + if (!m_ok) return; - DespecklingReader::openContainer(it.pos()); + DespecklingReader::openContainer(it.pos()); } //--------------------------------------------------------------------------------------------- template -void IsolatedReader::addElement(const RasterEdgeIterator &it) -{ - if (!m_ok) - return; - m_ok = (it.leftColor() == m_selector.transparent()); - if (!m_ok) - return; - - DespecklingReader::addElement(it.pos()); +void IsolatedReader::addElement( + const RasterEdgeIterator &it) { + if (!m_ok) return; + m_ok = (it.leftColor() == m_selector.transparent()); + if (!m_ok) return; + + DespecklingReader::addElement(it.pos()); } //--------------------------------------------------------------------------------------------- template -void IsolatedReader::closeContainer() -{ - if (m_ok) - DespecklingReader::closeContainer(); +void IsolatedReader::closeContainer() { + if (m_ok) DespecklingReader::closeContainer(); } -} //namespace +} // namespace //********************************************************************************************************* // Despeckling Mains //********************************************************************************************************* /*! - Applies despeckling (paint or removal of small blots of uniform color) to the image. + Applies despeckling (paint or removal of small blots of uniform color) to the + image. */ template -void doDespeckleRGBM(const TRasterPT &ras, int sizeThreshold, bool transparentIsWhite) -{ - InkSelectorRGBM selector(transparentIsWhite); - IsolatedReader> reader(selector, sizeThreshold); - ReplacePainter painter(ras, transparentIsWhite ? PIXEL::White : PIXEL::Transparent); - - TRop::borders::readBorders(ras, selector, reader, &painter.runsMap()); - painter.paintBorders(reader.borders()); +void doDespeckleRGBM(const TRasterPT &ras, int sizeThreshold, + bool transparentIsWhite) { + InkSelectorRGBM selector(transparentIsWhite); + IsolatedReader> reader(selector, + sizeThreshold); + ReplacePainter painter( + ras, transparentIsWhite ? PIXEL::White : PIXEL::Transparent); + + TRop::borders::readBorders(ras, selector, reader, &painter.runsMap()); + painter.paintBorders(reader.borders()); } //---------------------------------------------------- template -void doDespeckleGR(const TRasterPT &ras, int sizeThreshold) -{ - InkSelectorGR selector; - IsolatedReader> reader(selector, sizeThreshold); - ReplacePainter painter(ras, PIXEL::maxChannelValue); - - TRop::borders::readBorders(ras, selector, reader, &painter.runsMap()); - painter.paintBorders(reader.borders()); +void doDespeckleGR(const TRasterPT &ras, int sizeThreshold) { + InkSelectorGR selector; + IsolatedReader> reader(selector, sizeThreshold); + ReplacePainter painter(ras, PIXEL::maxChannelValue); + + TRop::borders::readBorders(ras, selector, reader, &painter.runsMap()); + painter.paintBorders(reader.borders()); } //---------------------------------------------------- -void doDespeckleCM32(const TRasterPT &ras, int sizeThreshold, bool check) -{ - TRasterCM32P rasCM(ras); - rasCM->lock(); - - InkSelectorCM32 selector; - IsolatedReader reader(selector, sizeThreshold); - ReplacePainter painter(rasCM, check ? 0xffffff00 : 0x000000ff, 0); // 0xffffff00 is a special non-mapped full ink pixel - // 0x000000ff is a full transparent paint pixel - TRop::borders::readBorders(rasCM, selector, reader, &painter.runsMap()); - painter.paintBorders(reader.borders()); - - rasCM->unlock(); +void doDespeckleCM32(const TRasterPT &ras, int sizeThreshold, + bool check) { + TRasterCM32P rasCM(ras); + rasCM->lock(); + + InkSelectorCM32 selector; + IsolatedReader reader(selector, sizeThreshold); + ReplacePainter painter( + rasCM, check ? 0xffffff00 : 0x000000ff, + 0); // 0xffffff00 is a special non-mapped full ink pixel + // 0x000000ff is a full transparent paint pixel + TRop::borders::readBorders(rasCM, selector, reader, &painter.runsMap()); + painter.paintBorders(reader.borders()); + + rasCM->unlock(); } //--------------------------------------------------------------------------------------------- -void TRop::despeckle(const TRasterP &ras, int sizeThreshold, bool check, bool transparentIsWhite) -{ - ras->lock(); - - if (TRasterCM32P(ras)) { - doDespeckleCM32(ras, sizeThreshold, check); - return; - } - if (TRaster32P(ras)) { - doDespeckleRGBM(ras, sizeThreshold, transparentIsWhite); - return; - } - if (TRaster64P(ras)) { - doDespeckleRGBM(ras, sizeThreshold, transparentIsWhite); - return; - } - if (TRasterGR8P(ras)) { - doDespeckleGR(ras, sizeThreshold); - return; - } - if (TRasterGR16P(ras)) { - doDespeckleGR(ras, sizeThreshold); - return; - } - - ras->unlock(); +void TRop::despeckle(const TRasterP &ras, int sizeThreshold, bool check, + bool transparentIsWhite) { + ras->lock(); + + if (TRasterCM32P(ras)) { + doDespeckleCM32(ras, sizeThreshold, check); + return; + } + if (TRaster32P(ras)) { + doDespeckleRGBM(ras, sizeThreshold, transparentIsWhite); + return; + } + if (TRaster64P(ras)) { + doDespeckleRGBM(ras, sizeThreshold, transparentIsWhite); + return; + } + if (TRasterGR8P(ras)) { + doDespeckleGR(ras, sizeThreshold); + return; + } + if (TRasterGR16P(ras)) { + doDespeckleGR(ras, sizeThreshold); + return; + } + + ras->unlock(); } //--------------------------------------------------------------------------------------------- @@ -492,232 +496,225 @@ void TRop::despeckle(const TRasterP &ras, int sizeThreshold, bool check, bool tr /*! Performs a copy of rin and then applies despeckling. */ -void TRop::despeckle(const TRasterP &rout, const TRasterP &rin, int sizeThreshold, bool check) -{ - TRop::copy(rout, rin); - TRop::despeckle(rout, sizeThreshold, check); +void TRop::despeckle(const TRasterP &rout, const TRasterP &rin, + int sizeThreshold, bool check) { + TRop::copy(rout, rin); + TRop::despeckle(rout, sizeThreshold, check); } //********************************************************************************************************* // Majority Despeckling //********************************************************************************************************* -namespace -{ +namespace { template -class FillingReader : public DespecklingReader -{ +class FillingReader : public DespecklingReader { public: - typedef typename PixelSelector::pixel_type pixel_type; - typedef typename PixelSelector::value_type value_type; + typedef typename PixelSelector::pixel_type pixel_type; + typedef typename PixelSelector::value_type value_type; private: - ReplacePainter m_painter; + ReplacePainter m_painter; public: - FillingReader(const TRasterGR8P &rasGR, int sizeTol) - : DespecklingReader(sizeTol), m_painter(rasGR, TPixelGR8::Black) {} + FillingReader(const TRasterGR8P &rasGR, int sizeTol) + : DespecklingReader(sizeTol), m_painter(rasGR, TPixelGR8::Black) {} - void openContainer(const RasterEdgeIterator &it); - void addElement(const RasterEdgeIterator &it); - void closeContainer(); + void openContainer(const RasterEdgeIterator &it); + void addElement(const RasterEdgeIterator &it); + void closeContainer(); - RunsMapP &runsMap() { return m_painter.runsMap(); } + RunsMapP &runsMap() { return m_painter.runsMap(); } }; //--------------------------------------------------------------------------------------------- template -void FillingReader::openContainer(const RasterEdgeIterator &it) -{ - DespecklingReader::openContainer(it.pos()); +void FillingReader::openContainer( + const RasterEdgeIterator &it) { + DespecklingReader::openContainer(it.pos()); } //--------------------------------------------------------------------------------------------- template -void FillingReader::addElement(const RasterEdgeIterator &it) -{ - DespecklingReader::addElement(it.pos()); +void FillingReader::addElement( + const RasterEdgeIterator &it) { + DespecklingReader::addElement(it.pos()); } //--------------------------------------------------------------------------------------------- template -void FillingReader::closeContainer() -{ - if (isSpeckle(m_border)) - m_painter.paintBorder(m_border); +void FillingReader::closeContainer() { + if (isSpeckle(m_border)) m_painter.paintBorder(m_border); - DespecklingReader::closeContainer(); + DespecklingReader::closeContainer(); } //============================================================================================= -inline TPoint direction(const TPoint &a, const TPoint &b) -{ - return TPoint((b.x > a.x) ? 1 : (b.x < a.x) ? -1 : 0, - (b.y > a.y) ? 1 : (b.y < a.y) ? -1 : 0); +inline TPoint direction(const TPoint &a, const TPoint &b) { + return TPoint((b.x > a.x) ? 1 : (b.x < a.x) ? -1 : 0, + (b.y > a.y) ? 1 : (b.y < a.y) ? -1 : 0); } //--------------------------------------------------------------------------------------------- template bool majority(const TRasterPT ras, const TRasterGR8P &rasGR, - const PixelSelector &selector, const Border &border, - typename PixelSelector::value_type &color) -{ - typedef typename PixelSelector::value_type value_type; + const PixelSelector &selector, const Border &border, + typename PixelSelector::value_type &color) { + typedef typename PixelSelector::value_type value_type; - //Build a histogram of all found colors around the border - std::map histogram; + // Build a histogram of all found colors around the border + std::map histogram; - Pixel *pix, *basePix = ras->pixels(0); - TPixelGR8 *grPix; + Pixel *pix, *basePix = ras->pixels(0); + TPixelGR8 *grPix; - int diff, x, y, lx = ras->getLx(), ly = ras->getLy(), wrap = ras->getWrap(); + int diff, x, y, lx = ras->getLx(), ly = ras->getLy(), wrap = ras->getWrap(); - assert(border.m_points[1].y > border.m_points[0].y); + assert(border.m_points[1].y > border.m_points[0].y); - //Iterate the raster along the border - const std::vector &points = border.m_points; + // Iterate the raster along the border + const std::vector &points = border.m_points; - RasterEdgeIterator - start(ras, selector, points[0], direction(points[0], points[1])), - it(start); + RasterEdgeIterator start(ras, selector, points[0], + direction(points[0], points[1])), + it(start); - size_t next = 1, size = points.size(); - do { - while (it.pos() != points[next]) { - pix = it.leftPix(); - diff = pix - basePix; - x = diff % wrap; - y = diff / wrap; + size_t next = 1, size = points.size(); + do { + while (it.pos() != points[next]) { + pix = it.leftPix(); + diff = pix - basePix; + x = diff % wrap; + y = diff / wrap; - if (x >= 0 && y >= 0 && x < lx && y < ly) { - grPix = rasGR->pixels(y) + x; - if (grPix->value) - ++histogram[it.leftColor()]; - } + if (x >= 0 && y >= 0 && x < lx && y < ly) { + grPix = rasGR->pixels(y) + x; + if (grPix->value) ++histogram[it.leftColor()]; + } - it.setEdge(it.pos() + it.dir(), it.dir()); - } + it.setEdge(it.pos() + it.dir(), it.dir()); + } - next = (next + 1) % size; - it.setEdge(it.pos(), direction(it.pos(), points[next])); - } while (it != start); + next = (next + 1) % size; + it.setEdge(it.pos(), direction(it.pos(), points[next])); + } while (it != start); - if (!histogram.empty()) { - //Return the most found color - color = histogram.begin()->first; - return true; - } + if (!histogram.empty()) { + // Return the most found color + color = histogram.begin()->first; + return true; + } - return false; + return false; } //--------------------------------------------------------------------------------------------- template -void majorityDespeckle(const TRasterPT &ras, int sizeThreshold) -{ - typedef typename TRop::borders::PixelSelector pixel_selector; - typedef typename pixel_selector::pixel_type pixel_type; - typedef typename pixel_selector::value_type value_type; +void majorityDespeckle(const TRasterPT &ras, int sizeThreshold) { + typedef typename TRop::borders::PixelSelector pixel_selector; + typedef typename pixel_selector::pixel_type pixel_type; + typedef typename pixel_selector::value_type value_type; - ras->lock(); + ras->lock(); - //Use a temporary bitmap (well, a bytemap - for now?) to store the found speckles - TRasterGR8P rasGR(ras->getSize()); - rasGR->fill(TPixelGR8::White); + // Use a temporary bitmap (well, a bytemap - for now?) to store the found + // speckles + TRasterGR8P rasGR(ras->getSize()); + rasGR->fill(TPixelGR8::White); - //Find the speckles and draw them on the bitmap - pixel_selector selector; - FillingReader reader(rasGR, sizeThreshold); + // Find the speckles and draw them on the bitmap + pixel_selector selector; + FillingReader reader(rasGR, sizeThreshold); - TRop::borders::readBorders(ras, selector, reader, &reader.runsMap()); + TRop::borders::readBorders(ras, selector, reader, &reader.runsMap()); - //Now, operate each speckle. Try to apply a majority color to the speckle - ReplacePainter painter(ras); - painter.runsMap() = reader.runsMap(); + // Now, operate each speckle. Try to apply a majority color to the speckle + ReplacePainter painter(ras); + painter.runsMap() = reader.runsMap(); - ReplacePainter painterGR(rasGR, TPixelGR8::White); - painterGR.runsMap() = reader.runsMap(); + ReplacePainter painterGR(rasGR, TPixelGR8::White); + painterGR.runsMap() = reader.runsMap(); - std::deque borders = reader.borders(); //Note that the DEEP copy is NEEDED + std::deque borders = + reader.borders(); // Note that the DEEP copy is NEEDED - int processedCount = 1; - while (processedCount > 0 && !borders.empty()) { - processedCount = 0; + int processedCount = 1; + while (processedCount > 0 && !borders.empty()) { + processedCount = 0; - //Traverse the speckles list. Try to apply majority. - Border *current, *last = borders.back(); + // Traverse the speckles list. Try to apply majority. + Border *current, *last = borders.back(); - do { - current = borders.front(); - borders.pop_front(); + do { + current = borders.front(); + borders.pop_front(); - value_type color; - if (majority(ras, rasGR, selector, *current, color)) { - ++processedCount; - painter.color() = color; + value_type color; + if (majority(ras, rasGR, selector, *current, color)) { + ++processedCount; + painter.color() = color; - painter.paintBorder(*current); - painterGR.paintBorder(*current); - } else - borders.push_back(current); + painter.paintBorder(*current); + painterGR.paintBorder(*current); + } else + borders.push_back(current); - } while (current != last); - } + } while (current != last); + } - //Speckles may remain. In this case, fill with transparent. - painter.color() = selector.transparent(); - while (!borders.empty()) { - Border *current = borders.front(); - painter.paintBorder(*current); - borders.pop_front(); - } + // Speckles may remain. In this case, fill with transparent. + painter.color() = selector.transparent(); + while (!borders.empty()) { + Border *current = borders.front(); + painter.paintBorder(*current); + borders.pop_front(); + } - ras->unlock(); + ras->unlock(); } -} //namespace +} // namespace //================================================================================================ -void TRop::majorityDespeckle(const TRasterP &ras, int sizeThreshold) -{ - TRaster32P ras32(ras); - if (ras32) { - ::majorityDespeckle(ras32, sizeThreshold); - return; - } - - TRaster64P ras64(ras); - if (ras64) { - ::majorityDespeckle(ras64, sizeThreshold); - return; - } - - TRasterGR8P rasGR8(ras); - if (rasGR8) { - ::majorityDespeckle(rasGR8, sizeThreshold); - return; - } - - TRasterGR16P rasGR16(ras); - if (rasGR16) { - ::majorityDespeckle(rasGR16, sizeThreshold); - return; - } - - TRasterCM32P rasCM32(ras); - if (rasCM32) { - //Not yet implemented - assert(false); - - //::majorityDespeckleCM(rasCM32, sizeThreshold, toneTol); - return; - } +void TRop::majorityDespeckle(const TRasterP &ras, int sizeThreshold) { + TRaster32P ras32(ras); + if (ras32) { + ::majorityDespeckle(ras32, sizeThreshold); + return; + } + + TRaster64P ras64(ras); + if (ras64) { + ::majorityDespeckle(ras64, sizeThreshold); + return; + } + + TRasterGR8P rasGR8(ras); + if (rasGR8) { + ::majorityDespeckle(rasGR8, sizeThreshold); + return; + } + + TRasterGR16P rasGR16(ras); + if (rasGR16) { + ::majorityDespeckle(rasGR16, sizeThreshold); + return; + } + + TRasterCM32P rasCM32(ras); + if (rasCM32) { + // Not yet implemented + assert(false); + + //::majorityDespeckleCM(rasCM32, sizeThreshold, toneTol); + return; + } } diff --git a/toonz/sources/common/trop/tdistancetransform.cpp b/toonz/sources/common/trop/tdistancetransform.cpp index 3a4bf49..401ca33 100644 --- a/toonz/sources/common/trop/tdistancetransform.cpp +++ b/toonz/sources/common/trop/tdistancetransform.cpp @@ -8,7 +8,8 @@ // STD includes #include -//#define UNIT_TEST // Enables unit testing at program startup +//#define UNIT_TEST // Enables unit +//testing at program startup //************************************************************************ // Rationale @@ -25,133 +26,136 @@ // Local namespace stuff //************************************************************************ -namespace -{ +namespace { /*! \brief Given 2 parabolas with (minimal) height at centers \p a and \p b and centers separated by distance \p d, returns the min between - \p d and the value \p x satisfying a + x^2 == b + (x - d)^2. + \p d and the value \p x satisfying a + x^2 == b + (x - + d)^2. */ -unsigned int takeoverDist(unsigned int a, unsigned int b, unsigned int d) -{ - // The actual formula is: x = (h^2 + b - a) / 2h. It simplifies as follows - // using integers only. +unsigned int takeoverDist(unsigned int a, unsigned int b, unsigned int d) { + // The actual formula is: x = (h^2 + b - a) / 2h. It simplifies as follows + // using integers only. - // NOTE: It can be proven that with integer division, x/ab == (x/a)/b. - return (b < a) ? d : std::max((d + (b - a) / d + 1) / 2, d); // Note the +1 to get the ceil + // NOTE: It can be proven that with integer division, x/ab == (x/a)/b. + return (b < a) ? d : std::max((d + (b - a) / d + 1) / 2, + d); // Note the +1 to get the ceil } //-------------------------------------------------------------- template -void initializeDT(const TRasterPT &ras, const TRasterPT &dtRas, - IsInsideFunc isInside) -{ - assert(ras->getLx() == dtRas->getLx() && ras->getLy() == dtRas->getLy()); - - static const unsigned int uiMax = // Due to the above takeoverDist, for - (std::numeric_limits::max)() - 2; // d == 1 - - int lx = ras->getLx(), ly = ras->getLy(); - for (int y = 0; y != ly; ++y) { - Pix *pix = ras->pixels(y), *rowEnd = pix + lx; - unsigned int *dt = dtRas->pixels(y); - - for (; pix != rowEnd; ++pix, ++dt) { - assert(*dt == 0u); - - if (!isInside(*pix)) - *dt = uiMax; - } - } +void initializeDT(const TRasterPT &ras, + const TRasterPT &dtRas, IsInsideFunc isInside) { + assert(ras->getLx() == dtRas->getLx() && ras->getLy() == dtRas->getLy()); + + static const unsigned int uiMax = // Due to the above takeoverDist, for + (std::numeric_limits::max)() - 2; // d == 1 + + int lx = ras->getLx(), ly = ras->getLy(); + for (int y = 0; y != ly; ++y) { + Pix *pix = ras->pixels(y), *rowEnd = pix + lx; + unsigned int *dt = dtRas->pixels(y); + + for (; pix != rowEnd; ++pix, ++dt) { + assert(*dt == 0u); + + if (!isInside(*pix)) *dt = uiMax; + } + } } //-------------------------------------------------------------- template -void expand(int lineLength, int linesCount, - Pix *buf, int incrPix, - int incrLine, - unsigned int *dtBuf, int dtIncrPix, - int dtIncrLine, - OutFunc outFunc) -{ - struct locals { - static void copyLine(unsigned int *dst, unsigned int *src, unsigned int *srcEnd, - int srcStride) - { - for (; src != srcEnd; src += srcStride, ++dst) - *dst = *src; - } - - static void buildRange(unsigned int *dtRef, unsigned int *dtLineEnd, - unsigned int *&dtEnd, unsigned int *&dtNewRef) - { - unsigned int d = 1, dNew = 0, // dNew at 0 to provide a consistent dtNewRef - dMax = (std::numeric_limits::max)(); // at the end - should not matter though - unsigned int *dt = dtRef + 1; - - for (; d <= dMax && dt != dtLineEnd; ++d, ++dt) // Pick larger intervals if possible - { - unsigned int newDMax = ::takeoverDist(*dtRef, *dt, d); // - if (newDMax <= dMax) { - dNew = d; - dMax = newDMax; - } - } - - dtEnd = dtRef + std::min(d, dMax); // Could end the line before (dMax < d) - dtNewRef = dtRef + dNew; - } - }; // locals - - // Allocate a buffer equivalent to a dt line. It will store the original - // dt values. Final dt values will be written directly on the dt raster. - // This is necessary since read and write intervals overlap. - std::unique_ptr dtOriginalLine(new unsigned[lineLength]); - - unsigned int *odtLineStart = dtOriginalLine.get(), - *odtLineEnd = odtLineStart + lineLength; - - // Process each line - for (int l = 0; l != linesCount; ++l) { - unsigned int *dtLineStart = dtBuf + dtIncrLine * l, // Using dtBuf to track colors from now on, - *dtLineEnd = dtLineStart + dtIncrPix * lineLength, // it already embeds colorFunc's output due - *dt = dtLineStart, // to the way it was initialized. - *odtRef = odtLineStart; - - Pix *lineStart = buf + incrLine * l, - *pix = lineStart; - - // Make a copy of the original dt values - locals::copyLine(dtOriginalLine.get(), dtLineStart, dtLineEnd, dtIncrPix); - - // Expand a colored pixel along the line - while (dt != dtLineEnd) { - // The line is subdivided in consecutive ranges associated to the same - // half-parabola - process one - - // Build a half-parabola range - unsigned int *dtEnd, *odtNewRef; - locals::buildRange(odtRef, odtLineEnd, dtEnd, odtNewRef); - - assert(odtLineStart <= odtNewRef && odtNewRef <= odtLineEnd); - assert(odtLineStart <= dtEnd && dtEnd <= odtLineEnd); - - dtEnd = dtLineStart + dtIncrPix * (dtEnd - odtLineStart); // Convert dtEnd to the dt raster buffer - - // Process the range - Pix *ref = lineStart + incrPix * (odtRef - odtLineStart); - - unsigned int d = (pix - ref) / incrPix; - for (; dt != dtEnd; ++d, dt += dtIncrPix, pix += incrPix) - outFunc(*pix, *ref, *dt = *odtRef + sq(d)); - - odtRef = odtNewRef; - } - } +void expand(int lineLength, int linesCount, Pix *buf, int incrPix, int incrLine, + unsigned int *dtBuf, int dtIncrPix, int dtIncrLine, + OutFunc outFunc) { + struct locals { + static void copyLine(unsigned int *dst, unsigned int *src, + unsigned int *srcEnd, int srcStride) { + for (; src != srcEnd; src += srcStride, ++dst) *dst = *src; + } + + static void buildRange(unsigned int *dtRef, unsigned int *dtLineEnd, + unsigned int *&dtEnd, unsigned int *&dtNewRef) { + unsigned int d = 1, + dNew = 0, // dNew at 0 to provide a consistent dtNewRef + dMax = (std::numeric_limits::max)(); // at the end - + // should not + // matter though + unsigned int *dt = dtRef + 1; + + for (; d <= dMax && dt != dtLineEnd; + ++d, ++dt) // Pick larger intervals if possible + { + unsigned int newDMax = ::takeoverDist(*dtRef, *dt, d); // + if (newDMax <= dMax) { + dNew = d; + dMax = newDMax; + } + } + + dtEnd = + dtRef + std::min(d, dMax); // Could end the line before (dMax < d) + dtNewRef = dtRef + dNew; + } + }; // locals + + // Allocate a buffer equivalent to a dt line. It will store the original + // dt values. Final dt values will be written directly on the dt raster. + // This is necessary since read and write intervals overlap. + std::unique_ptr dtOriginalLine(new unsigned[lineLength]); + + unsigned int *odtLineStart = dtOriginalLine.get(), + *odtLineEnd = odtLineStart + lineLength; + + // Process each line + for (int l = 0; l != linesCount; ++l) { + unsigned int *dtLineStart = + dtBuf + + dtIncrLine * + l, // Using dtBuf to track colors from now on, + *dtLineEnd = + dtLineStart + + dtIncrPix * lineLength, // it already embeds colorFunc's output due + *dt = dtLineStart, // to the way it was initialized. + *odtRef = odtLineStart; + + Pix *lineStart = buf + incrLine * l, *pix = lineStart; + + // Make a copy of the original dt values + locals::copyLine(dtOriginalLine.get(), dtLineStart, dtLineEnd, dtIncrPix); + + // Expand a colored pixel along the line + while (dt != dtLineEnd) { + // The line is subdivided in consecutive ranges associated to the same + // half-parabola - process one + + // Build a half-parabola range + unsigned int *dtEnd, *odtNewRef; + locals::buildRange(odtRef, odtLineEnd, dtEnd, odtNewRef); + + assert(odtLineStart <= odtNewRef && odtNewRef <= odtLineEnd); + assert(odtLineStart <= dtEnd && dtEnd <= odtLineEnd); + + dtEnd = + dtLineStart + + dtIncrPix * + (dtEnd - odtLineStart); // Convert dtEnd to the dt raster buffer + + // Process the range + Pix *ref = lineStart + incrPix * (odtRef - odtLineStart); + + unsigned int d = (pix - ref) / incrPix; + for (; dt != dtEnd; ++d, dt += dtIncrPix, pix += incrPix) + outFunc(*pix, *ref, *dt = *odtRef + sq(d)); + + odtRef = odtNewRef; + } + } } //-------------------------------------------------------------- @@ -176,26 +180,29 @@ void expand(int lineLength, int linesCount, */ template -void distanceTransform(const TRasterPT &ras, IsInsideFunc isInside, OutFunc outFunc) -{ - int lx = ras->getLx(), ly = ras->getLy(); - - // Allocate a suitable temporary raster holding the (squared) distance transform - // built from the specified color function - TRasterPT dtRas(lx, ly); // Summed squared distances will be limited to - // 2 billions. This is generally suitable. - ::initializeDT(ras, dtRas, isInside); // The raster is binarized directly into the - // auxiliary dtRas. Pixels in the set to expand - // will have value 0, the others a suitable high value. - expand(lx, ly, ras->pixels(0), 1, ras->getWrap(), - dtRas->pixels(0), 1, dtRas->getWrap(), outFunc); - expand(lx, ly, ras->pixels(0) + lx - 1, -1, ras->getWrap(), - dtRas->pixels(0) + lx - 1, -1, dtRas->getWrap(), outFunc); - - expand(ly, lx, ras->pixels(0), ras->getWrap(), 1, - dtRas->pixels(0), dtRas->getWrap(), 1, outFunc); - expand(ly, lx, ras->pixels(ly - 1), -ras->getWrap(), 1, - dtRas->pixels(ly - 1), -dtRas->getWrap(), 1, outFunc); +void distanceTransform(const TRasterPT &ras, IsInsideFunc isInside, + OutFunc outFunc) { + int lx = ras->getLx(), ly = ras->getLy(); + + // Allocate a suitable temporary raster holding the (squared) distance + // transform + // built from the specified color function + TRasterPT dtRas( + lx, ly); // Summed squared distances will be limited to + // 2 billions. This is generally suitable. + ::initializeDT(ras, dtRas, + isInside); // The raster is binarized directly into the + // auxiliary dtRas. Pixels in the set to expand + // will have value 0, the others a suitable high value. + expand(lx, ly, ras->pixels(0), 1, ras->getWrap(), dtRas->pixels(0), 1, + dtRas->getWrap(), outFunc); + expand(lx, ly, ras->pixels(0) + lx - 1, -1, ras->getWrap(), + dtRas->pixels(0) + lx - 1, -1, dtRas->getWrap(), outFunc); + + expand(ly, lx, ras->pixels(0), ras->getWrap(), 1, dtRas->pixels(0), + dtRas->getWrap(), 1, outFunc); + expand(ly, lx, ras->pixels(ly - 1), -ras->getWrap(), 1, dtRas->pixels(ly - 1), + -dtRas->getWrap(), 1, outFunc); } } @@ -208,21 +215,19 @@ void distanceTransform(const TRasterPT &ras, IsInsideFunc isInside, OutFunc callbacks. */ -namespace -{ +namespace { struct SomePaint { - inline bool operator()(const TPixelCM32 &pix) const - { - return (pix.getTone() != 0) || (pix.getPaint() != 0); - } + inline bool operator()(const TPixelCM32 &pix) const { + return (pix.getTone() != 0) || (pix.getPaint() != 0); + } }; struct CopyPaint { - inline void operator()(TPixelCM32 &out, const TPixelCM32 &in, unsigned int) const - { - out.setPaint(in.getPaint()); - } + inline void operator()(TPixelCM32 &out, const TPixelCM32 &in, + unsigned int) const { + out.setPaint(in.getPaint()); + } }; } @@ -230,9 +235,8 @@ struct CopyPaint { // API functions //************************************************************************ -void TRop::expandPaint(const TRasterCM32P &rasCM) -{ - distanceTransform(rasCM, SomePaint(), CopyPaint()); +void TRop::expandPaint(const TRasterCM32P &rasCM) { + distanceTransform(rasCM, SomePaint(), CopyPaint()); } //************************************************************************ @@ -241,58 +245,47 @@ void TRop::expandPaint(const TRasterCM32P &rasCM) #if defined UNIT_TEST && !defined NDEBUG -namespace -{ +namespace { -void assertEqualBufs(const TRasterT &a, const TRasterT &b) -{ - for (int y = 0; y != a.getLy(); ++y) { - for (int x = 0; x != a.getLx(); ++x) - assert(a.pixels(y)[x] == b.pixels(y)[x]); - } +void assertEqualBufs(const TRasterT &a, + const TRasterT &b) { + for (int y = 0; y != a.getLy(); ++y) { + for (int x = 0; x != a.getLx(); ++x) + assert(a.pixels(y)[x] == b.pixels(y)[x]); + } } struct Selector { - inline bool operator()(unsigned int val) const - { - return val; - } + inline bool operator()(unsigned int val) const { return val; } }; struct OutputDT { - inline void operator()(unsigned int &out, const unsigned int &in, unsigned int d2) const - { - out = d2; - } + inline void operator()(unsigned int &out, const unsigned int &in, + unsigned int d2) const { + out = d2; + } }; struct DTTest { - DTTest() - { - unsigned int imgBuf[] = { - 0, 0, 1, 0, 0, 0, - 0, 0, 1, 0, 0, 0, - 0, 1, 1, 1, 1, 0, - 0, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - }; - - unsigned int dtBuf[] = { - 4, 1, 0, 1, 4, 5, - 2, 1, 0, 1, 1, 2, - 1, 0, 0, 0, 0, 1, - 1, 0, 1, 1, 1, 2, - 2, 1, 2, 4, 4, 5, - }; - - TRasterPT imgRas(6, 5, 6, imgBuf, false), - dtRas(6, 5, 6, dtBuf, false); - - distanceTransform(imgRas, Selector(), OutputDT()); - assertEqualBufs(*imgRas, *dtRas); - } + DTTest() { + unsigned int imgBuf[] = { + 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, + 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }; + + unsigned int dtBuf[] = { + 4, 1, 0, 1, 4, 5, 2, 1, 0, 1, 1, 2, 1, 0, 0, + 0, 0, 1, 1, 0, 1, 1, 1, 2, 2, 1, 2, 4, 4, 5, + }; + + TRasterPT imgRas(6, 5, 6, imgBuf, false), + dtRas(6, 5, 6, dtBuf, false); + + distanceTransform(imgRas, Selector(), OutputDT()); + assertEqualBufs(*imgRas, *dtRas); + } } dtTest; -} // namespace +} // namespace -#endif // UNIT_TEST && !NDEBUG +#endif // UNIT_TEST && !NDEBUG diff --git a/toonz/sources/common/trop/terodilate.cpp b/toonz/sources/common/trop/terodilate.cpp index 519e0a2..63021d3 100644 --- a/toonz/sources/common/trop/terodilate.cpp +++ b/toonz/sources/common/trop/terodilate.cpp @@ -7,108 +7,114 @@ /*! \file terodilate.cpp -This file contains an implementation of a greyscale (ie per-channel) erode/dilate +This file contains an implementation of a greyscale (ie per-channel) +erode/dilate morphological operator, following the van Herk/Gil-Werman O(row*cols) algorithm. -An extension with circular structuring element is attempted - unfortunately I could +An extension with circular structuring element is attempted - unfortunately I +could not retrieve a copy of Miyataka's paper about that, which seemingly claimed -O(rows * cols) too. The implemented algorithm is a sub-optimal O(rows*cols*radius). +O(rows * cols) too. The implemented algorithm is a sub-optimal +O(rows*cols*radius). */ //******************************************************** // Auxiliary functions //******************************************************** -namespace -{ +namespace { template -void copyMatte(const TRasterPT &src, const TRasterPT &matte) -{ - typedef typename Pix::Channel Chan; - - int y, lx = src->getLx(), ly = src->getLy(); - for (y = 0; y != ly; ++y) { - Pix *s, *sBegin = src->pixels(y), *sEnd = sBegin + lx; - Chan *m, *mBegin = matte->pixels(y); - - for (s = sBegin, m = mBegin; s != sEnd; ++s, ++m) - *m = s->m; - } +void copyMatte(const TRasterPT &src, + const TRasterPT &matte) { + typedef typename Pix::Channel Chan; + + int y, lx = src->getLx(), ly = src->getLy(); + for (y = 0; y != ly; ++y) { + Pix *s, *sBegin = src->pixels(y), *sEnd = sBegin + lx; + Chan *m, *mBegin = matte->pixels(y); + + for (s = sBegin, m = mBegin; s != sEnd; ++s, ++m) *m = s->m; + } } //-------------------------------------------------------------- template -void copyChannels_erode(const TRasterPT &src, const TRasterPT &matte, - const TRasterPT &dst) -{ - typedef typename Pix::Channel Chan; +void copyChannels_erode(const TRasterPT &src, + const TRasterPT &matte, + const TRasterPT &dst) { + typedef typename Pix::Channel Chan; - // Just assemble src and matte, remembering to depremultiply src pixels before - // applying the new matte + // Just assemble src and matte, remembering to depremultiply src pixels before + // applying the new matte - double fac; + double fac; - int y, lx = src->getLx(), ly = src->getLy(); - for (y = 0; y != ly; ++y) { - const Pix *s, *sBegin = src->pixels(y), *sEnd = sBegin + lx; - Pix *d, *dBegin = dst->pixels(y); + int y, lx = src->getLx(), ly = src->getLy(); + for (y = 0; y != ly; ++y) { + const Pix *s, *sBegin = src->pixels(y), *sEnd = sBegin + lx; + Pix *d, *dBegin = dst->pixels(y); - Chan *m, *mBegin = matte->pixels(y); + Chan *m, *mBegin = matte->pixels(y); - for (s = sBegin, d = dBegin, m = mBegin; s != sEnd; ++s, ++d, ++m) { - fac = double(*m) / double(s->m); - d->r = fac * s->r, d->g = fac * s->g, d->b = fac * s->b, d->m = *m; - } - } + for (s = sBegin, d = dBegin, m = mBegin; s != sEnd; ++s, ++d, ++m) { + fac = double(*m) / double(s->m); + d->r = fac * s->r, d->g = fac * s->g, d->b = fac * s->b, d->m = *m; + } + } } //-------------------------------------------------------------- template -void copyChannels_dilate(const TRasterPT &src, const TRasterPT &matte, - const TRasterPT &dst) -{ - typedef typename Pix::Channel Chan; - - // Trickier - since src is presumably premultiplied, increasing its pixels' alpha by direct - // substitution would expose the excessive RGB discretization of pixels with a low matte value. - // So, let's just put the pixels on a black background. It should do fine. - - double max = Pix::maxChannelValue; - - int y, lx = src->getLx(), ly = src->getLy(); - for (y = 0; y != ly; ++y) { - const Pix *s, *sBegin = src->pixels(y), *sEnd = sBegin + lx; - Pix *d, *dBegin = dst->pixels(y); - - const Chan *m, *mBegin = matte->pixels(y); - - for (s = sBegin, d = dBegin, m = mBegin; s != sEnd; ++s, ++d, ++m) { - *d = *s; - d->m = s->m + (1.0 - s->m / max) * *m; - } - } +void copyChannels_dilate(const TRasterPT &src, + const TRasterPT &matte, + const TRasterPT &dst) { + typedef typename Pix::Channel Chan; + + // Trickier - since src is presumably premultiplied, increasing its pixels' + // alpha by direct + // substitution would expose the excessive RGB discretization of pixels with a + // low matte value. + // So, let's just put the pixels on a black background. It should do fine. + + double max = Pix::maxChannelValue; + + int y, lx = src->getLx(), ly = src->getLy(); + for (y = 0; y != ly; ++y) { + const Pix *s, *sBegin = src->pixels(y), *sEnd = sBegin + lx; + Pix *d, *dBegin = dst->pixels(y); + + const Chan *m, *mBegin = matte->pixels(y); + + for (s = sBegin, d = dBegin, m = mBegin; s != sEnd; ++s, ++d, ++m) { + *d = *s; + d->m = s->m + (1.0 - s->m / max) * *m; + } + } } -} // namespace +} // namespace //******************************************************** // EroDilate algorithms //******************************************************** -namespace -{ +namespace { template struct MaxFunc { - inline Chan operator()(const Chan &a, const Chan &b) { return std::max(a, b); } + inline Chan operator()(const Chan &a, const Chan &b) { + return std::max(a, b); + } }; template struct MinFunc { - inline Chan operator()(const Chan &a, const Chan &b) { return std::min(a, b); } + inline Chan operator()(const Chan &a, const Chan &b) { + return std::min(a, b); + } }; //-------------------------------------------------------------- @@ -117,370 +123,406 @@ struct MinFunc { template void erodilate_row(int len, const Chan *src, int sIncr, Chan *dst, int dIncr, - int rad, double radR, Func func) -{ - assert(rad >= 0); - - // Segment the row of specified length into wCount windows of max wSize elements - int w, wSize = 2 * rad + 1, wCount = len / wSize + 1; - int swIncr = wSize * sIncr, srIncr = rad * sIncr; - int dwIncr = wSize * dIncr, drIncr = rad * dIncr; - - const Chan *s, *sEnd = src + len * sIncr; - Chan *d, *dEnd = dst + len * dIncr; - - double one_radR = (1.0 - radR); - - for (w = 0; w != wCount; ++w) { - Chan *dwBegin = dst + w * dwIncr, *dwEnd = std::min(dwBegin + dwIncr, dEnd); - - // Compute prefixes - const Chan *swBegin = src + std::max(w * swIncr - srIncr - sIncr, 0), - *swEnd = src + std::min(w * swIncr + srIncr + sIncr, len * sIncr); - - s = swEnd - sIncr, d = dst + ((s - src) / sIncr) * dIncr + drIncr; // d already decremented by dIncr - - Chan val = *s, oldVal; - - for (s -= sIncr; (d >= dEnd) && (s >= swBegin); s -= sIncr, d -= dIncr) // s decremented here - { - assert(s >= src); - assert(s < sEnd); - assert((s - src) % sIncr == 0); - assert(d >= dst); - assert((d - dst) % dIncr == 0); - - val = func(oldVal = val, *s); - } - - for (; s >= swBegin; s -= sIncr, d -= dIncr) { - assert(s >= src); - assert(s < sEnd); - assert((s - src) % sIncr == 0); - assert(d >= dst); - assert(d < dEnd); - assert((d - dst) % dIncr == 0); - - val = func(oldVal = val, *s); - *d = (oldVal == val) ? val : one_radR * oldVal + radR * val; - } - - for (d = std::min(d, dEnd - dIncr); d >= dwBegin; d -= dIncr) { - assert(d >= dst); - assert(d < dEnd); - assert((d - dst) % dIncr == 0); - - val = func(oldVal = val, 0); - *d = (oldVal == val) ? val : one_radR * oldVal + radR * val; - } - - // Compute suffixes - swBegin = src + w * swIncr + srIncr, swEnd = std::min(swBegin + swIncr + sIncr, sEnd); - if (swBegin >= swEnd) - continue; - - s = swBegin, d = dwBegin; - - val = *s; - - for (s += sIncr; (s < swEnd); s += sIncr, d += dIncr) { - assert(s >= src); - assert(s < sEnd); - assert((s - src) % sIncr == 0); - assert(d >= dst); - assert(d < dEnd); - assert((d - dst) % dIncr == 0); - - val = func(oldVal = val, *s); - *d = func(*d, (oldVal == val) ? val : one_radR * oldVal + radR * val); - } - - for (; d < dwEnd; d += dIncr) { - assert(d >= dst); - assert(d < dEnd); - assert((d - dst) % dIncr == 0); - - val = func(oldVal = val, 0); - *d = func(*d, (oldVal == val) ? val : one_radR * oldVal + radR * val); - } - } + int rad, double radR, Func func) { + assert(rad >= 0); + + // Segment the row of specified length into wCount windows of max wSize + // elements + int w, wSize = 2 * rad + 1, wCount = len / wSize + 1; + int swIncr = wSize * sIncr, srIncr = rad * sIncr; + int dwIncr = wSize * dIncr, drIncr = rad * dIncr; + + const Chan *s, *sEnd = src + len * sIncr; + Chan *d, *dEnd = dst + len * dIncr; + + double one_radR = (1.0 - radR); + + for (w = 0; w != wCount; ++w) { + Chan *dwBegin = dst + w * dwIncr, *dwEnd = std::min(dwBegin + dwIncr, dEnd); + + // Compute prefixes + const Chan *swBegin = src + std::max(w * swIncr - srIncr - sIncr, 0), + *swEnd = + src + std::min(w * swIncr + srIncr + sIncr, len * sIncr); + + s = swEnd - sIncr, d = dst + ((s - src) / sIncr) * dIncr + + drIncr; // d already decremented by dIncr + + Chan val = *s, oldVal; + + for (s -= sIncr; (d >= dEnd) && (s >= swBegin); + s -= sIncr, d -= dIncr) // s decremented here + { + assert(s >= src); + assert(s < sEnd); + assert((s - src) % sIncr == 0); + assert(d >= dst); + assert((d - dst) % dIncr == 0); + + val = func(oldVal = val, *s); + } + + for (; s >= swBegin; s -= sIncr, d -= dIncr) { + assert(s >= src); + assert(s < sEnd); + assert((s - src) % sIncr == 0); + assert(d >= dst); + assert(d < dEnd); + assert((d - dst) % dIncr == 0); + + val = func(oldVal = val, *s); + *d = (oldVal == val) ? val : one_radR * oldVal + radR * val; + } + + for (d = std::min(d, dEnd - dIncr); d >= dwBegin; d -= dIncr) { + assert(d >= dst); + assert(d < dEnd); + assert((d - dst) % dIncr == 0); + + val = func(oldVal = val, 0); + *d = (oldVal == val) ? val : one_radR * oldVal + radR * val; + } + + // Compute suffixes + swBegin = src + w * swIncr + srIncr, + swEnd = std::min(swBegin + swIncr + sIncr, sEnd); + if (swBegin >= swEnd) continue; + + s = swBegin, d = dwBegin; + + val = *s; + + for (s += sIncr; (s < swEnd); s += sIncr, d += dIncr) { + assert(s >= src); + assert(s < sEnd); + assert((s - src) % sIncr == 0); + assert(d >= dst); + assert(d < dEnd); + assert((d - dst) % dIncr == 0); + + val = func(oldVal = val, *s); + *d = func(*d, (oldVal == val) ? val : one_radR * oldVal + radR * val); + } + + for (; d < dwEnd; d += dIncr) { + assert(d >= dst); + assert(d < dEnd); + assert((d - dst) % dIncr == 0); + + val = func(oldVal = val, 0); + *d = func(*d, (oldVal == val) ? val : one_radR * oldVal + radR * val); + } + } } //-------------------------------------------------------------- template -void erodilate_chan(const TRasterPT &src, const TRasterPT &dst, double radius, bool dilate) -{ - assert(radius > 0.0); - - int radI = tfloor(radius); - double radR = radius - radI; - - // Using a temporary raster to keep intermediate results. This allows us to - // perform a cache-friendly iteration in the separable/square kernel case - int x, y, lx = src->getLx(), ly = src->getLy(); - - // Peform rows erodilation - TRasterPT temp(ly, lx); // Notice transposition plz - - { - if (dilate) - for (y = 0; y != ly; ++y) - ::erodilate_row(lx, &src->pixels(y)->m, 4, temp->pixels(0) + y, ly, radI, radR, MaxFunc()); - else - for (y = 0; y != ly; ++y) - ::erodilate_row(lx, &src->pixels(y)->m, 4, temp->pixels(0) + y, ly, radI, radR, MinFunc()); - } - - // Perform columns erodilation - { - if (dilate) - for (x = 0; x != lx; ++x) - ::erodilate_row(ly, temp->pixels(x), 1, dst->pixels(0) + x, dst->getWrap(), radI, radR, MaxFunc()); - else - for (x = 0; x != lx; ++x) - ::erodilate_row(ly, temp->pixels(x), 1, dst->pixels(0) + x, dst->getWrap(), radI, radR, MinFunc()); - } +void erodilate_chan(const TRasterPT &src, const TRasterPT &dst, + double radius, bool dilate) { + assert(radius > 0.0); + + int radI = tfloor(radius); + double radR = radius - radI; + + // Using a temporary raster to keep intermediate results. This allows us to + // perform a cache-friendly iteration in the separable/square kernel case + int x, y, lx = src->getLx(), ly = src->getLy(); + + // Peform rows erodilation + TRasterPT temp(ly, lx); // Notice transposition plz + + { + if (dilate) + for (y = 0; y != ly; ++y) + ::erodilate_row(lx, &src->pixels(y)->m, 4, temp->pixels(0) + y, ly, + radI, radR, MaxFunc()); + else + for (y = 0; y != ly; ++y) + ::erodilate_row(lx, &src->pixels(y)->m, 4, temp->pixels(0) + y, ly, + radI, radR, MinFunc()); + } + + // Perform columns erodilation + { + if (dilate) + for (x = 0; x != lx; ++x) + ::erodilate_row(ly, temp->pixels(x), 1, dst->pixels(0) + x, + dst->getWrap(), radI, radR, MaxFunc()); + else + for (x = 0; x != lx; ++x) + ::erodilate_row(ly, temp->pixels(x), 1, dst->pixels(0) + x, + dst->getWrap(), radI, radR, MinFunc()); + } } //-------------------------------------------------------------- template -void rect_erodilate(const TRasterPT &src, const TRasterPT &dst, double radius) -{ - typedef typename Pix::Channel Chan; - - if (radius == 0.0) { - // No-op case - TRop::copy(dst, src); - return; - } - - bool dilate = (radius >= 0.0); - - // Perform columns erodilation - TRasterPT temp(src->getLx(), src->getLy()); - ::erodilate_chan(src, temp, fabs(radius), dilate); - - // Remember that we have just calculated the matte values. We still have to apply them to the old RGB - // values, which requires depremultiplying from source matte and premultiplying with the new one. - if (dilate) - ::copyChannels_dilate(src, temp, dst); - else - ::copyChannels_erode(src, temp, dst); +void rect_erodilate(const TRasterPT &src, const TRasterPT &dst, + double radius) { + typedef typename Pix::Channel Chan; + + if (radius == 0.0) { + // No-op case + TRop::copy(dst, src); + return; + } + + bool dilate = (radius >= 0.0); + + // Perform columns erodilation + TRasterPT temp(src->getLx(), src->getLy()); + ::erodilate_chan(src, temp, fabs(radius), dilate); + + // Remember that we have just calculated the matte values. We still have to + // apply them to the old RGB + // values, which requires depremultiplying from source matte and + // premultiplying with the new one. + if (dilate) + ::copyChannels_dilate(src, temp, dst); + else + ::copyChannels_erode(src, temp, dst); } -} // namespace +} // namespace //******************************************************** // EroDilate round algorithm //******************************************************** -namespace -{ +namespace { template -void erodilate_quarters(int lx, int ly, - Chan *src, int sIncrX, int sIncrY, - Chan *dst, int dIncrX, int dIncrY, - double radius, double shift, Func func) -{ - double sqRadius = sq(radius); - double squareHeight = radius / tcg::consts::sqrt2; - int squareHeightI = tfloor(squareHeight); - - // For every arc point - int arcY; - for (arcY = -squareHeightI; arcY <= squareHeightI; ++arcY) { - // Calculate x and weights - double sqArcY = sq(arcY); - assert(sqRadius >= sqArcY); - - double x = shift + sqrt(sqRadius - sqArcY) - squareHeight; - - int arcX = tfloor(x); - double w = x - arcX, one_w = 1.0 - w; - - // Build dst area influenced by the arc point. Func with 0 outside that. - TRect bounds(0, 0, lx, ly); - - TRect dRect(bounds * (bounds + TPoint(-arcX, -arcY))); - TRect sRect(bounds * (bounds + TPoint(arcX, arcY))); - - int sy, dy; - - // Func with 0 before dRect.y0 - for (dy = 0; dy < dRect.y0; ++dy) { - Chan *d, *dBegin = dst + dy * dIncrY, *dEnd = dBegin + lx * dIncrX; - for (d = dBegin; d != dEnd; d += dIncrX) { - //assert(d >= dst); assert(d < dEnd); assert((d-dst) % dIncrX == 0); - *d = func(*d, 0); - } - } - - // Func with 0 after dRect.y1 - for (dy = dRect.y1; dy < ly; ++dy) { - Chan *d, *dBegin = dst + dy * dIncrY, *dEnd = dBegin + lx * dIncrX; - for (d = dBegin; d != dEnd; d += dIncrX) { - //assert(d >= dst); assert(d < dEnd); assert((d-dst) % dIncrX == 0); - *d = func(*d, 0); - } - } - - // For every dst pixel in the area, Func with the corresponding pixel in src - for (dy = dRect.y0, sy = sRect.y0; dy != dRect.y1; ++dy, ++sy) { - Chan *d, *dLine = dst + dy * dIncrY, *dBegin = dLine + dRect.x0 * dIncrX; - Chan *s, *sLine = src + sy * sIncrY, *sBegin = sLine + sRect.x0 * sIncrX, *sEnd = sLine + sRect.x1 * sIncrX; - - Chan *sLast = sEnd - sIncrX; // sLast would lerp with sEnd - - for (d = dBegin, s = sBegin; s != sLast; d += dIncrX, s += sIncrX) // hence we stop before it - { - //assert(s >= src); assert(s < sEnd); assert((s-src) % sIncrX == 0); - //assert(d >= dst); assert(d < dEnd); assert((d-dst) % dIncrX == 0); - - *d = func(*d, *s * one_w + *(s + sIncrX) * w); - } - - //assert(s >= src); assert(s < sEnd); assert((s-src) % sIncrX == 0); - //assert(d >= dst); assert(d < dEnd); assert((d-dst) % dIncrX == 0); - - *d = func(*d, *s * one_w); // lerp sLast with 0 - } - } +void erodilate_quarters(int lx, int ly, Chan *src, int sIncrX, int sIncrY, + Chan *dst, int dIncrX, int dIncrY, double radius, + double shift, Func func) { + double sqRadius = sq(radius); + double squareHeight = radius * M_SQRT1_2; + int squareHeightI = tfloor(squareHeight); + + // For every arc point + int arcY; + for (arcY = -squareHeightI; arcY <= squareHeightI; ++arcY) { + // Calculate x and weights + double sqArcY = sq(arcY); + assert(sqRadius >= sqArcY); + + double x = shift + sqrt(sqRadius - sqArcY) - squareHeight; + + int arcX = tfloor(x); + double w = x - arcX, one_w = 1.0 - w; + + // Build dst area influenced by the arc point. Func with 0 outside that. + TRect bounds(0, 0, lx, ly); + + TRect dRect(bounds * (bounds + TPoint(-arcX, -arcY))); + TRect sRect(bounds * (bounds + TPoint(arcX, arcY))); + + int sy, dy; + + // Func with 0 before dRect.y0 + for (dy = 0; dy < dRect.y0; ++dy) { + Chan *d, *dBegin = dst + dy * dIncrY, *dEnd = dBegin + lx * dIncrX; + for (d = dBegin; d != dEnd; d += dIncrX) { + // assert(d >= dst); assert(d < dEnd); assert((d-dst) % dIncrX == 0); + *d = func(*d, 0); + } + } + + // Func with 0 after dRect.y1 + for (dy = dRect.y1; dy < ly; ++dy) { + Chan *d, *dBegin = dst + dy * dIncrY, *dEnd = dBegin + lx * dIncrX; + for (d = dBegin; d != dEnd; d += dIncrX) { + // assert(d >= dst); assert(d < dEnd); assert((d-dst) % dIncrX == 0); + *d = func(*d, 0); + } + } + + // For every dst pixel in the area, Func with the corresponding pixel in src + for (dy = dRect.y0, sy = sRect.y0; dy != dRect.y1; ++dy, ++sy) { + Chan *d, *dLine = dst + dy * dIncrY, *dBegin = dLine + dRect.x0 * dIncrX; + Chan *s, *sLine = src + sy * sIncrY, *sBegin = sLine + sRect.x0 * sIncrX, + *sEnd = sLine + sRect.x1 * sIncrX; + + Chan *sLast = sEnd - sIncrX; // sLast would lerp with sEnd + + for (d = dBegin, s = sBegin; s != sLast; + d += dIncrX, s += sIncrX) // hence we stop before it + { + // assert(s >= src); assert(s < sEnd); assert((s-src) % sIncrX == 0); + // assert(d >= dst); assert(d < dEnd); assert((d-dst) % dIncrX == 0); + + *d = func(*d, *s * one_w + *(s + sIncrX) * w); + } + + // assert(s >= src); assert(s < sEnd); assert((s-src) % sIncrX == 0); + // assert(d >= dst); assert(d < dEnd); assert((d-dst) % dIncrX == 0); + + *d = func(*d, *s * one_w); // lerp sLast with 0 + } + } } //-------------------------------------------------------------- template -void circular_erodilate(const TRasterPT &src, const TRasterPT &dst, double radius) -{ - typedef typename Pix::Channel Chan; - - if (radius == 0.0) { - // No-op case - TRop::copy(dst, src); - return; - } - - // Ok, the idea is: consider the maximal embedded square in our circular structuring element. - // Erodilating by it consists in the consecutive erodilation by rows and columns with the same - // 'square' radius. Now, it's easy to see that the square could be 'bent' so that one of its - // edges matches that of a 1/4 of the circle's edge, while remaining inside the circle. - // Erodilating by the bent square can be achieved by erodilating first by rows or column for - // the square edge radius, followed by perpendicular erodilationg with a fourth of our - // circumference. Sum the 4 erodilations needed to complete the circumference - and it's done. - - // NOTE: Unfortunately, the above decomposition has lots of intersections among the pieces - yet - // it's simple enough and removes an O(radius) from the naive algorithm. Could be done better? - - // First, build the various erodilation data - bool dilate = (radius >= 0.0); - radius = fabs(radius); - - double inner_square_diameter = radius * tcg::consts::sqrt2; - - double shift = 0.25 * inner_square_diameter; // Shift of the bent square SE needed to avoid - // touching the circumference on the other side - double row_filter_radius = 0.5 * (inner_square_diameter - shift); - double cseShift = 0.5 * shift; // circumference structuring element shift - - int lx = src->getLx(), ly = src->getLy(); - - TRasterPT temp1(lx, ly), temp2(lx, ly); - - int radI = tfloor(row_filter_radius); - double radR = row_filter_radius - radI; - - if (dilate) { - temp2->fill(0); // Initialize with a Func-neutral value - - if (row_filter_radius > 0.0) - for (int y = 0; y != ly; ++y) - ::erodilate_row(lx, &src->pixels(y)->m, 4, temp1->pixels(y), 1, radI, radR, MaxFunc()); - else - ::copyMatte(src, temp1); - - ::erodilate_quarters(lx, ly, temp1->pixels(0), 1, lx, temp2->pixels(0), 1, lx, radius, cseShift, MaxFunc()); - ::erodilate_quarters(lx, ly, temp1->pixels(0) + lx - 1, -1, lx, temp2->pixels(0) + lx - 1, -1, lx, radius, cseShift, MaxFunc()); - - if (row_filter_radius > 0.0) - for (int x = 0; x != lx; ++x) - ::erodilate_row(ly, &src->pixels(0)[x].m, 4 * src->getWrap(), temp1->pixels(0) + x, lx, radI, radR, MaxFunc()); - else - ::copyMatte(src, temp1); - - ::erodilate_quarters(ly, lx, temp1->pixels(0), lx, 1, temp2->pixels(0), lx, 1, radius, cseShift, MaxFunc()); - ::erodilate_quarters(ly, lx, temp1->pixels(0) + lx * ly - 1, -lx, -1, temp2->pixels(0) + lx * ly - 1, -lx, -1, radius, cseShift, MaxFunc()); - } else { - temp2->fill((std::numeric_limits::max)()); // Initialize with a Func-neutral value - - if (row_filter_radius > 0.0) - for (int y = 0; y != ly; ++y) - ::erodilate_row(lx, &src->pixels(y)->m, 4, temp1->pixels(y), 1, radI, radR, MinFunc()); - else - ::copyMatte(src, temp1); - - ::erodilate_quarters(lx, ly, temp1->pixels(0), 1, lx, temp2->pixels(0), 1, lx, radius, cseShift, MinFunc()); - ::erodilate_quarters(lx, ly, temp1->pixels(0) + lx - 1, -1, lx, temp2->pixels(0) + lx - 1, -1, lx, radius, cseShift, MinFunc()); - - if (row_filter_radius > 0.0) - for (int x = 0; x != lx; ++x) - ::erodilate_row(ly, &src->pixels(0)[x].m, 4 * src->getWrap(), temp1->pixels(0) + x, lx, radI, radR, MinFunc()); - else - ::copyMatte(src, temp1); - - ::erodilate_quarters(ly, lx, temp1->pixels(0), lx, 1, temp2->pixels(0), lx, 1, radius, cseShift, MinFunc()); - ::erodilate_quarters(ly, lx, temp1->pixels(0) + lx * ly - 1, -lx, -1, temp2->pixels(0) + lx * ly - 1, -lx, -1, radius, cseShift, MinFunc()); - } - - // Remember that we have just calculated the matte values. We still have to apply them to the old RGB - // values, which requires depremultiplying from source matte and premultiplying with the new one. - if (dilate) - ::copyChannels_dilate(src, temp2, dst); - else - ::copyChannels_erode(src, temp2, dst); +void circular_erodilate(const TRasterPT &src, const TRasterPT &dst, + double radius) { + typedef typename Pix::Channel Chan; + + if (radius == 0.0) { + // No-op case + TRop::copy(dst, src); + return; + } + + // Ok, the idea is: consider the maximal embedded square in our circular + // structuring element. + // Erodilating by it consists in the consecutive erodilation by rows and + // columns with the same + // 'square' radius. Now, it's easy to see that the square could be 'bent' so + // that one of its + // edges matches that of a 1/4 of the circle's edge, while remaining inside + // the circle. + // Erodilating by the bent square can be achieved by erodilating first by rows + // or column for + // the square edge radius, followed by perpendicular erodilationg with a + // fourth of our + // circumference. Sum the 4 erodilations needed to complete the circumference + // - and it's done. + + // NOTE: Unfortunately, the above decomposition has lots of intersections + // among the pieces - yet + // it's simple enough and removes an O(radius) from the naive algorithm. Could + // be done better? + + // First, build the various erodilation data + bool dilate = (radius >= 0.0); + radius = fabs(radius); + + double inner_square_diameter = radius * M_SQRT2; + + double shift = + 0.25 * + inner_square_diameter; // Shift of the bent square SE needed to avoid + // touching the circumference on the other side + double row_filter_radius = 0.5 * (inner_square_diameter - shift); + double cseShift = 0.5 * shift; // circumference structuring element shift + + int lx = src->getLx(), ly = src->getLy(); + + TRasterPT temp1(lx, ly), temp2(lx, ly); + + int radI = tfloor(row_filter_radius); + double radR = row_filter_radius - radI; + + if (dilate) { + temp2->fill(0); // Initialize with a Func-neutral value + + if (row_filter_radius > 0.0) + for (int y = 0; y != ly; ++y) + ::erodilate_row(lx, &src->pixels(y)->m, 4, temp1->pixels(y), 1, radI, + radR, MaxFunc()); + else + ::copyMatte(src, temp1); + + ::erodilate_quarters(lx, ly, temp1->pixels(0), 1, lx, temp2->pixels(0), 1, + lx, radius, cseShift, MaxFunc()); + ::erodilate_quarters(lx, ly, temp1->pixels(0) + lx - 1, -1, lx, + temp2->pixels(0) + lx - 1, -1, lx, radius, cseShift, + MaxFunc()); + + if (row_filter_radius > 0.0) + for (int x = 0; x != lx; ++x) + ::erodilate_row(ly, &src->pixels(0)[x].m, 4 * src->getWrap(), + temp1->pixels(0) + x, lx, radI, radR, MaxFunc()); + else + ::copyMatte(src, temp1); + + ::erodilate_quarters(ly, lx, temp1->pixels(0), lx, 1, temp2->pixels(0), lx, + 1, radius, cseShift, MaxFunc()); + ::erodilate_quarters(ly, lx, temp1->pixels(0) + lx * ly - 1, -lx, -1, + temp2->pixels(0) + lx * ly - 1, -lx, -1, radius, + cseShift, MaxFunc()); + } else { + temp2->fill((std::numeric_limits::max)()); // Initialize with a + // Func-neutral value + + if (row_filter_radius > 0.0) + for (int y = 0; y != ly; ++y) + ::erodilate_row(lx, &src->pixels(y)->m, 4, temp1->pixels(y), 1, radI, + radR, MinFunc()); + else + ::copyMatte(src, temp1); + + ::erodilate_quarters(lx, ly, temp1->pixels(0), 1, lx, temp2->pixels(0), 1, + lx, radius, cseShift, MinFunc()); + ::erodilate_quarters(lx, ly, temp1->pixels(0) + lx - 1, -1, lx, + temp2->pixels(0) + lx - 1, -1, lx, radius, cseShift, + MinFunc()); + + if (row_filter_radius > 0.0) + for (int x = 0; x != lx; ++x) + ::erodilate_row(ly, &src->pixels(0)[x].m, 4 * src->getWrap(), + temp1->pixels(0) + x, lx, radI, radR, MinFunc()); + else + ::copyMatte(src, temp1); + + ::erodilate_quarters(ly, lx, temp1->pixels(0), lx, 1, temp2->pixels(0), lx, + 1, radius, cseShift, MinFunc()); + ::erodilate_quarters(ly, lx, temp1->pixels(0) + lx * ly - 1, -lx, -1, + temp2->pixels(0) + lx * ly - 1, -lx, -1, radius, + cseShift, MinFunc()); + } + + // Remember that we have just calculated the matte values. We still have to + // apply them to the old RGB + // values, which requires depremultiplying from source matte and + // premultiplying with the new one. + if (dilate) + ::copyChannels_dilate(src, temp2, dst); + else + ::copyChannels_erode(src, temp2, dst); } -} // namespace +} // namespace //******************************************************** // EroDilate main functions //******************************************************** -void TRop::erodilate(const TRasterP &src, const TRasterP &dst, - double radius, ErodilateMaskType type) -{ - assert(src->getSize() == dst->getSize()); - - src->lock(), dst->lock(); - - if ((TRaster32P)src && (TRaster32P)dst) - switch (type) { - case ED_rectangular: - ::rect_erodilate(src, dst, radius); - break; - case ED_circular: - ::circular_erodilate(src, dst, radius); - break; - default: - assert(!"Unknown mask type"); - break; - } - else if ((TRaster64P)src && (TRaster64P)dst) - switch (type) { - case ED_rectangular: - ::rect_erodilate(src, dst, radius); - break; - case ED_circular: - ::circular_erodilate(src, dst, radius); - break; - default: - assert(!"Unknown mask type"); - break; - } - else - assert(!"Unsupported raster type!"); - - src->unlock(), dst->unlock(); +void TRop::erodilate(const TRasterP &src, const TRasterP &dst, double radius, + ErodilateMaskType type) { + assert(src->getSize() == dst->getSize()); + + src->lock(), dst->lock(); + + if ((TRaster32P)src && (TRaster32P)dst) switch (type) { + case ED_rectangular: + ::rect_erodilate(src, dst, radius); + break; + case ED_circular: + ::circular_erodilate(src, dst, radius); + break; + default: + assert(!"Unknown mask type"); + break; + } + else if ((TRaster64P)src && (TRaster64P)dst) + switch (type) { + case ED_rectangular: + ::rect_erodilate(src, dst, radius); + break; + case ED_circular: + ::circular_erodilate(src, dst, radius); + break; + default: + assert(!"Unknown mask type"); + break; + } + else + assert(!"Unsupported raster type!"); + + src->unlock(), dst->unlock(); } diff --git a/toonz/sources/common/trop/tfracmove.cpp b/toonz/sources/common/trop/tfracmove.cpp index 06e2a80..85739f9 100644 --- a/toonz/sources/common/trop/tfracmove.cpp +++ b/toonz/sources/common/trop/tfracmove.cpp @@ -6,113 +6,105 @@ //------------------------------------------------------------------------------ -namespace -{ +namespace { -inline double gauss(double x, double y, double x0, double y0, double s) -{ - return exp(-((x - x0) * (x - x0) + (y - y0) * (y - y0)) / s) / (s * TConsts::pi); +inline double gauss(double x, double y, double x0, double y0, double s) { + return exp(-((x - x0) * (x - x0) + (y - y0) * (y - y0)) / s) / (s * M_PI); } //------------------------------------------------------------------------------ double integ_gauss(double xmin, double ymin, double xmax, double ymax, - double x0, double y0, double s) -{ - int i, j, n; - double x1, y1, x2, y2, xstep, ystep, area; - double sum; - n = 50; - sum = 0; - xstep = (xmax - xmin) / n; - ystep = (ymax - ymin) / n; - area = xstep * ystep; - for (i = 0; i < n; i++) - for (j = 0; j < n; j++) { - x1 = xmin + xstep * i; - y1 = ymin + ystep * i; - x2 = x1 + xstep; - y2 = y1 + ystep; - sum += area * (gauss(x1, y1, x0, y0, s) + - gauss(x1, y2, x0, y0, s) + - gauss(x2, y2, x0, y0, s) + - gauss(x2, y1, x0, y0, s)) / - 4; - } - return sum; + double x0, double y0, double s) { + int i, j, n; + double x1, y1, x2, y2, xstep, ystep, area; + double sum; + n = 50; + sum = 0; + xstep = (xmax - xmin) / n; + ystep = (ymax - ymin) / n; + area = xstep * ystep; + for (i = 0; i < n; i++) + for (j = 0; j < n; j++) { + x1 = xmin + xstep * i; + y1 = ymin + ystep * i; + x2 = x1 + xstep; + y2 = y1 + ystep; + sum += area * (gauss(x1, y1, x0, y0, s) + gauss(x1, y2, x0, y0, s) + + gauss(x2, y2, x0, y0, s) + gauss(x2, y1, x0, y0, s)) / + 4; + } + return sum; } //------------------------------------------------------------------------------ -void build_filter(double h[], double x0, double y0, double s) -{ - double sum, vv; - int i, j, k; - double x1, y1, x2, y2; - k = 0; - sum = 0.0; - for (i = 0; i < 3; i++) - for (j = 0; j < 3; j++) { - x1 = -1.5 + j; - y1 = -1.5 + i; - x2 = x1 + 1.0; - y2 = y1 + 1.0; - h[k++] = vv = integ_gauss(x1, y1, x2, y2, x0, y0, s); - sum += vv; - } - if (sum > 0.0) { - sum = 1.0 / sum; - for (k = 0; k < 9; k++) - h[k] *= sum; - } +void build_filter(double h[], double x0, double y0, double s) { + double sum, vv; + int i, j, k; + double x1, y1, x2, y2; + k = 0; + sum = 0.0; + for (i = 0; i < 3; i++) + for (j = 0; j < 3; j++) { + x1 = -1.5 + j; + y1 = -1.5 + i; + x2 = x1 + 1.0; + y2 = y1 + 1.0; + h[k++] = vv = integ_gauss(x1, y1, x2, y2, x0, y0, s); + sum += vv; + } + if (sum > 0.0) { + sum = 1.0 / sum; + for (k = 0; k < 9; k++) h[k] *= sum; + } } -} // anonymous namespace +} // anonymous namespace //------------------------------------------------------------------------------ -void TRop::fracmove(TRasterP rout, TRasterP rin, double dx, double dy) -{ - //Using a bilinear filter is best - consider that only 4 pixels should contribute - //to a fractionarily shifted one, with weights proportional to the intersection areas. - double w[4] = {1, 0, 0, 0}; - double sum = 0; +void TRop::fracmove(TRasterP rout, TRasterP rin, double dx, double dy) { + // Using a bilinear filter is best - consider that only 4 pixels should + // contribute + // to a fractionarily shifted one, with weights proportional to the + // intersection areas. + double w[4] = {1, 0, 0, 0}; + double sum = 0; - int idx = tfloor(dx); - int idy = tfloor(dy); - double fracX = dx - idx; - double fracY = dy - idy; + int idx = tfloor(dx); + int idy = tfloor(dy); + double fracX = dx - idx; + double fracY = dy - idy; - int i, j; - for (i = 0; i < 2; ++i) - for (j = 0; j < 2; ++j) - sum += w[j + 2 * i] = fabs(fracX - j) * fabs(fracY - i); + int i, j; + for (i = 0; i < 2; ++i) + for (j = 0; j < 2; ++j) + sum += w[j + 2 * i] = fabs(fracX - j) * fabs(fracY - i); - for (i = 0; i < 4; ++i) - w[i] /= sum; + for (i = 0; i < 4; ++i) w[i] /= sum; - TRop::convolve_i(rout, rin, idx, idy, w, 2); + TRop::convolve_i(rout, rin, idx, idy, w, 2); } //------------------------------------------------------------------------------ -void TRop::fracmove(TRasterP rout, TRasterCM32P rin, const TPaletteP &palette, double dx, double dy) -{ - double w[4] = {1, 0, 0, 0}; - double sum = 0; +void TRop::fracmove(TRasterP rout, TRasterCM32P rin, const TPaletteP &palette, + double dx, double dy) { + double w[4] = {1, 0, 0, 0}; + double sum = 0; - int idx = tfloor(dx); - int idy = tfloor(dy); - double fracX = dx - idx; - double fracY = dy - idy; + int idx = tfloor(dx); + int idy = tfloor(dy); + double fracX = dx - idx; + double fracY = dy - idy; - int i, j; - for (i = 0; i < 2; ++i) - for (j = 0; j < 2; ++j) - sum += w[j + 2 * i] = fabs(fracX - j) * fabs(fracY - i); + int i, j; + for (i = 0; i < 2; ++i) + for (j = 0; j < 2; ++j) + sum += w[j + 2 * i] = fabs(fracX - j) * fabs(fracY - i); - for (i = 0; i < 4; ++i) - w[i] /= sum; + for (i = 0; i < 4; ++i) w[i] /= sum; - TRop::convolve_i(rout, rin, idx, idy, w, 2); + TRop::convolve_i(rout, rin, idx, idy, w, 2); } diff --git a/toonz/sources/common/trop/tinvert.cpp b/toonz/sources/common/trop/tinvert.cpp index 14c3e22..0208a8b 100644 --- a/toonz/sources/common/trop/tinvert.cpp +++ b/toonz/sources/common/trop/tinvert.cpp @@ -3,119 +3,111 @@ #include "trop.h" #include "tpixelgr.h" -namespace -{ +namespace { template -inline void do_invert(TRasterPT ras) -{ - int wrap = ras->getWrap(); - int lx = ras->getLx(); - PixType *rowIn = ras->pixels(); - PixType *lastPix = rowIn + wrap * ras->getLy(); - PixType *pixIn = 0; - PixType *endPix = 0; +inline void do_invert(TRasterPT ras) { + int wrap = ras->getWrap(); + int lx = ras->getLx(); + PixType *rowIn = ras->pixels(); + PixType *lastPix = rowIn + wrap * ras->getLy(); + PixType *pixIn = 0; + PixType *endPix = 0; - while (pixIn < lastPix) { - pixIn = rowIn; - endPix = pixIn + lx; - while (pixIn < endPix) { - pixIn->r = pixIn->m - pixIn->r; - pixIn->g = pixIn->m - pixIn->g; - pixIn->b = pixIn->m - pixIn->b; /*pixIn->m = pixIn->m;*/ + while (pixIn < lastPix) { + pixIn = rowIn; + endPix = pixIn + lx; + while (pixIn < endPix) { + pixIn->r = pixIn->m - pixIn->r; + pixIn->g = pixIn->m - pixIn->g; + pixIn->b = pixIn->m - pixIn->b; /*pixIn->m = pixIn->m;*/ - ++pixIn; - } - rowIn += wrap; - } + ++pixIn; + } + rowIn += wrap; + } } //------------------------------------------------------------------------------ template -inline void do_invert(TRasterPT ras, bool invRed, bool invGreen, bool invBlue, bool invMatte) -{ - int wrap = ras->getWrap(); - int lx = ras->getLx(); - PixType *rowIn = ras->pixels(); - PixType *lastPix = rowIn + wrap * ras->getLy(); - PixType *pixIn = 0; - PixType *endPix = 0; +inline void do_invert(TRasterPT ras, bool invRed, bool invGreen, + bool invBlue, bool invMatte) { + int wrap = ras->getWrap(); + int lx = ras->getLx(); + PixType *rowIn = ras->pixels(); + PixType *lastPix = rowIn + wrap * ras->getLy(); + PixType *pixIn = 0; + PixType *endPix = 0; - while (pixIn < lastPix) { - pixIn = rowIn; - endPix = pixIn + lx; - while (pixIn < endPix) { - if (invRed) - pixIn->r = pixIn->m - pixIn->r; - if (invGreen) - pixIn->g = pixIn->m - pixIn->g; - if (invBlue) - pixIn->b = pixIn->m - pixIn->b; - if (invMatte) - pixIn->m = ~pixIn->m; - ++pixIn; - } - rowIn += wrap; - } + while (pixIn < lastPix) { + pixIn = rowIn; + endPix = pixIn + lx; + while (pixIn < endPix) { + if (invRed) pixIn->r = pixIn->m - pixIn->r; + if (invGreen) pixIn->g = pixIn->m - pixIn->g; + if (invBlue) pixIn->b = pixIn->m - pixIn->b; + if (invMatte) pixIn->m = ~pixIn->m; + ++pixIn; + } + rowIn += wrap; + } } //------------------------------------------------------------------------------ template <> -inline void do_invert(TRasterPT ras) -{ - int wrap = ras->getWrap(); - int lx = ras->getLx(); - TPixelGR8 *rowIn = ras->pixels(); - TPixelGR8 *lastPix = rowIn + wrap * ras->getLy(); - TPixelGR8 *pixIn = 0; - TPixelGR8 *endPix = 0; +inline void do_invert(TRasterPT ras) { + int wrap = ras->getWrap(); + int lx = ras->getLx(); + TPixelGR8 *rowIn = ras->pixels(); + TPixelGR8 *lastPix = rowIn + wrap * ras->getLy(); + TPixelGR8 *pixIn = 0; + TPixelGR8 *endPix = 0; - while (pixIn < lastPix) { - pixIn = rowIn; - endPix = pixIn + lx; - while (pixIn < endPix) { - pixIn->value = 255 - pixIn->value; + while (pixIn < lastPix) { + pixIn = rowIn; + endPix = pixIn + lx; + while (pixIn < endPix) { + pixIn->value = 255 - pixIn->value; - ++pixIn; - } - rowIn += wrap; - } + ++pixIn; + } + rowIn += wrap; + } } } //------------------------------------------------------------------------------ -void TRop::invert(TRasterP ras, bool invRed, bool invGreen, bool invBlue, bool invMatte) -{ - if (!invRed && !invGreen && !invBlue) - return; - bool flag = invRed && invGreen && invBlue && !invMatte; +void TRop::invert(TRasterP ras, bool invRed, bool invGreen, bool invBlue, + bool invMatte) { + if (!invRed && !invGreen && !invBlue) return; + bool flag = invRed && invGreen && invBlue && !invMatte; - TRaster32P ras32 = ras; - ras->lock(); - if (ras32) - if (flag) - do_invert(ras32); - else - do_invert(ras, invRed, invGreen, invBlue, invMatte); - else { - TRaster64P ras64 = ras; - if (ras64) - if (flag) - do_invert(ras64); - else - do_invert(ras64, invRed, invGreen, invBlue, invMatte); - else { - TRasterGR8P ras8 = ras; - if (ras8) - do_invert(ras8); - else { - ras->unlock(); - throw TRopException("unsupported pixel type"); - } - } - } - ras->unlock(); + TRaster32P ras32 = ras; + ras->lock(); + if (ras32) + if (flag) + do_invert(ras32); + else + do_invert(ras, invRed, invGreen, invBlue, invMatte); + else { + TRaster64P ras64 = ras; + if (ras64) + if (flag) + do_invert(ras64); + else + do_invert(ras64, invRed, invGreen, invBlue, invMatte); + else { + TRasterGR8P ras8 = ras; + if (ras8) + do_invert(ras8); + else { + ras->unlock(); + throw TRopException("unsupported pixel type"); + } + } + } + ras->unlock(); } //------------------------------------------------------------------------------ diff --git a/toonz/sources/common/trop/toperators.cpp b/toonz/sources/common/trop/toperators.cpp index 384843c..76f47f8 100644 --- a/toonz/sources/common/trop/toperators.cpp +++ b/toonz/sources/common/trop/toperators.cpp @@ -5,1588 +5,1636 @@ #include "tpixelutils.h" #ifdef _WIN32 -#include // per SSE2 +#include // per SSE2 #endif -namespace -{ -inline double luminance(TPixel32 *pix) -{ - return 0.2126 * pix->r + 0.7152 * pix->g + 0.0722 * pix->b; +namespace { +inline double luminance(TPixel32 *pix) { + return 0.2126 * pix->r + 0.7152 * pix->g + 0.0722 * pix->b; } -inline double luminance(TPixel64 *pix) -{ - return 0.2126 * pix->r + 0.7152 * pix->g + 0.0722 * pix->b; +inline double luminance(TPixel64 *pix) { + return 0.2126 * pix->r + 0.7152 * pix->g + 0.0722 * pix->b; } -} //namespace +} // namespace //----------------------------------------------------------------------------- -#define FOR_EACH_PIXEL_BEGIN_LOOP(UpType, up, DownType, down, OutType, out) \ - { \ - int upWrap = up->getWrap(); \ - int downWrap = down->getWrap(); \ - int outWrap = out->getWrap(); \ - \ - up->lock(); \ - down->lock(); \ - out->lock(); \ - UpType *upPix = 0, *upRow = up->pixels(); \ - DownType *downPix, *downRow = down->pixels(); \ - OutType *outPix, *outRow = out->pixels(); \ - UpType *endPix; \ - int upLx = up->getLx(); \ - UpType *lastPix = upRow + upWrap * (up->getLy() - 1) + upLx; \ - while (upPix < lastPix) { \ - upPix = upRow; \ - downPix = downRow; \ - outPix = outRow; \ - endPix = upPix + upLx; \ - while (upPix < endPix) { - +#define FOR_EACH_PIXEL_BEGIN_LOOP(UpType, up, DownType, down, OutType, out) \ + { \ + int upWrap = up->getWrap(); \ + int downWrap = down->getWrap(); \ + int outWrap = out->getWrap(); \ + \ + up->lock(); \ + down->lock(); \ + out->lock(); \ + UpType *upPix = 0, *upRow = up->pixels(); \ + DownType *downPix, *downRow = down->pixels(); \ + OutType *outPix, *outRow = out->pixels(); \ + UpType *endPix; \ + int upLx = up->getLx(); \ + UpType *lastPix = upRow + upWrap * (up->getLy() - 1) + upLx; \ + while (upPix < lastPix) { \ + upPix = upRow; \ + downPix = downRow; \ + outPix = outRow; \ + endPix = upPix + upLx; \ + while (upPix < endPix) { //----------------------------------------------------------------------------- -#define FOR_EACH_PIXEL_END_LOOP(up, down, out) \ - ++upPix; \ - ++downPix; \ - ++outPix; \ - } \ - upRow += upWrap; \ - downRow += downWrap; \ - outRow += outWrap; \ - } \ - up->unlock(); \ - down->unlock(); \ - out->unlock(); \ - } +#define FOR_EACH_PIXEL_END_LOOP(up, down, out) \ + ++upPix; \ + ++downPix; \ + ++outPix; \ + } \ + upRow += upWrap; \ + downRow += downWrap; \ + outRow += outWrap; \ + } \ + up->unlock(); \ + down->unlock(); \ + out->unlock(); \ + } //----------------------------------------------------------------------------- -#define FOR_EACH_PIXEL_32_BEGIN_LOOP \ - assert(up32 &&down32 &&out32); \ - FOR_EACH_PIXEL_BEGIN_LOOP(TPixelRGBM32, up32, TPixelRGBM32, down32, TPixelRGBM32, out32) +#define FOR_EACH_PIXEL_32_BEGIN_LOOP \ + assert(up32 &&down32 &&out32); \ + FOR_EACH_PIXEL_BEGIN_LOOP(TPixelRGBM32, up32, TPixelRGBM32, down32, \ + TPixelRGBM32, out32) //----------------------------------------------------------------------------- -#define FOR_EACH_PIXEL_32_END_LOOP \ - assert(up32 &&down32 &&out32); \ - FOR_EACH_PIXEL_END_LOOP(up32, down32, out32) +#define FOR_EACH_PIXEL_32_END_LOOP \ + assert(up32 &&down32 &&out32); \ + FOR_EACH_PIXEL_END_LOOP(up32, down32, out32) //----------------------------------------------------------------------------- -#define FOR_EACH_PIXEL_64_BEGIN_LOOP \ - assert(up64 &&down64 &&out64); \ - FOR_EACH_PIXEL_BEGIN_LOOP(TPixelRGBM64, up64, TPixelRGBM64, down64, TPixelRGBM64, out64) +#define FOR_EACH_PIXEL_64_BEGIN_LOOP \ + assert(up64 &&down64 &&out64); \ + FOR_EACH_PIXEL_BEGIN_LOOP(TPixelRGBM64, up64, TPixelRGBM64, down64, \ + TPixelRGBM64, out64) //----------------------------------------------------------------------------- -#define FOR_EACH_PIXEL_64_END_LOOP \ - assert(up64 &&down64 &&out64); \ - FOR_EACH_PIXEL_END_LOOP(up64, down64, out64) +#define FOR_EACH_PIXEL_64_END_LOOP \ + assert(up64 &&down64 &&out64); \ + FOR_EACH_PIXEL_END_LOOP(up64, down64, out64) //----------------------------------------------------------------------------- -#define FOR_EACH_PIXEL_8_BEGIN_LOOP \ - assert(up8 &&down8 &&out8); \ - FOR_EACH_PIXEL_BEGIN_LOOP(TPixelGR8, up8, TPixelGR8, down8, TPixelGR8, out8) +#define FOR_EACH_PIXEL_8_BEGIN_LOOP \ + assert(up8 &&down8 &&out8); \ + FOR_EACH_PIXEL_BEGIN_LOOP(TPixelGR8, up8, TPixelGR8, down8, TPixelGR8, out8) //----------------------------------------------------------------------------- -#define FOR_EACH_PIXEL_8_END_LOOP \ - assert(up8 &&down8 &&out8); \ - FOR_EACH_PIXEL_END_LOOP(up32, down32, out32) +#define FOR_EACH_PIXEL_8_END_LOOP \ + assert(up8 &&down8 &&out8); \ + FOR_EACH_PIXEL_END_LOOP(up32, down32, out32) //----------------------------------------------------------------------------- -void TRop::add(const TRasterP &rup, const TRasterP &rdown, const TRasterP &rout, double v) -{ - TRaster32P up32 = rup; - TRaster32P down32 = rdown; - TRaster32P out32 = rout; - - if (up32 && down32 && out32) { - FOR_EACH_PIXEL_32_BEGIN_LOOP - - TINT32 r, g, b, m; - if (upPix->m == 0) - *outPix = *downPix; - else { - r = downPix->r + tround(upPix->r * v); - g = downPix->g + tround(upPix->g * v); - b = downPix->b + tround(upPix->b * v); - m = downPix->m + tround(upPix->m * v); - outPix->r = (UCHAR)tcrop(r, (TINT32)0, (TINT32)255); - outPix->g = (UCHAR)tcrop(g, (TINT32)0, (TINT32)255); - outPix->b = (UCHAR)tcrop(b, (TINT32)0, (TINT32)255); - outPix->m = (UCHAR)tcrop(m, (TINT32)0, (TINT32)255); - } - - FOR_EACH_PIXEL_32_END_LOOP - } else { - TRaster64P up64 = rup; - TRaster64P down64 = rdown; - TRaster64P out64 = rout; - - if (up64 && down64 && out64) { - FOR_EACH_PIXEL_64_BEGIN_LOOP - - TINT32 r, g, b, m; - r = downPix->r + tround(upPix->r * v); - g = downPix->g + tround(upPix->g * v); - b = downPix->b + tround(upPix->b * v); - m = downPix->m + tround(upPix->m * v); - - outPix->r = (USHORT)tcrop(r, 0, 0xffff); - outPix->g = (USHORT)tcrop(g, 0, 0xffff); - outPix->b = (USHORT)tcrop(b, 0, 0xffff); - outPix->m = (USHORT)tcrop(m, 0, 0xffff); - - FOR_EACH_PIXEL_64_END_LOOP - } else { - TRasterGR8P up8 = rup; - TRasterGR8P down8 = rdown; - TRasterGR8P out8 = rout; - - if (up8 && down8 && out8) { - FOR_EACH_PIXEL_8_BEGIN_LOOP - - USHORT value = troundp(upPix->value * v) + downPix->value; - - outPix->value = (UCHAR)tcrop(value, 0, 255); - - FOR_EACH_PIXEL_8_END_LOOP - } else - throw TRopException("TRop::add invalid raster combination"); - } - } +void TRop::add(const TRasterP &rup, const TRasterP &rdown, const TRasterP &rout, + double v) { + TRaster32P up32 = rup; + TRaster32P down32 = rdown; + TRaster32P out32 = rout; + + if (up32 && down32 && out32) { + FOR_EACH_PIXEL_32_BEGIN_LOOP + + TINT32 r, g, b, m; + if (upPix->m == 0) + *outPix = *downPix; + else { + r = downPix->r + tround(upPix->r * v); + g = downPix->g + tround(upPix->g * v); + b = downPix->b + tround(upPix->b * v); + m = downPix->m + tround(upPix->m * v); + outPix->r = (UCHAR)tcrop(r, (TINT32)0, (TINT32)255); + outPix->g = (UCHAR)tcrop(g, (TINT32)0, (TINT32)255); + outPix->b = (UCHAR)tcrop(b, (TINT32)0, (TINT32)255); + outPix->m = (UCHAR)tcrop(m, (TINT32)0, (TINT32)255); + } + + FOR_EACH_PIXEL_32_END_LOOP + } else { + TRaster64P up64 = rup; + TRaster64P down64 = rdown; + TRaster64P out64 = rout; + + if (up64 && down64 && out64) { + FOR_EACH_PIXEL_64_BEGIN_LOOP + + TINT32 r, g, b, m; + r = downPix->r + tround(upPix->r * v); + g = downPix->g + tround(upPix->g * v); + b = downPix->b + tround(upPix->b * v); + m = downPix->m + tround(upPix->m * v); + + outPix->r = (USHORT)tcrop(r, 0, 0xffff); + outPix->g = (USHORT)tcrop(g, 0, 0xffff); + outPix->b = (USHORT)tcrop(b, 0, 0xffff); + outPix->m = (USHORT)tcrop(m, 0, 0xffff); + + FOR_EACH_PIXEL_64_END_LOOP + } else { + TRasterGR8P up8 = rup; + TRasterGR8P down8 = rdown; + TRasterGR8P out8 = rout; + + if (up8 && down8 && out8) { + FOR_EACH_PIXEL_8_BEGIN_LOOP + + USHORT value = troundp(upPix->value * v) + downPix->value; + + outPix->value = (UCHAR)tcrop(value, 0, 255); + + FOR_EACH_PIXEL_8_END_LOOP + } else + throw TRopException("TRop::add invalid raster combination"); + } + } } //----------------------------------------------------------------------------- -void TRop::add(const TRasterP &rup, const TRasterP &rdown, const TRasterP &rout) -{ - TRaster32P up32 = rup; - TRaster32P down32 = rdown; - TRaster32P out32 = rout; - - if (up32 && down32 && out32) { - FOR_EACH_PIXEL_32_BEGIN_LOOP - - USHORT r, g, b, m; - r = downPix->r + upPix->r; - g = downPix->g + upPix->g; - b = downPix->b + upPix->b; - m = downPix->m + upPix->m; - - outPix->r = (UCHAR)tcrop(r, 0, 255); - outPix->g = (UCHAR)tcrop(g, 0, 255); - outPix->b = (UCHAR)tcrop(b, 0, 255); - outPix->m = (UCHAR)tcrop(m, 0, 255); - - FOR_EACH_PIXEL_32_END_LOOP - } else { - TRaster64P up64 = rup; - TRaster64P down64 = rdown; - TRaster64P out64 = rout; - - if (up64 && down64 && out64) { - FOR_EACH_PIXEL_64_BEGIN_LOOP - - TINT32 r, g, b, m; - r = downPix->r + upPix->r; - g = downPix->g + upPix->g; - b = downPix->b + upPix->b; - m = downPix->m + upPix->m; - - outPix->r = (USHORT)tcrop(r, 0, 0xffff); - outPix->g = (USHORT)tcrop(g, 0, 0xffff); - outPix->b = (USHORT)tcrop(b, 0, 0xffff); - outPix->m = (USHORT)tcrop(m, 0, 0xffff); - - FOR_EACH_PIXEL_64_END_LOOP - } else { - TRasterGR8P up8 = rup; - TRasterGR8P down8 = rdown; - TRasterGR8P out8 = rout; - - if (up8 && down8 && out8) { - FOR_EACH_PIXEL_8_BEGIN_LOOP - - USHORT value = upPix->value + downPix->value; - - outPix->value = (UCHAR)tcrop(value, 0, 255); - - FOR_EACH_PIXEL_8_END_LOOP - } else - throw TRopException("TRop::add invalid raster combination"); - } - } +void TRop::add(const TRasterP &rup, const TRasterP &rdown, + const TRasterP &rout) { + TRaster32P up32 = rup; + TRaster32P down32 = rdown; + TRaster32P out32 = rout; + + if (up32 && down32 && out32) { + FOR_EACH_PIXEL_32_BEGIN_LOOP + + USHORT r, g, b, m; + r = downPix->r + upPix->r; + g = downPix->g + upPix->g; + b = downPix->b + upPix->b; + m = downPix->m + upPix->m; + + outPix->r = (UCHAR)tcrop(r, 0, 255); + outPix->g = (UCHAR)tcrop(g, 0, 255); + outPix->b = (UCHAR)tcrop(b, 0, 255); + outPix->m = (UCHAR)tcrop(m, 0, 255); + + FOR_EACH_PIXEL_32_END_LOOP + } else { + TRaster64P up64 = rup; + TRaster64P down64 = rdown; + TRaster64P out64 = rout; + + if (up64 && down64 && out64) { + FOR_EACH_PIXEL_64_BEGIN_LOOP + + TINT32 r, g, b, m; + r = downPix->r + upPix->r; + g = downPix->g + upPix->g; + b = downPix->b + upPix->b; + m = downPix->m + upPix->m; + + outPix->r = (USHORT)tcrop(r, 0, 0xffff); + outPix->g = (USHORT)tcrop(g, 0, 0xffff); + outPix->b = (USHORT)tcrop(b, 0, 0xffff); + outPix->m = (USHORT)tcrop(m, 0, 0xffff); + + FOR_EACH_PIXEL_64_END_LOOP + } else { + TRasterGR8P up8 = rup; + TRasterGR8P down8 = rdown; + TRasterGR8P out8 = rout; + + if (up8 && down8 && out8) { + FOR_EACH_PIXEL_8_BEGIN_LOOP + + USHORT value = upPix->value + downPix->value; + + outPix->value = (UCHAR)tcrop(value, 0, 255); + + FOR_EACH_PIXEL_8_END_LOOP + } else + throw TRopException("TRop::add invalid raster combination"); + } + } } //----------------------------------------------------------------------------- -void TRop::colordodge(const TRasterP &rup, const TRasterP &rdown, const TRasterP &rout) -{ - TRaster32P up32 = rup; - TRaster32P down32 = rdown; - TRaster32P out32 = rout; - if (up32 && down32 && out32) { - - FOR_EACH_PIXEL_32_BEGIN_LOOP +void TRop::colordodge(const TRasterP &rup, const TRasterP &rdown, + const TRasterP &rout) { + TRaster32P up32 = rup; + TRaster32P down32 = rdown; + TRaster32P out32 = rout; + if (up32 && down32 && out32) { + FOR_EACH_PIXEL_32_BEGIN_LOOP - USHORT r, g, b, m; + USHORT r, g, b, m; - r = (USHORT)((downPix->r << 8) / (256.0 - upPix->r)); - g = (USHORT)((downPix->g << 8) / (256.0 - upPix->g)); - b = (USHORT)((downPix->b << 8) / (256.0 - upPix->b)); + r = (USHORT)((downPix->r << 8) / (256.0 - upPix->r)); + g = (USHORT)((downPix->g << 8) / (256.0 - upPix->g)); + b = (USHORT)((downPix->b << 8) / (256.0 - upPix->b)); - m = downPix->m + upPix->m; + m = downPix->m + upPix->m; - outPix->r = (UCHAR)tcrop(r, 0, 255); - outPix->g = (UCHAR)tcrop(g, 0, 255); - outPix->b = (UCHAR)tcrop(b, 0, 255); - outPix->m = (UCHAR)tcrop(m, 0, 255); + outPix->r = (UCHAR)tcrop(r, 0, 255); + outPix->g = (UCHAR)tcrop(g, 0, 255); + outPix->b = (UCHAR)tcrop(b, 0, 255); + outPix->m = (UCHAR)tcrop(m, 0, 255); - FOR_EACH_PIXEL_32_END_LOOP - } else { - TRaster64P up64 = rup; - TRaster64P down64 = rdown; - TRaster64P out64 = rout; + FOR_EACH_PIXEL_32_END_LOOP + } else { + TRaster64P up64 = rup; + TRaster64P down64 = rdown; + TRaster64P out64 = rout; - if (up64 && down64 && out64) { - FOR_EACH_PIXEL_64_BEGIN_LOOP + if (up64 && down64 && out64) { + FOR_EACH_PIXEL_64_BEGIN_LOOP - TINT32 r, g, b, m; - r = (TINT32)(65536.0 * (downPix->r / (65536.0 - upPix->r))); + TINT32 r, g, b, m; + r = (TINT32)(65536.0 * (downPix->r / (65536.0 - upPix->r))); - g = (TINT32)(65536.0 * (downPix->g / (65536.0 - upPix->g))); + g = (TINT32)(65536.0 * (downPix->g / (65536.0 - upPix->g))); - b = (TINT32)(65536.0 * (downPix->b / (65536.0 - upPix->b))); + b = (TINT32)(65536.0 * (downPix->b / (65536.0 - upPix->b))); - m = downPix->m + upPix->m; + m = downPix->m + upPix->m; - outPix->r = (USHORT)tcrop(r, 0, 0xffff); - outPix->g = (USHORT)tcrop(g, 0, 0xffff); - outPix->b = (USHORT)tcrop(b, 0, 0xffff); - outPix->m = (USHORT)tcrop(m, 0, 0xffff); + outPix->r = (USHORT)tcrop(r, 0, 0xffff); + outPix->g = (USHORT)tcrop(g, 0, 0xffff); + outPix->b = (USHORT)tcrop(b, 0, 0xffff); + outPix->m = (USHORT)tcrop(m, 0, 0xffff); - FOR_EACH_PIXEL_64_END_LOOP - } else { - TRasterGR8P up8 = rup; - TRasterGR8P down8 = rdown; - TRasterGR8P out8 = rout; + FOR_EACH_PIXEL_64_END_LOOP + } else { + TRasterGR8P up8 = rup; + TRasterGR8P down8 = rdown; + TRasterGR8P out8 = rout; - if (up8 && down8 && out8) { - FOR_EACH_PIXEL_8_BEGIN_LOOP - USHORT value; - if (downPix->value) - value = (USHORT)((downPix->value << 8) / (255.0 - upPix->value)); + if (up8 && down8 && out8) { + FOR_EACH_PIXEL_8_BEGIN_LOOP + USHORT value; + if (downPix->value) + value = (USHORT)((downPix->value << 8) / (255.0 - upPix->value)); - outPix->value = (UCHAR)tcrop(value, 0, 255); + outPix->value = (UCHAR)tcrop(value, 0, 255); - FOR_EACH_PIXEL_8_END_LOOP - } else - throw TRopException("TRop::color dodge invalid raster combination"); - } - } + FOR_EACH_PIXEL_8_END_LOOP + } else + throw TRopException("TRop::color dodge invalid raster combination"); + } + } } //----------------------------------------------------------------------------- -void TRop::colorburn(const TRasterP &rup, const TRasterP &rdown, const TRasterP &rout) -{ - TRaster32P up32 = rup; - TRaster32P down32 = rdown; - TRaster32P out32 = rout; - if (up32 && down32 && out32) { - - FOR_EACH_PIXEL_32_BEGIN_LOOP - // downPix->r=0; - // downPix->g=255; - // downPix->b=0; - double r, g, b; - if (upPix->m) { - if (downPix->r == 0 || downPix->r == 255) - r = downPix->r; - else if (upPix->r) - r = 255 - (((255 - downPix->r) << 8) / (double)upPix->r); - else - r = 0; - if (downPix->g == 0 || downPix->g == 255) - g = downPix->g; - else if (upPix->g) - g = 255 - (((255 - downPix->g) << 8) / (double)upPix->g); - else - g = 0; - if (downPix->b == 0 || downPix->b == 255) - b = downPix->b; - else if (upPix->b) - b = 255 - (((255 - downPix->b) << 8) / (double)upPix->b); - else - b = 0; - - if (upPix->m != 255) { - - TPixel32 tmpPix; - tmpPix.r = (UCHAR)tcrop(r, .0, 255.0); - tmpPix.g = (UCHAR)tcrop(g, .0, 255.0); - tmpPix.b = (UCHAR)tcrop(b, .0, 255.0); - tmpPix.m = upPix->m; - ; - overPix(*outPix, *downPix, tmpPix); - } else { - outPix->r = (UCHAR)tcrop(r, .0, 255.0); - outPix->g = (UCHAR)tcrop(g, .0, 255.0); - outPix->b = (UCHAR)tcrop(b, .0, 255.0); - outPix->m = downPix->m; - } - } else { - outPix = downPix; - } - FOR_EACH_PIXEL_32_END_LOOP - } else { - TRaster64P up64 = rup; - TRaster64P down64 = rdown; - TRaster64P out64 = rout; - - if (up64 && down64 && out64) { - FOR_EACH_PIXEL_64_BEGIN_LOOP - double r, g, b; - if (upPix->m) { - if (downPix->r == 0 || downPix->r == 65535) - r = downPix->r; - else if (upPix->r) - r = 65535 - 65536 * ((65535.0 - downPix->r) / (double)upPix->r); - else - r = 0; - if (downPix->g == 0 || downPix->g == 65535) - g = downPix->g; - else if (upPix->g) - g = 65535 - 65536 * ((65535.0 - downPix->g) / (double)upPix->g); - else - g = 0; - if (downPix->b == 0 || downPix->b == 65535) - b = downPix->b; - else if (upPix->b) - b = 65535 - 65536 * ((65535.0 - downPix->b) / (double)upPix->b); - else - b = 0; - - if (upPix->m != 65535) { - - TPixel64 tmpPix; - tmpPix.r = (USHORT)tcrop(r, .0, 65535.0); - tmpPix.g = (USHORT)tcrop(g, .0, 65535.0); - tmpPix.b = (USHORT)tcrop(b, .0, 65535.0); - tmpPix.m = upPix->m; - overPix(*outPix, *downPix, tmpPix); - } else { - outPix->r = (USHORT)tcrop(r, .0, 65535.0); - outPix->g = (USHORT)tcrop(g, .0, 65535.0); - outPix->b = (USHORT)tcrop(b, .0, 65535.0); - outPix->m = downPix->m; - } - } else { - outPix = downPix; - } - FOR_EACH_PIXEL_64_END_LOOP - } else - throw TRopException("TRop::color burn invalid raster combination"); - } +void TRop::colorburn(const TRasterP &rup, const TRasterP &rdown, + const TRasterP &rout) { + TRaster32P up32 = rup; + TRaster32P down32 = rdown; + TRaster32P out32 = rout; + if (up32 && down32 && out32) { + FOR_EACH_PIXEL_32_BEGIN_LOOP + // downPix->r=0; + // downPix->g=255; + // downPix->b=0; + double r, g, b; + if (upPix->m) { + if (downPix->r == 0 || downPix->r == 255) + r = downPix->r; + else if (upPix->r) + r = 255 - (((255 - downPix->r) << 8) / (double)upPix->r); + else + r = 0; + if (downPix->g == 0 || downPix->g == 255) + g = downPix->g; + else if (upPix->g) + g = 255 - (((255 - downPix->g) << 8) / (double)upPix->g); + else + g = 0; + if (downPix->b == 0 || downPix->b == 255) + b = downPix->b; + else if (upPix->b) + b = 255 - (((255 - downPix->b) << 8) / (double)upPix->b); + else + b = 0; + + if (upPix->m != 255) { + TPixel32 tmpPix; + tmpPix.r = (UCHAR)tcrop(r, .0, 255.0); + tmpPix.g = (UCHAR)tcrop(g, .0, 255.0); + tmpPix.b = (UCHAR)tcrop(b, .0, 255.0); + tmpPix.m = upPix->m; + ; + overPix(*outPix, *downPix, tmpPix); + } else { + outPix->r = (UCHAR)tcrop(r, .0, 255.0); + outPix->g = (UCHAR)tcrop(g, .0, 255.0); + outPix->b = (UCHAR)tcrop(b, .0, 255.0); + outPix->m = downPix->m; + } + } else { + outPix = downPix; + } + FOR_EACH_PIXEL_32_END_LOOP + } else { + TRaster64P up64 = rup; + TRaster64P down64 = rdown; + TRaster64P out64 = rout; + + if (up64 && down64 && out64) { + FOR_EACH_PIXEL_64_BEGIN_LOOP + double r, g, b; + if (upPix->m) { + if (downPix->r == 0 || downPix->r == 65535) + r = downPix->r; + else if (upPix->r) + r = 65535 - 65536 * ((65535.0 - downPix->r) / (double)upPix->r); + else + r = 0; + if (downPix->g == 0 || downPix->g == 65535) + g = downPix->g; + else if (upPix->g) + g = 65535 - 65536 * ((65535.0 - downPix->g) / (double)upPix->g); + else + g = 0; + if (downPix->b == 0 || downPix->b == 65535) + b = downPix->b; + else if (upPix->b) + b = 65535 - 65536 * ((65535.0 - downPix->b) / (double)upPix->b); + else + b = 0; + + if (upPix->m != 65535) { + TPixel64 tmpPix; + tmpPix.r = (USHORT)tcrop(r, .0, 65535.0); + tmpPix.g = (USHORT)tcrop(g, .0, 65535.0); + tmpPix.b = (USHORT)tcrop(b, .0, 65535.0); + tmpPix.m = upPix->m; + overPix(*outPix, *downPix, tmpPix); + } else { + outPix->r = (USHORT)tcrop(r, .0, 65535.0); + outPix->g = (USHORT)tcrop(g, .0, 65535.0); + outPix->b = (USHORT)tcrop(b, .0, 65535.0); + outPix->m = downPix->m; + } + } else { + outPix = downPix; + } + FOR_EACH_PIXEL_64_END_LOOP + } else + throw TRopException("TRop::color burn invalid raster combination"); + } } //----------------------------------------------------------------------------- -void TRop::screen(const TRasterP &rup, const TRasterP &rdown, const TRasterP &rout) -{ - TRaster32P up32 = rup; - TRaster32P down32 = rdown; - TRaster32P out32 = rout; - if (up32 && down32 && out32) { - - FOR_EACH_PIXEL_32_BEGIN_LOOP - - double r, g, b; - r = 256 - ((256 - upPix->r) * (256 - downPix->r) >> 8); - g = 256 - ((256 - upPix->g) * (256 - downPix->g) >> 8); - b = 256 - ((256 - upPix->b) * (256 - downPix->b) >> 8); - - if (upPix->m != 255) { - double m; - m = 256 - ((256 - upPix->m) * (256 - downPix->m) >> 8); - TPixel32 tmpPix; - tmpPix.r = (UCHAR)tcrop(r, 0, 255); - tmpPix.g = (UCHAR)tcrop(g, 0, 255); - tmpPix.b = (UCHAR)tcrop(b, 0, 255); - tmpPix.m = (UCHAR)tcrop(m, 0, 255); - overPix(*outPix, *downPix, tmpPix); - } else { - - outPix->r = (UCHAR)tcrop(r, 0, 255); - outPix->g = (UCHAR)tcrop(g, 0, 255); - outPix->b = (UCHAR)tcrop(b, 0, 255); - outPix->m = upPix->m; - } - FOR_EACH_PIXEL_32_END_LOOP - } else { - TRaster64P up64 = rup; - TRaster64P down64 = rdown; - TRaster64P out64 = rout; - - if (up64 && down64 && out64) { - FOR_EACH_PIXEL_64_BEGIN_LOOP - - double r, g, b; - r = 65536 - (65536 - upPix->r) * ((65536 - downPix->r) / 65536.0); - g = 65536 - (65536 - upPix->g) * ((65536 - downPix->g) / 65536.0); - b = 65536 - (65536 - upPix->b) * ((65536 - downPix->b) / 65536.0); - - if (upPix->m != 65535) { - double m; - m = 65536 - (65536 - upPix->m) * ((65536 - downPix->m) / 65536.0); - TPixel64 tmpPix; - tmpPix.r = (USHORT)tcrop(r, 0, 65535); - tmpPix.g = (USHORT)tcrop(g, 0, 65535); - tmpPix.b = (USHORT)tcrop(b, 0, 65535); - tmpPix.m = (USHORT)tcrop(m, 0, 65535); - overPix(*outPix, *downPix, tmpPix); - } else { - - outPix->r = (USHORT)tcrop(r, 0, 65535); - outPix->g = (USHORT)tcrop(g, 0, 65535); - outPix->b = (USHORT)tcrop(b, 0, 65535); - outPix->m = upPix->m; - } - - FOR_EACH_PIXEL_64_END_LOOP - } else { - TRasterGR8P up8 = rup; - TRasterGR8P down8 = rdown; - TRasterGR8P out8 = rout; - - if (up8 && down8 && out8) { - FOR_EACH_PIXEL_8_BEGIN_LOOP - USHORT value; - if (downPix->value) - value = (USHORT)((downPix->value << 8) / (255.0 - upPix->value)); - - outPix->value = (UCHAR)tcrop(value, 0, 255); - - FOR_EACH_PIXEL_8_END_LOOP - } else - throw TRopException("TRop::color dodge invalid raster combination"); - } - } +void TRop::screen(const TRasterP &rup, const TRasterP &rdown, + const TRasterP &rout) { + TRaster32P up32 = rup; + TRaster32P down32 = rdown; + TRaster32P out32 = rout; + if (up32 && down32 && out32) { + FOR_EACH_PIXEL_32_BEGIN_LOOP + + double r, g, b; + r = 256 - ((256 - upPix->r) * (256 - downPix->r) >> 8); + g = 256 - ((256 - upPix->g) * (256 - downPix->g) >> 8); + b = 256 - ((256 - upPix->b) * (256 - downPix->b) >> 8); + + if (upPix->m != 255) { + double m; + m = 256 - ((256 - upPix->m) * (256 - downPix->m) >> 8); + TPixel32 tmpPix; + tmpPix.r = (UCHAR)tcrop(r, 0, 255); + tmpPix.g = (UCHAR)tcrop(g, 0, 255); + tmpPix.b = (UCHAR)tcrop(b, 0, 255); + tmpPix.m = (UCHAR)tcrop(m, 0, 255); + overPix(*outPix, *downPix, tmpPix); + } else { + outPix->r = (UCHAR)tcrop(r, 0, 255); + outPix->g = (UCHAR)tcrop(g, 0, 255); + outPix->b = (UCHAR)tcrop(b, 0, 255); + outPix->m = upPix->m; + } + FOR_EACH_PIXEL_32_END_LOOP + } else { + TRaster64P up64 = rup; + TRaster64P down64 = rdown; + TRaster64P out64 = rout; + + if (up64 && down64 && out64) { + FOR_EACH_PIXEL_64_BEGIN_LOOP + + double r, g, b; + r = 65536 - (65536 - upPix->r) * ((65536 - downPix->r) / 65536.0); + g = 65536 - (65536 - upPix->g) * ((65536 - downPix->g) / 65536.0); + b = 65536 - (65536 - upPix->b) * ((65536 - downPix->b) / 65536.0); + + if (upPix->m != 65535) { + double m; + m = 65536 - (65536 - upPix->m) * ((65536 - downPix->m) / 65536.0); + TPixel64 tmpPix; + tmpPix.r = (USHORT)tcrop(r, 0, 65535); + tmpPix.g = (USHORT)tcrop(g, 0, 65535); + tmpPix.b = (USHORT)tcrop(b, 0, 65535); + tmpPix.m = (USHORT)tcrop(m, 0, 65535); + overPix(*outPix, *downPix, tmpPix); + } else { + outPix->r = (USHORT)tcrop(r, 0, 65535); + outPix->g = (USHORT)tcrop(g, 0, 65535); + outPix->b = (USHORT)tcrop(b, 0, 65535); + outPix->m = upPix->m; + } + + FOR_EACH_PIXEL_64_END_LOOP + } else { + TRasterGR8P up8 = rup; + TRasterGR8P down8 = rdown; + TRasterGR8P out8 = rout; + + if (up8 && down8 && out8) { + FOR_EACH_PIXEL_8_BEGIN_LOOP + USHORT value; + if (downPix->value) + value = (USHORT)((downPix->value << 8) / (255.0 - upPix->value)); + + outPix->value = (UCHAR)tcrop(value, 0, 255); + + FOR_EACH_PIXEL_8_END_LOOP + } else + throw TRopException("TRop::color dodge invalid raster combination"); + } + } } //----------------------------------------------------------------------------- -void TRop::sub(const TRasterP &rup, const TRasterP &rdown, const TRasterP &rout, bool matte) -{ - TRaster32P up32 = rup; - TRaster32P down32 = rdown; - TRaster32P out32 = rout; - if (matte) { - if (up32 && down32 && out32) { - FOR_EACH_PIXEL_32_BEGIN_LOOP - - SHORT r = downPix->r - upPix->r; - SHORT g = downPix->g - upPix->g; - SHORT b = downPix->b - upPix->b; - SHORT m = downPix->m - upPix->m; - - outPix->r = (UCHAR)tcrop(r, 0, 255); - outPix->g = (UCHAR)tcrop(g, 0, 255); - outPix->b = (UCHAR)tcrop(b, 0, 255); - outPix->m = (UCHAR)tcrop(m, 0, 255); - - FOR_EACH_PIXEL_32_END_LOOP - } else { - TRaster64P up64 = rup; - TRaster64P down64 = rdown; - TRaster64P out64 = rout; - - if (up64 && down64 && out64) { - FOR_EACH_PIXEL_64_BEGIN_LOOP - - TINT32 r = downPix->r - upPix->r; - TINT32 g = downPix->g - upPix->g; - TINT32 b = downPix->b - upPix->b; - TINT32 m = downPix->m - upPix->m; - outPix->r = (USHORT)tcrop(r, 0, 0xffff); - outPix->g = (USHORT)tcrop(g, 0, 0xffff); - outPix->b = (USHORT)tcrop(b, 0, 0xffff); - outPix->m = (USHORT)tcrop(m, 0, 0xffff); - - FOR_EACH_PIXEL_64_END_LOOP - } else { - TRasterGR8P up8 = rup; - TRasterGR8P down8 = rdown; - TRasterGR8P out8 = rout; - - if (up8 && down8 && out8) { - FOR_EACH_PIXEL_8_BEGIN_LOOP - - SHORT value = upPix->value - downPix->value; - outPix->value = (UCHAR)tcrop(value, 0, 255); - - FOR_EACH_PIXEL_8_END_LOOP - } else - throw TRopException("TRop::sub invalid raster combination"); - } - } - } else { - if (up32 && down32 && out32) { - FOR_EACH_PIXEL_32_BEGIN_LOOP - - SHORT r = downPix->r - upPix->r; - SHORT g = downPix->g - upPix->g; - SHORT b = downPix->b - upPix->b; - SHORT m = downPix->m; // - upPix->m; - - outPix->r = (UCHAR)tcrop(r, 0, 255); - outPix->g = (UCHAR)tcrop(g, 0, 255); - outPix->b = (UCHAR)tcrop(b, 0, 255); - outPix->m = (UCHAR)tcrop(m, 0, 255); - - FOR_EACH_PIXEL_32_END_LOOP - } else { - TRaster64P up64 = rup; - TRaster64P down64 = rdown; - TRaster64P out64 = rout; - - if (up64 && down64 && out64) { - FOR_EACH_PIXEL_64_BEGIN_LOOP - - TINT32 r = downPix->r - upPix->r; - TINT32 g = downPix->g - upPix->g; - TINT32 b = downPix->b - upPix->b; - TINT32 m = downPix->m; // - upPix->m; - outPix->r = (USHORT)tcrop(r, 0, 0xffff); - outPix->g = (USHORT)tcrop(g, 0, 0xffff); - outPix->b = (USHORT)tcrop(b, 0, 0xffff); - outPix->m = (USHORT)tcrop(m, 0, 0xffff); - - FOR_EACH_PIXEL_64_END_LOOP - } else { - TRasterGR8P up8 = rup; - TRasterGR8P down8 = rdown; - TRasterGR8P out8 = rout; - - if (up8 && down8 && out8) { - FOR_EACH_PIXEL_8_BEGIN_LOOP - - SHORT value = upPix->value - downPix->value; - outPix->value = (UCHAR)tcrop(value, 0, 255); - - FOR_EACH_PIXEL_8_END_LOOP - } else - throw TRopException("TRop::sub invalid raster combination"); - } - } - } +void TRop::sub(const TRasterP &rup, const TRasterP &rdown, const TRasterP &rout, + bool matte) { + TRaster32P up32 = rup; + TRaster32P down32 = rdown; + TRaster32P out32 = rout; + if (matte) { + if (up32 && down32 && out32) { + FOR_EACH_PIXEL_32_BEGIN_LOOP + + SHORT r = downPix->r - upPix->r; + SHORT g = downPix->g - upPix->g; + SHORT b = downPix->b - upPix->b; + SHORT m = downPix->m - upPix->m; + + outPix->r = (UCHAR)tcrop(r, 0, 255); + outPix->g = (UCHAR)tcrop(g, 0, 255); + outPix->b = (UCHAR)tcrop(b, 0, 255); + outPix->m = (UCHAR)tcrop(m, 0, 255); + + FOR_EACH_PIXEL_32_END_LOOP + } else { + TRaster64P up64 = rup; + TRaster64P down64 = rdown; + TRaster64P out64 = rout; + + if (up64 && down64 && out64) { + FOR_EACH_PIXEL_64_BEGIN_LOOP + + TINT32 r = downPix->r - upPix->r; + TINT32 g = downPix->g - upPix->g; + TINT32 b = downPix->b - upPix->b; + TINT32 m = downPix->m - upPix->m; + outPix->r = (USHORT)tcrop(r, 0, 0xffff); + outPix->g = (USHORT)tcrop(g, 0, 0xffff); + outPix->b = (USHORT)tcrop(b, 0, 0xffff); + outPix->m = (USHORT)tcrop(m, 0, 0xffff); + + FOR_EACH_PIXEL_64_END_LOOP + } else { + TRasterGR8P up8 = rup; + TRasterGR8P down8 = rdown; + TRasterGR8P out8 = rout; + + if (up8 && down8 && out8) { + FOR_EACH_PIXEL_8_BEGIN_LOOP + + SHORT value = upPix->value - downPix->value; + outPix->value = (UCHAR)tcrop(value, 0, 255); + + FOR_EACH_PIXEL_8_END_LOOP + } else + throw TRopException("TRop::sub invalid raster combination"); + } + } + } else { + if (up32 && down32 && out32) { + FOR_EACH_PIXEL_32_BEGIN_LOOP + + SHORT r = downPix->r - upPix->r; + SHORT g = downPix->g - upPix->g; + SHORT b = downPix->b - upPix->b; + SHORT m = downPix->m; // - upPix->m; + + outPix->r = (UCHAR)tcrop(r, 0, 255); + outPix->g = (UCHAR)tcrop(g, 0, 255); + outPix->b = (UCHAR)tcrop(b, 0, 255); + outPix->m = (UCHAR)tcrop(m, 0, 255); + + FOR_EACH_PIXEL_32_END_LOOP + } else { + TRaster64P up64 = rup; + TRaster64P down64 = rdown; + TRaster64P out64 = rout; + + if (up64 && down64 && out64) { + FOR_EACH_PIXEL_64_BEGIN_LOOP + + TINT32 r = downPix->r - upPix->r; + TINT32 g = downPix->g - upPix->g; + TINT32 b = downPix->b - upPix->b; + TINT32 m = downPix->m; // - upPix->m; + outPix->r = (USHORT)tcrop(r, 0, 0xffff); + outPix->g = (USHORT)tcrop(g, 0, 0xffff); + outPix->b = (USHORT)tcrop(b, 0, 0xffff); + outPix->m = (USHORT)tcrop(m, 0, 0xffff); + + FOR_EACH_PIXEL_64_END_LOOP + } else { + TRasterGR8P up8 = rup; + TRasterGR8P down8 = rdown; + TRasterGR8P out8 = rout; + + if (up8 && down8 && out8) { + FOR_EACH_PIXEL_8_BEGIN_LOOP + + SHORT value = upPix->value - downPix->value; + outPix->value = (UCHAR)tcrop(value, 0, 255); + + FOR_EACH_PIXEL_8_END_LOOP + } else + throw TRopException("TRop::sub invalid raster combination"); + } + } + } } //----------------------------------------------------------------------------- -void TRop::mult(const TRasterP &rup, const TRasterP &rdown, const TRasterP &rout, int v, bool matte) -{ - /* - Let U be 'up', D be 'down' and M be 'multiplied' (the result), and suppose for the moment - that pixels are both NOT premultiplied and normalized to [0, 1]. - - The additional value v is used to add to RGB components of the U pixel: - - U'_rgb = (U_rgb + v / 255) - - The matte component is either U_m D_m in case (matte == true), or D_m in case (matte == false). - Please, observe that in the case (matte == false) that choice makes the product NOT COMMUTATIVE, - but I think that's justified - it's simply the most obvious use case. - - In case (matte == true), each channel is multiplied independently, and that's it. - - The matter is more complicated when (matte == false). The problem in this case is dealing with rgb - components when U and D both have some transparency. When U is fully transparent, we expect the - result to be D, and vice-versa, which is non-trivial. - - We REQUIRE that (let's denote r only here): +void TRop::mult(const TRasterP &rup, const TRasterP &rdown, + const TRasterP &rout, int v, bool matte) { + /* +Let U be 'up', D be 'down' and M be 'multiplied' (the result), and suppose for +the moment +that pixels are both NOT premultiplied and normalized to [0, 1]. - M_r = M_r_u = U_r (1 - D_m) + U_r D_r D_m, when U_m == 1 (When U is fully opaque, M_r is a D_m-linear - combination of U_r and U_r D_r) - M_r = M_r_d = D_r (1 - U_m) + U_r D_r U_m, when D_m == 1 (Vice-versa, when it's D that is fully opaque) +The additional value v is used to add to RGB components of the U pixel: - Finally, we're building a weighted sum, by U_m and D_m of the two above: +U'_rgb = (U_rgb + v / 255) - M_r = (M_r_u * U_m + M_r_d * D_m) / (U_m + D_m) = - = (...) = - = [ U_r U_m (1 - D_m) + D_r D_m (1 - U_m) + 2 U_r U_m D_r D_m ] / (U_m + D_m) - */ +The matte component is either U_m D_m in case (matte == true), or D_m in case +(matte == false). +Please, observe that in the case (matte == false) that choice makes the product +NOT COMMUTATIVE, +but I think that's justified - it's simply the most obvious use case. - // 32-bit images case - TRaster32P up32 = rup, - down32 = rdown, - out32 = rout; +In case (matte == true), each channel is multiplied independently, and that's +it. - if (up32 && down32 && out32) { - static const float maxChannelF = float(TPixel32::maxChannelValue); - static const UCHAR maxChannelC = UCHAR(TPixel32::maxChannelValue); +The matter is more complicated when (matte == false). The problem in this case +is dealing with rgb +components when U and D both have some transparency. When U is fully +transparent, we expect the +result to be D, and vice-versa, which is non-trivial. - float vf = v; +We REQUIRE that (let's denote r only here): - if (matte) { - float dnMf, upMf_norm, outMf; +M_r = M_r_u = U_r (1 - D_m) + U_r D_r D_m, when U_m == 1 (When U is fully +opaque, M_r is a D_m-linear + combination of +U_r and U_r D_r) +M_r = M_r_d = D_r (1 - U_m) + U_r D_r U_m, when D_m == 1 (Vice-versa, when +it's D that is fully opaque) - FOR_EACH_PIXEL_32_BEGIN_LOOP // Awful... should be explicit... +Finally, we're building a weighted sum, by U_m and D_m of the two above: - dnMf = downPix->m; - upMf_norm = upPix->m / maxChannelF; - - outMf = downPix->m * upMf_norm; - - outPix->r = tcrop((upPix->r / upMf_norm + vf) * (downPix->r / dnMf), 0.0f, outMf); - outPix->g = tcrop((upPix->g / upMf_norm + vf) * (downPix->g / dnMf), 0.0f, outMf); - outPix->b = tcrop((upPix->b / upMf_norm + vf) * (downPix->b / dnMf), 0.0f, outMf); - outPix->m = outMf; - - // NOTE: + 0.5f in the crop arguments could take care of rounding... +M_r = (M_r_u * U_m + M_r_d * D_m) / (U_m + D_m) = + = (...) = + = [ U_r U_m (1 - D_m) + D_r D_m (1 - U_m) + 2 U_r U_m D_r D_m ] / (U_m + +D_m) +*/ - FOR_EACH_PIXEL_32_END_LOOP - } else { - float umf_norm, dmf_norm, umdmf_norm, outMf; - float mSumf, uf, df, ufdf, normalizer; + // 32-bit images case + TRaster32P up32 = rup, down32 = rdown, out32 = rout; - FOR_EACH_PIXEL_32_BEGIN_LOOP + if (up32 && down32 && out32) { + static const float maxChannelF = float(TPixel32::maxChannelValue); + static const UCHAR maxChannelC = UCHAR(TPixel32::maxChannelValue); - mSumf = upPix->m + float(downPix->m); - if (mSumf > 0.0f) { - umf_norm = upPix->m / maxChannelF, dmf_norm = downPix->m / maxChannelF; - outMf = upPix->m + (1.0f - umf_norm) * downPix->m; // umf_norm should be ensured in [0.0, 1.0]. - // Convex combination should be in the conversion range. - normalizer = outMf / (maxChannelF * mSumf); - umdmf_norm = umf_norm * dmf_norm; + float vf = v; - uf = upPix->r + vf * umdmf_norm, df = downPix->r, ufdf = uf * df; - outPix->r = tcrop((uf * (maxChannelC - downPix->m) + df * (maxChannelC - upPix->m) + ufdf + ufdf) * normalizer, 0.0f, outMf); + if (matte) { + float dnMf, upMf_norm, outMf; - uf = upPix->g + vf * umdmf_norm, df = downPix->g, ufdf = uf * df; - outPix->g = tcrop((uf * (maxChannelC - downPix->m) + df * (maxChannelC - upPix->m) + ufdf + ufdf) * normalizer, 0.0f, outMf); + FOR_EACH_PIXEL_32_BEGIN_LOOP // Awful... should be explicit... - uf = upPix->b + vf * umdmf_norm, df = downPix->b, ufdf = uf * df; - outPix->b = tcrop((uf * (maxChannelC - downPix->m) + df * (maxChannelC - upPix->m) + ufdf + ufdf) * normalizer, 0.0f, outMf); + dnMf = downPix->m; + upMf_norm = upPix->m / maxChannelF; - outPix->m = outMf; - } else - *outPix = TPixel32::Transparent; + outMf = downPix->m * upMf_norm; - FOR_EACH_PIXEL_32_END_LOOP - } + outPix->r = + tcrop((upPix->r / upMf_norm + vf) * (downPix->r / dnMf), 0.0f, outMf); + outPix->g = + tcrop((upPix->g / upMf_norm + vf) * (downPix->g / dnMf), 0.0f, outMf); + outPix->b = + tcrop((upPix->b / upMf_norm + vf) * (downPix->b / dnMf), 0.0f, outMf); + outPix->m = outMf; - return; - } + // NOTE: + 0.5f in the crop arguments could take care of rounding... - // 64-bit images case - TRaster64P up64 = rup, - down64 = rdown, - out64 = rout; + FOR_EACH_PIXEL_32_END_LOOP + } else { + float umf_norm, dmf_norm, umdmf_norm, outMf; + float mSumf, uf, df, ufdf, normalizer; - if (up64 && down64 && out64) { - static const double maxChannelF = double(TPixel64::maxChannelValue); - static const USHORT maxChannelC = USHORT(TPixel64::maxChannelValue); + FOR_EACH_PIXEL_32_BEGIN_LOOP - double vf = v * (TPixel64::maxChannelValue / double(TPixel32::maxChannelValue)); + mSumf = upPix->m + float(downPix->m); + if (mSumf > 0.0f) { + umf_norm = upPix->m / maxChannelF, dmf_norm = downPix->m / maxChannelF; + outMf = upPix->m + + (1.0f - umf_norm) * + downPix->m; // umf_norm should be ensured in [0.0, 1.0]. + // Convex combination should be in the conversion range. + normalizer = outMf / (maxChannelF * mSumf); + umdmf_norm = umf_norm * dmf_norm; - if (matte) { - double dnMf, upMf_norm, outMf; + uf = upPix->r + vf * umdmf_norm, df = downPix->r, ufdf = uf * df; + outPix->r = tcrop((uf * (maxChannelC - downPix->m) + + df * (maxChannelC - upPix->m) + ufdf + ufdf) * + normalizer, + 0.0f, outMf); - FOR_EACH_PIXEL_64_BEGIN_LOOP + uf = upPix->g + vf * umdmf_norm, df = downPix->g, ufdf = uf * df; + outPix->g = tcrop((uf * (maxChannelC - downPix->m) + + df * (maxChannelC - upPix->m) + ufdf + ufdf) * + normalizer, + 0.0f, outMf); - dnMf = downPix->m; - upMf_norm = upPix->m / maxChannelF; + uf = upPix->b + vf * umdmf_norm, df = downPix->b, ufdf = uf * df; + outPix->b = tcrop((uf * (maxChannelC - downPix->m) + + df * (maxChannelC - upPix->m) + ufdf + ufdf) * + normalizer, + 0.0f, outMf); - outMf = downPix->m * upMf_norm; + outPix->m = outMf; + } else + *outPix = TPixel32::Transparent; - outPix->r = tcrop((upPix->r / upMf_norm + vf) * (downPix->r / dnMf), 0.0, outMf); - outPix->g = tcrop((upPix->g / upMf_norm + vf) * (downPix->g / dnMf), 0.0, outMf); - outPix->b = tcrop((upPix->b / upMf_norm + vf) * (downPix->b / dnMf), 0.0, outMf); - outPix->m = outMf; + FOR_EACH_PIXEL_32_END_LOOP + } - FOR_EACH_PIXEL_64_END_LOOP - } else { - double umf_norm, dmf_norm, umdmf_norm, outMf; - double mSumf, uf, df, ufdf, normalizer; + return; + } - FOR_EACH_PIXEL_64_BEGIN_LOOP + // 64-bit images case + TRaster64P up64 = rup, down64 = rdown, out64 = rout; - mSumf = upPix->m + double(downPix->m); - if (mSumf > 0.0) { - umf_norm = upPix->m / maxChannelF, dmf_norm = downPix->m / maxChannelF; - outMf = upPix->m + (1.0 - umf_norm) * downPix->m; + if (up64 && down64 && out64) { + static const double maxChannelF = double(TPixel64::maxChannelValue); + static const USHORT maxChannelC = USHORT(TPixel64::maxChannelValue); - normalizer = outMf / (maxChannelF * mSumf); - umdmf_norm = umf_norm * dmf_norm; + double vf = + v * (TPixel64::maxChannelValue / double(TPixel32::maxChannelValue)); - uf = upPix->r + vf * umdmf_norm, df = downPix->r, ufdf = uf * df; - outPix->r = tcrop((uf * (maxChannelC - downPix->m) + df * (maxChannelC - upPix->m) + ufdf + ufdf) * normalizer, 0.0, outMf); + if (matte) { + double dnMf, upMf_norm, outMf; - uf = upPix->g + vf * umdmf_norm, df = downPix->g, ufdf = uf * df; - outPix->g = tcrop((uf * (maxChannelC - downPix->m) + df * (maxChannelC - upPix->m) + ufdf + ufdf) * normalizer, 0.0, outMf); + FOR_EACH_PIXEL_64_BEGIN_LOOP - uf = upPix->b + vf * umdmf_norm, df = downPix->b, ufdf = uf * df; - outPix->b = tcrop((uf * (maxChannelC - downPix->m) + df * (maxChannelC - upPix->m) + ufdf + ufdf) * normalizer, 0.0, outMf); + dnMf = downPix->m; + upMf_norm = upPix->m / maxChannelF; - outPix->m = outMf; - } else - *outPix = TPixel64::Transparent; + outMf = downPix->m * upMf_norm; - FOR_EACH_PIXEL_64_END_LOOP - } + outPix->r = + tcrop((upPix->r / upMf_norm + vf) * (downPix->r / dnMf), 0.0, outMf); + outPix->g = + tcrop((upPix->g / upMf_norm + vf) * (downPix->g / dnMf), 0.0, outMf); + outPix->b = + tcrop((upPix->b / upMf_norm + vf) * (downPix->b / dnMf), 0.0, outMf); + outPix->m = outMf; - return; - } + FOR_EACH_PIXEL_64_END_LOOP + } else { + double umf_norm, dmf_norm, umdmf_norm, outMf; + double mSumf, uf, df, ufdf, normalizer; - // According to the specifics, throw an exception. I think it's not appropriate, though. - throw TRopException("TRop::mult invalid raster combination"); + FOR_EACH_PIXEL_64_BEGIN_LOOP + + mSumf = upPix->m + double(downPix->m); + if (mSumf > 0.0) { + umf_norm = upPix->m / maxChannelF, dmf_norm = downPix->m / maxChannelF; + outMf = upPix->m + (1.0 - umf_norm) * downPix->m; + + normalizer = outMf / (maxChannelF * mSumf); + umdmf_norm = umf_norm * dmf_norm; + + uf = upPix->r + vf * umdmf_norm, df = downPix->r, ufdf = uf * df; + outPix->r = tcrop((uf * (maxChannelC - downPix->m) + + df * (maxChannelC - upPix->m) + ufdf + ufdf) * + normalizer, + 0.0, outMf); + + uf = upPix->g + vf * umdmf_norm, df = downPix->g, ufdf = uf * df; + outPix->g = tcrop((uf * (maxChannelC - downPix->m) + + df * (maxChannelC - upPix->m) + ufdf + ufdf) * + normalizer, + 0.0, outMf); + + uf = upPix->b + vf * umdmf_norm, df = downPix->b, ufdf = uf * df; + outPix->b = tcrop((uf * (maxChannelC - downPix->m) + + df * (maxChannelC - upPix->m) + ufdf + ufdf) * + normalizer, + 0.0, outMf); + + outPix->m = outMf; + } else + *outPix = TPixel64::Transparent; + + FOR_EACH_PIXEL_64_END_LOOP + } + + return; + } + + // According to the specifics, throw an exception. I think it's not + // appropriate, though. + throw TRopException("TRop::mult invalid raster combination"); } //----------------------------------------------------------------------------- -void TRop::ropin(const TRasterP &source, const TRasterP &matte, const TRasterP &rout) -{ - TRaster32P source32 = source; - TRaster32P matte32 = matte; - TRaster32P out32 = rout; - TRaster64P source64 = source; - TRaster64P matte64 = matte; - TRaster64P out64 = rout; - - if (source32 && matte32 && out32) { - FOR_EACH_PIXEL_BEGIN_LOOP(TPixelRGBM32, source32, TPixelRGBM32, matte32, TPixelRGBM32, out32) - - if (downPix->m == 0) - outPix->r = outPix->g = outPix->b = outPix->m = 0; - else if (downPix->m == 255) - *outPix = *upPix; - else { - /* - __m128i zeros = _mm_setzero_si128(); - - __m128i upPix_packed_i= _mm_unpacklo_epi8(_mm_cvtsi32_si128(*(DWORD*)upPix), zeros); - __m128 upPix_packed = _mm_cvtepi32_ps(_mm_unpacklo_epi16(upPix_packed_i, zeros)); - - float fac = downPix->m / 255.0; - __m128 fac_packed = _mm_load1_ps(&fac); - - upPix_packed = _mm_mul_ps(upPix_packed, fac_packed); - - __m128i outPix_packed_i = _mm_cvtps_epi32(upPix_packed); - outPix_packed_i = _mm_packs_epi32(outPix_packed_i, zeros); - outPix_packed_i = _mm_packus_epi16(outPix_packed_i, zeros); - *(DWORD*)(outPix) = _mm_cvtsi128_si32(outPix_packed_i); +void TRop::ropin(const TRasterP &source, const TRasterP &matte, + const TRasterP &rout) { + TRaster32P source32 = source; + TRaster32P matte32 = matte; + TRaster32P out32 = rout; + TRaster64P source64 = source; + TRaster64P matte64 = matte; + TRaster64P out64 = rout; + + if (source32 && matte32 && out32) { + FOR_EACH_PIXEL_BEGIN_LOOP(TPixelRGBM32, source32, TPixelRGBM32, matte32, + TPixelRGBM32, out32) + + if (downPix->m == 0) + outPix->r = outPix->g = outPix->b = outPix->m = 0; + else if (downPix->m == 255) + *outPix = *upPix; + else { + /* +__m128i zeros = _mm_setzero_si128(); + +__m128i upPix_packed_i= _mm_unpacklo_epi8(_mm_cvtsi32_si128(*(DWORD*)upPix), +zeros); +__m128 upPix_packed = _mm_cvtepi32_ps(_mm_unpacklo_epi16(upPix_packed_i, +zeros)); + +float fac = downPix->m / 255.0; +__m128 fac_packed = _mm_load1_ps(&fac); + +upPix_packed = _mm_mul_ps(upPix_packed, fac_packed); + +__m128i outPix_packed_i = _mm_cvtps_epi32(upPix_packed); +outPix_packed_i = _mm_packs_epi32(outPix_packed_i, zeros); +outPix_packed_i = _mm_packus_epi16(outPix_packed_i, zeros); +*(DWORD*)(outPix) = _mm_cvtsi128_si32(outPix_packed_i); */ - const int MAGICFAC = (257U * 256U + 1U); - UINT fac = MAGICFAC * downPix->m; + const int MAGICFAC = (257U * 256U + 1U); + UINT fac = MAGICFAC * downPix->m; - outPix->r = (UINT)(upPix->r * fac + (1U << 23)) >> 24; - outPix->g = (UINT)(upPix->g * fac + (1U << 23)) >> 24; - outPix->b = (UINT)(upPix->b * fac + (1U << 23)) >> 24; - outPix->m = (UINT)(upPix->m * fac + (1U << 23)) >> 24; - } + outPix->r = (UINT)(upPix->r * fac + (1U << 23)) >> 24; + outPix->g = (UINT)(upPix->g * fac + (1U << 23)) >> 24; + outPix->b = (UINT)(upPix->b * fac + (1U << 23)) >> 24; + outPix->m = (UINT)(upPix->m * fac + (1U << 23)) >> 24; + } - FOR_EACH_PIXEL_END_LOOP(source32, matte32, out32) - } else if (source64 && matte64 && out64) + FOR_EACH_PIXEL_END_LOOP(source32, matte32, out32) + } else if (source64 && matte64 && out64) - { - FOR_EACH_PIXEL_BEGIN_LOOP(TPixelRGBM64, source64, TPixelRGBM64, matte64, TPixelRGBM64, out64) + { + FOR_EACH_PIXEL_BEGIN_LOOP(TPixelRGBM64, source64, TPixelRGBM64, matte64, + TPixelRGBM64, out64) - if (downPix->m == 0) - outPix->r = outPix->g = outPix->b = outPix->m = 0; - else if (downPix->m == 65535) - *outPix = *upPix; - else { - /* - __m128i zeros = _mm_setzero_si128(); + if (downPix->m == 0) + outPix->r = outPix->g = outPix->b = outPix->m = 0; + else if (downPix->m == 65535) + *outPix = *upPix; + else { + /* +__m128i zeros = _mm_setzero_si128(); - __m128i upPix_packed_i= _mm_unpacklo_epi8(_mm_cvtsi32_si128(*(DWORD*)upPix), zeros); - __m128 upPix_packed = _mm_cvtepi32_ps(_mm_unpacklo_epi16(upPix_packed_i, zeros)); +__m128i upPix_packed_i= _mm_unpacklo_epi8(_mm_cvtsi32_si128(*(DWORD*)upPix), +zeros); +__m128 upPix_packed = _mm_cvtepi32_ps(_mm_unpacklo_epi16(upPix_packed_i, +zeros)); - float fac = downPix->m / 255.0; - __m128 fac_packed = _mm_load1_ps(&fac); +float fac = downPix->m / 255.0; +__m128 fac_packed = _mm_load1_ps(&fac); - upPix_packed = _mm_mul_ps(upPix_packed, fac_packed); +upPix_packed = _mm_mul_ps(upPix_packed, fac_packed); - __m128i outPix_packed_i = _mm_cvtps_epi32(upPix_packed); - outPix_packed_i = _mm_packs_epi32(outPix_packed_i, zeros); - outPix_packed_i = _mm_packus_epi16(outPix_packed_i, zeros); - *(DWORD*)(outPix) = _mm_cvtsi128_si32(outPix_packed_i); +__m128i outPix_packed_i = _mm_cvtps_epi32(upPix_packed); +outPix_packed_i = _mm_packs_epi32(outPix_packed_i, zeros); +outPix_packed_i = _mm_packus_epi16(outPix_packed_i, zeros); +*(DWORD*)(outPix) = _mm_cvtsi128_si32(outPix_packed_i); */ - double fac = downPix->m / 65535.0; + double fac = downPix->m / 65535.0; - outPix->r = (USHORT)(upPix->r * fac); - outPix->g = (USHORT)(upPix->g * fac); - outPix->b = (USHORT)(upPix->b * fac); - outPix->m = (USHORT)(upPix->m * fac); - } + outPix->r = (USHORT)(upPix->r * fac); + outPix->g = (USHORT)(upPix->g * fac); + outPix->b = (USHORT)(upPix->b * fac); + outPix->m = (USHORT)(upPix->m * fac); + } - FOR_EACH_PIXEL_END_LOOP(source64, matte64, out64) - } else - throw TRopException("TRop::in invalid raster combination"); + FOR_EACH_PIXEL_END_LOOP(source64, matte64, out64) + } else + throw TRopException("TRop::in invalid raster combination"); } //----------------------------------------------------------------------------- -void TRop::ropout(const TRasterP &source, const TRasterP &matte, const TRasterP &rout) -{ - TRaster32P source32 = source; - TRaster32P matte32 = matte; - TRaster32P out32 = rout; - TRaster64P source64 = source; - TRaster64P matte64 = matte; - TRaster64P out64 = rout; - - if (source32 && matte32 && out32) { - FOR_EACH_PIXEL_BEGIN_LOOP(TPixelRGBM32, source32, TPixelRGBM32, matte32, TPixelRGBM32, out32) - - if (downPix->m == 255) - outPix->r = outPix->g = outPix->b = outPix->m = 0; - else if (downPix->m == 0) - *outPix = *upPix; - else { - const int MAGICFAC = (257U * 256U + 1U); - UINT fac = MAGICFAC * (255 - downPix->m); - - outPix->r = (UINT)(upPix->r * fac + (1U << 23)) >> 24; - outPix->g = (UINT)(upPix->g * fac + (1U << 23)) >> 24; - outPix->b = (UINT)(upPix->b * fac + (1U << 23)) >> 24; - outPix->m = (UINT)(upPix->m * fac + (1U << 23)) >> 24; - } - - FOR_EACH_PIXEL_END_LOOP(source32, matte32, out32) - } else if (source64 && matte64 && out64) { - FOR_EACH_PIXEL_BEGIN_LOOP(TPixelRGBM64, source64, TPixelRGBM64, matte64, TPixelRGBM64, out64) - - if (downPix->m == 65535) - outPix->r = outPix->g = outPix->b = outPix->m = 0; - else if (downPix->m == 0) - *outPix = *upPix; - else { - double fac = (65535 - downPix->m) / 65535.0; - - outPix->r = (USHORT)(upPix->r * fac); - outPix->g = (USHORT)(upPix->g * fac); - outPix->b = (USHORT)(upPix->b * fac); - outPix->m = (USHORT)(upPix->m * fac); - } - - FOR_EACH_PIXEL_END_LOOP(source64, matte64, out64) - } else - throw TRopException("TRop::out invalid raster combination"); +void TRop::ropout(const TRasterP &source, const TRasterP &matte, + const TRasterP &rout) { + TRaster32P source32 = source; + TRaster32P matte32 = matte; + TRaster32P out32 = rout; + TRaster64P source64 = source; + TRaster64P matte64 = matte; + TRaster64P out64 = rout; + + if (source32 && matte32 && out32) { + FOR_EACH_PIXEL_BEGIN_LOOP(TPixelRGBM32, source32, TPixelRGBM32, matte32, + TPixelRGBM32, out32) + + if (downPix->m == 255) + outPix->r = outPix->g = outPix->b = outPix->m = 0; + else if (downPix->m == 0) + *outPix = *upPix; + else { + const int MAGICFAC = (257U * 256U + 1U); + UINT fac = MAGICFAC * (255 - downPix->m); + + outPix->r = (UINT)(upPix->r * fac + (1U << 23)) >> 24; + outPix->g = (UINT)(upPix->g * fac + (1U << 23)) >> 24; + outPix->b = (UINT)(upPix->b * fac + (1U << 23)) >> 24; + outPix->m = (UINT)(upPix->m * fac + (1U << 23)) >> 24; + } + + FOR_EACH_PIXEL_END_LOOP(source32, matte32, out32) + } else if (source64 && matte64 && out64) { + FOR_EACH_PIXEL_BEGIN_LOOP(TPixelRGBM64, source64, TPixelRGBM64, matte64, + TPixelRGBM64, out64) + + if (downPix->m == 65535) + outPix->r = outPix->g = outPix->b = outPix->m = 0; + else if (downPix->m == 0) + *outPix = *upPix; + else { + double fac = (65535 - downPix->m) / 65535.0; + + outPix->r = (USHORT)(upPix->r * fac); + outPix->g = (USHORT)(upPix->g * fac); + outPix->b = (USHORT)(upPix->b * fac); + outPix->m = (USHORT)(upPix->m * fac); + } + + FOR_EACH_PIXEL_END_LOOP(source64, matte64, out64) + } else + throw TRopException("TRop::out invalid raster combination"); } //----------------------------------------------------------------------------- -void TRop::atop(const TRasterP &rup, const TRasterP &rdown, const TRasterP &rout) -{ - // calcola rup ATOP rdown - - // da ottimizzare... - TRaster32P up32 = rup; - TRaster32P down32 = rdown; - TRaster32P out32 = rout; - TRaster64P up64 = rup; - TRaster64P down64 = rdown; - TRaster64P out64 = rout; - - if (up32 && down32 && out32) { - FOR_EACH_PIXEL_32_BEGIN_LOOP - - TPixel32 tmpPix(0, 0, 0, 0); - if (downPix->m != 0) { - const int MAGICFAC = (257U * 256U + 1U); - UINT fac = MAGICFAC * downPix->m; - - tmpPix.r = (UINT)(upPix->r * fac + (1U << 23)) >> 24; - tmpPix.g = (UINT)(upPix->g * fac + (1U << 23)) >> 24; - tmpPix.b = (UINT)(upPix->b * fac + (1U << 23)) >> 24; - tmpPix.m = (UINT)(upPix->m * fac + (1U << 23)) >> 24; - } - - overPix(*outPix, *downPix, tmpPix); - - FOR_EACH_PIXEL_32_END_LOOP - } else if (up64 && down64 && out64) { - FOR_EACH_PIXEL_64_BEGIN_LOOP - - TPixel64 tmpPix(0, 0, 0, 0); - if (downPix->m != 0) { - double fac = downPix->m / 65535.0; - - tmpPix.r = (USHORT)(upPix->r * fac); - tmpPix.g = (USHORT)(upPix->g * fac); - tmpPix.b = (USHORT)(upPix->b * fac); - tmpPix.m = (USHORT)(upPix->m * fac); - } - - overPix(*outPix, *downPix, tmpPix); - - FOR_EACH_PIXEL_64_END_LOOP - } else - throw TRopException("TRop::atop invalid raster combination"); +void TRop::atop(const TRasterP &rup, const TRasterP &rdown, + const TRasterP &rout) { + // calcola rup ATOP rdown + + // da ottimizzare... + TRaster32P up32 = rup; + TRaster32P down32 = rdown; + TRaster32P out32 = rout; + TRaster64P up64 = rup; + TRaster64P down64 = rdown; + TRaster64P out64 = rout; + + if (up32 && down32 && out32) { + FOR_EACH_PIXEL_32_BEGIN_LOOP + + TPixel32 tmpPix(0, 0, 0, 0); + if (downPix->m != 0) { + const int MAGICFAC = (257U * 256U + 1U); + UINT fac = MAGICFAC * downPix->m; + + tmpPix.r = (UINT)(upPix->r * fac + (1U << 23)) >> 24; + tmpPix.g = (UINT)(upPix->g * fac + (1U << 23)) >> 24; + tmpPix.b = (UINT)(upPix->b * fac + (1U << 23)) >> 24; + tmpPix.m = (UINT)(upPix->m * fac + (1U << 23)) >> 24; + } + + overPix(*outPix, *downPix, tmpPix); + + FOR_EACH_PIXEL_32_END_LOOP + } else if (up64 && down64 && out64) { + FOR_EACH_PIXEL_64_BEGIN_LOOP + + TPixel64 tmpPix(0, 0, 0, 0); + if (downPix->m != 0) { + double fac = downPix->m / 65535.0; + + tmpPix.r = (USHORT)(upPix->r * fac); + tmpPix.g = (USHORT)(upPix->g * fac); + tmpPix.b = (USHORT)(upPix->b * fac); + tmpPix.m = (USHORT)(upPix->m * fac); + } + + overPix(*outPix, *downPix, tmpPix); + + FOR_EACH_PIXEL_64_END_LOOP + } else + throw TRopException("TRop::atop invalid raster combination"); } //----------------------------------------------------------------------------- -void TRop::txor(const TRasterP &rup, const TRasterP &rdown, const TRasterP &rout) -{ - // da ottimizzare... - TRaster32P up32 = rup; - TRaster32P down32 = rdown; - TRaster32P out32 = rout; - TRaster64P up64 = rup; - TRaster64P down64 = rdown; - TRaster64P out64 = rout; +void TRop::txor(const TRasterP &rup, const TRasterP &rdown, + const TRasterP &rout) { + // da ottimizzare... + TRaster32P up32 = rup; + TRaster32P down32 = rdown; + TRaster32P out32 = rout; + TRaster64P up64 = rup; + TRaster64P down64 = rdown; + TRaster64P out64 = rout; - if (up32 && down32 && out32) { - FOR_EACH_PIXEL_32_BEGIN_LOOP + if (up32 && down32 && out32) { + FOR_EACH_PIXEL_32_BEGIN_LOOP - TUINT32 notUpM = 255 - upPix->m; - TUINT32 notDownM = 255 - downPix->m; + TUINT32 notUpM = 255 - upPix->m; + TUINT32 notDownM = 255 - downPix->m; - TUINT32 r = notUpM + upPix->r * (notDownM); - TUINT32 g = notUpM + upPix->g * (notDownM); - TUINT32 b = notUpM + upPix->b * (notDownM); + TUINT32 r = notUpM + upPix->r * (notDownM); + TUINT32 g = notUpM + upPix->g * (notDownM); + TUINT32 b = notUpM + upPix->b * (notDownM); - outPix->r = (UCHAR)tcrop(0, 255, r); - outPix->g = (UCHAR)tcrop(0, 255, g); - outPix->b = (UCHAR)tcrop(0, 255, b); + outPix->r = (UCHAR)tcrop(0, 255, r); + outPix->g = (UCHAR)tcrop(0, 255, g); + outPix->b = (UCHAR)tcrop(0, 255, b); - FOR_EACH_PIXEL_32_END_LOOP - } else if (up64 && down64 && out64) { - FOR_EACH_PIXEL_64_BEGIN_LOOP + FOR_EACH_PIXEL_32_END_LOOP + } else if (up64 && down64 && out64) { + FOR_EACH_PIXEL_64_BEGIN_LOOP - TUINT32 notUpM = 65535 - upPix->m; - TUINT32 notDownM = 65535 - downPix->m; + TUINT32 notUpM = 65535 - upPix->m; + TUINT32 notDownM = 65535 - downPix->m; - TUINT32 r = notUpM + upPix->r * (notDownM); - TUINT32 g = notUpM + upPix->g * (notDownM); - TUINT32 b = notUpM + upPix->b * (notDownM); + TUINT32 r = notUpM + upPix->r * (notDownM); + TUINT32 g = notUpM + upPix->g * (notDownM); + TUINT32 b = notUpM + upPix->b * (notDownM); - outPix->r = (USHORT)tcrop(0, 65535, r); - outPix->g = (USHORT)tcrop(0, 65535, g); - outPix->b = (USHORT)tcrop(0, 65535, b); + outPix->r = (USHORT)tcrop(0, 65535, r); + outPix->g = (USHORT)tcrop(0, 65535, g); + outPix->b = (USHORT)tcrop(0, 65535, b); - FOR_EACH_PIXEL_64_END_LOOP - } else - throw TRopException("TRop::xor invalid raster combination"); + FOR_EACH_PIXEL_64_END_LOOP + } else + throw TRopException("TRop::xor invalid raster combination"); } //----------------------------------------------------------------------------- -void TRop::crossDissolve(const TRasterP &rup, const TRasterP &rdown, const TRasterP &rout, UCHAR v) -{ - TRaster32P up32 = rup; - TRaster32P down32 = rdown; - TRaster32P out32 = rout; - TRaster64P up64 = rup; - TRaster64P down64 = rdown; - TRaster64P out64 = rout; - - if (up32 && down32 && out32) { - FOR_EACH_PIXEL_32_BEGIN_LOOP - - outPix->r = (upPix->r * v + downPix->r * (255 - v)) / 255; - outPix->g = (upPix->g * v + downPix->g * (255 - v)) / 255; - outPix->b = (upPix->b * v + downPix->b * (255 - v)) / 255; - outPix->m = (upPix->m * v + downPix->m * (255 - v)) / 255; - - FOR_EACH_PIXEL_32_END_LOOP - } else if (up64 && down64 && out64) { - USHORT vv = v * 257; - - FOR_EACH_PIXEL_64_BEGIN_LOOP - - outPix->r = (upPix->r * vv + downPix->r * (65535 - vv)) / 65535; - outPix->g = (upPix->g * vv + downPix->g * (65535 - vv)) / 65535; - outPix->b = (upPix->b * vv + downPix->b * (65535 - vv)) / 65535; - outPix->m = (upPix->m * vv + downPix->m * (65535 - vv)) / 65535; - - FOR_EACH_PIXEL_64_END_LOOP - } else - throw TRopException("TRop::crossDissolve invalid raster combination"); +void TRop::crossDissolve(const TRasterP &rup, const TRasterP &rdown, + const TRasterP &rout, UCHAR v) { + TRaster32P up32 = rup; + TRaster32P down32 = rdown; + TRaster32P out32 = rout; + TRaster64P up64 = rup; + TRaster64P down64 = rdown; + TRaster64P out64 = rout; + + if (up32 && down32 && out32) { + FOR_EACH_PIXEL_32_BEGIN_LOOP + + outPix->r = (upPix->r * v + downPix->r * (255 - v)) / 255; + outPix->g = (upPix->g * v + downPix->g * (255 - v)) / 255; + outPix->b = (upPix->b * v + downPix->b * (255 - v)) / 255; + outPix->m = (upPix->m * v + downPix->m * (255 - v)) / 255; + + FOR_EACH_PIXEL_32_END_LOOP + } else if (up64 && down64 && out64) { + USHORT vv = v * 257; + + FOR_EACH_PIXEL_64_BEGIN_LOOP + + outPix->r = (upPix->r * vv + downPix->r * (65535 - vv)) / 65535; + outPix->g = (upPix->g * vv + downPix->g * (65535 - vv)) / 65535; + outPix->b = (upPix->b * vv + downPix->b * (65535 - vv)) / 65535; + outPix->m = (upPix->m * vv + downPix->m * (65535 - vv)) / 65535; + + FOR_EACH_PIXEL_64_END_LOOP + } else + throw TRopException("TRop::crossDissolve invalid raster combination"); } //----------------------------------------------------------------------------- -void TRop::darken(const TRasterP &rup, const TRasterP &rdown, const TRasterP &rout) -{ - TRaster32P up32 = rup; - TRaster32P down32 = rdown; - TRaster32P out32 = rout; - TRaster64P up64 = rup; - TRaster64P down64 = rdown; - TRaster64P out64 = rout; - - if (up32 && down32 && out32) { - FOR_EACH_PIXEL_32_BEGIN_LOOP - - double value0 = luminance(upPix); - double value1 = luminance(downPix); - - if (value0 < value1) - *outPix = *upPix; - else - *outPix = *downPix; - - FOR_EACH_PIXEL_32_END_LOOP - } else if (up64 && down64 && out64) { - FOR_EACH_PIXEL_64_BEGIN_LOOP - - double value0 = luminance(upPix); - double value1 = luminance(downPix); - - if (value0 < value1) - *outPix = *upPix; - else - *outPix = *downPix; - - FOR_EACH_PIXEL_64_END_LOOP - } else - throw TRopException("TRop::darken invalid raster combination"); +void TRop::darken(const TRasterP &rup, const TRasterP &rdown, + const TRasterP &rout) { + TRaster32P up32 = rup; + TRaster32P down32 = rdown; + TRaster32P out32 = rout; + TRaster64P up64 = rup; + TRaster64P down64 = rdown; + TRaster64P out64 = rout; + + if (up32 && down32 && out32) { + FOR_EACH_PIXEL_32_BEGIN_LOOP + + double value0 = luminance(upPix); + double value1 = luminance(downPix); + + if (value0 < value1) + *outPix = *upPix; + else + *outPix = *downPix; + + FOR_EACH_PIXEL_32_END_LOOP + } else if (up64 && down64 && out64) { + FOR_EACH_PIXEL_64_BEGIN_LOOP + + double value0 = luminance(upPix); + double value1 = luminance(downPix); + + if (value0 < value1) + *outPix = *upPix; + else + *outPix = *downPix; + + FOR_EACH_PIXEL_64_END_LOOP + } else + throw TRopException("TRop::darken invalid raster combination"); } //----------------------------------------------------------------------------- -void TRop::lighten(const TRasterP &rup, const TRasterP &rdown, const TRasterP &rout) -{ - TRaster32P up32 = rup; - TRaster32P down32 = rdown; - TRaster32P out32 = rout; - TRaster64P up64 = rup; - TRaster64P down64 = rdown; - TRaster64P out64 = rout; - - if (up32 && down32 && out32) { - FOR_EACH_PIXEL_32_BEGIN_LOOP - - double value0 = luminance(upPix); - double value1 = luminance(downPix); - - if (value0 > value1) { - TINT32 r, g, b, m; - if (upPix->m == 0) - *outPix = *downPix; - else { - r = downPix->r + upPix->r; - g = downPix->g + upPix->g; - b = downPix->b + upPix->b; - m = downPix->m + upPix->m; - outPix->r = (UCHAR)tcrop(r, (TINT32)0, (TINT32)255); - outPix->g = (UCHAR)tcrop(g, (TINT32)0, (TINT32)255); - outPix->b = (UCHAR)tcrop(b, (TINT32)0, (TINT32)255); - outPix->m = (UCHAR)tcrop(m, (TINT32)0, (TINT32)255); - } - } else { - *outPix = *downPix; - } - - FOR_EACH_PIXEL_32_END_LOOP - } else if (up64 && down64 && out64) { - FOR_EACH_PIXEL_64_BEGIN_LOOP - - double value0 = luminance(upPix); - double value1 = luminance(downPix); - - if (value0 > value1) { - TINT32 r, g, b, m; - if (upPix->m == 0) - *outPix = *downPix; - else { - r = downPix->r + upPix->r; - g = downPix->g + upPix->g; - b = downPix->b + upPix->b; - m = downPix->m + upPix->m; - outPix->r = (USHORT)tcrop(r, (TINT32)0, (TINT32)65535); - outPix->g = (USHORT)tcrop(g, (TINT32)0, (TINT32)65535); - outPix->b = (USHORT)tcrop(b, (TINT32)0, (TINT32)65535); - outPix->m = (USHORT)tcrop(m, (TINT32)0, (TINT32)65535); - } - } else { - *outPix = *downPix; - } - - FOR_EACH_PIXEL_64_END_LOOP - } else - throw TRopException("TRop::lighten invalid raster combination"); +void TRop::lighten(const TRasterP &rup, const TRasterP &rdown, + const TRasterP &rout) { + TRaster32P up32 = rup; + TRaster32P down32 = rdown; + TRaster32P out32 = rout; + TRaster64P up64 = rup; + TRaster64P down64 = rdown; + TRaster64P out64 = rout; + + if (up32 && down32 && out32) { + FOR_EACH_PIXEL_32_BEGIN_LOOP + + double value0 = luminance(upPix); + double value1 = luminance(downPix); + + if (value0 > value1) { + TINT32 r, g, b, m; + if (upPix->m == 0) + *outPix = *downPix; + else { + r = downPix->r + upPix->r; + g = downPix->g + upPix->g; + b = downPix->b + upPix->b; + m = downPix->m + upPix->m; + outPix->r = (UCHAR)tcrop(r, (TINT32)0, (TINT32)255); + outPix->g = (UCHAR)tcrop(g, (TINT32)0, (TINT32)255); + outPix->b = (UCHAR)tcrop(b, (TINT32)0, (TINT32)255); + outPix->m = (UCHAR)tcrop(m, (TINT32)0, (TINT32)255); + } + } else { + *outPix = *downPix; + } + + FOR_EACH_PIXEL_32_END_LOOP + } else if (up64 && down64 && out64) { + FOR_EACH_PIXEL_64_BEGIN_LOOP + + double value0 = luminance(upPix); + double value1 = luminance(downPix); + + if (value0 > value1) { + TINT32 r, g, b, m; + if (upPix->m == 0) + *outPix = *downPix; + else { + r = downPix->r + upPix->r; + g = downPix->g + upPix->g; + b = downPix->b + upPix->b; + m = downPix->m + upPix->m; + outPix->r = (USHORT)tcrop(r, (TINT32)0, (TINT32)65535); + outPix->g = (USHORT)tcrop(g, (TINT32)0, (TINT32)65535); + outPix->b = (USHORT)tcrop(b, (TINT32)0, (TINT32)65535); + outPix->m = (USHORT)tcrop(m, (TINT32)0, (TINT32)65535); + } + } else { + *outPix = *downPix; + } + + FOR_EACH_PIXEL_64_END_LOOP + } else + throw TRopException("TRop::lighten invalid raster combination"); } //----------------------------------------------------------------------------- -void TRop::ropmin(const TRasterP &rup, const TRasterP &rdown, const TRasterP &rout, bool matte) -{ - TRaster32P up32 = rup; - TRaster32P down32 = rdown; - TRaster32P out32 = rout; - - if (up32 && down32 && out32) { - if (matte) { - FOR_EACH_PIXEL_32_BEGIN_LOOP - - outPix->r = upPix->r < downPix->r ? upPix->r : downPix->r; - outPix->g = upPix->g < downPix->g ? upPix->g : downPix->g; - outPix->b = upPix->b < downPix->b ? upPix->b : downPix->b; - outPix->m = upPix->m < downPix->m ? upPix->m : downPix->m; - - FOR_EACH_PIXEL_32_END_LOOP - } else { - FOR_EACH_PIXEL_32_BEGIN_LOOP - if (upPix->m >= 255) { - outPix->r = upPix->r < downPix->r ? upPix->r : downPix->r; - outPix->g = upPix->g < downPix->g ? upPix->g : downPix->g; - outPix->b = upPix->b < downPix->b ? upPix->b : downPix->b; - outPix->m = upPix->m < downPix->m ? upPix->m : downPix->m; - - } else if (upPix->m) { - TPixel32 tmp; - tmp.r = upPix->r < downPix->r ? upPix->r : downPix->r; - tmp.g = upPix->g < downPix->g ? upPix->g : downPix->g; - tmp.b = upPix->b < downPix->b ? upPix->b : downPix->b; - //tmp.m = upPix->m < downPix->m ? upPix->m : downPix->m; - outPix->r = upPix->m * (tmp.r - downPix->r) / 255.0 + downPix->r; - outPix->g = upPix->m * (tmp.g - downPix->g) / 255.0 + downPix->g; - outPix->b = upPix->m * (tmp.b - downPix->b) / 255.0 + downPix->b; - outPix->m = upPix->m * (tmp.m - downPix->m) / 255.0 + downPix->m; - } else - *outPix = *downPix; - FOR_EACH_PIXEL_32_END_LOOP - } - } else { - TRaster64P up64 = rup; - TRaster64P down64 = rdown; - TRaster64P out64 = rout; - - if (up64 && down64 && out64) { - if (matte) { - FOR_EACH_PIXEL_64_BEGIN_LOOP - - outPix->r = upPix->r < downPix->r ? upPix->r : downPix->r; - outPix->g = upPix->g < downPix->g ? upPix->g : downPix->g; - outPix->b = upPix->b < downPix->b ? upPix->b : downPix->b; - outPix->m = upPix->m < downPix->m ? upPix->m : downPix->m; - - FOR_EACH_PIXEL_64_END_LOOP - } else { - FOR_EACH_PIXEL_32_BEGIN_LOOP - if (upPix->m >= 65535) { - outPix->r = upPix->r < downPix->r ? upPix->r : downPix->r; - outPix->g = upPix->g < downPix->g ? upPix->g : downPix->g; - outPix->b = upPix->b < downPix->b ? upPix->b : downPix->b; - outPix->m = upPix->m < downPix->m ? upPix->m : downPix->m; - - } else if (upPix->m) { - TPixel32 tmp; - tmp.r = upPix->r < downPix->r ? upPix->r : downPix->r; - tmp.g = upPix->g < downPix->g ? upPix->g : downPix->g; - tmp.b = upPix->b < downPix->b ? upPix->b : downPix->b; - //tmp.m = upPix->m < downPix->m ? upPix->m : downPix->m; - outPix->r = upPix->m * (tmp.r - downPix->r) / 65535.0 + downPix->r; - outPix->g = upPix->m * (tmp.g - downPix->g) / 65535.0 + downPix->g; - outPix->b = upPix->m * (tmp.b - downPix->b) / 65535.0 + downPix->b; - outPix->m = upPix->m * (tmp.m - downPix->m) / 65535.0 + downPix->m; - } else - *outPix = *downPix; - FOR_EACH_PIXEL_32_END_LOOP - } - } else { - TRasterGR8P up8 = rup; - TRasterGR8P down8 = rdown; - TRasterGR8P out8 = rout; - - if (up8 && down8 && out8) { - FOR_EACH_PIXEL_8_BEGIN_LOOP - - outPix->value = upPix->value < downPix->value ? upPix->value : downPix->value; - - FOR_EACH_PIXEL_8_END_LOOP - } else - throw TRopException("TRop::min invalid raster combination"); - } - } +void TRop::ropmin(const TRasterP &rup, const TRasterP &rdown, + const TRasterP &rout, bool matte) { + TRaster32P up32 = rup; + TRaster32P down32 = rdown; + TRaster32P out32 = rout; + + if (up32 && down32 && out32) { + if (matte) { + FOR_EACH_PIXEL_32_BEGIN_LOOP + + outPix->r = upPix->r < downPix->r ? upPix->r : downPix->r; + outPix->g = upPix->g < downPix->g ? upPix->g : downPix->g; + outPix->b = upPix->b < downPix->b ? upPix->b : downPix->b; + outPix->m = upPix->m < downPix->m ? upPix->m : downPix->m; + + FOR_EACH_PIXEL_32_END_LOOP + } else { + FOR_EACH_PIXEL_32_BEGIN_LOOP + if (upPix->m >= 255) { + outPix->r = upPix->r < downPix->r ? upPix->r : downPix->r; + outPix->g = upPix->g < downPix->g ? upPix->g : downPix->g; + outPix->b = upPix->b < downPix->b ? upPix->b : downPix->b; + outPix->m = upPix->m < downPix->m ? upPix->m : downPix->m; + + } else if (upPix->m) { + TPixel32 tmp; + tmp.r = upPix->r < downPix->r ? upPix->r : downPix->r; + tmp.g = upPix->g < downPix->g ? upPix->g : downPix->g; + tmp.b = upPix->b < downPix->b ? upPix->b : downPix->b; + // tmp.m = upPix->m < downPix->m ? upPix->m : downPix->m; + outPix->r = upPix->m * (tmp.r - downPix->r) / 255.0 + downPix->r; + outPix->g = upPix->m * (tmp.g - downPix->g) / 255.0 + downPix->g; + outPix->b = upPix->m * (tmp.b - downPix->b) / 255.0 + downPix->b; + outPix->m = upPix->m * (tmp.m - downPix->m) / 255.0 + downPix->m; + } else + *outPix = *downPix; + FOR_EACH_PIXEL_32_END_LOOP + } + } else { + TRaster64P up64 = rup; + TRaster64P down64 = rdown; + TRaster64P out64 = rout; + + if (up64 && down64 && out64) { + if (matte) { + FOR_EACH_PIXEL_64_BEGIN_LOOP + + outPix->r = upPix->r < downPix->r ? upPix->r : downPix->r; + outPix->g = upPix->g < downPix->g ? upPix->g : downPix->g; + outPix->b = upPix->b < downPix->b ? upPix->b : downPix->b; + outPix->m = upPix->m < downPix->m ? upPix->m : downPix->m; + + FOR_EACH_PIXEL_64_END_LOOP + } else { + FOR_EACH_PIXEL_32_BEGIN_LOOP + if (upPix->m >= 65535) { + outPix->r = upPix->r < downPix->r ? upPix->r : downPix->r; + outPix->g = upPix->g < downPix->g ? upPix->g : downPix->g; + outPix->b = upPix->b < downPix->b ? upPix->b : downPix->b; + outPix->m = upPix->m < downPix->m ? upPix->m : downPix->m; + + } else if (upPix->m) { + TPixel32 tmp; + tmp.r = upPix->r < downPix->r ? upPix->r : downPix->r; + tmp.g = upPix->g < downPix->g ? upPix->g : downPix->g; + tmp.b = upPix->b < downPix->b ? upPix->b : downPix->b; + // tmp.m = upPix->m < downPix->m ? upPix->m : downPix->m; + outPix->r = upPix->m * (tmp.r - downPix->r) / 65535.0 + downPix->r; + outPix->g = upPix->m * (tmp.g - downPix->g) / 65535.0 + downPix->g; + outPix->b = upPix->m * (tmp.b - downPix->b) / 65535.0 + downPix->b; + outPix->m = upPix->m * (tmp.m - downPix->m) / 65535.0 + downPix->m; + } else + *outPix = *downPix; + FOR_EACH_PIXEL_32_END_LOOP + } + } else { + TRasterGR8P up8 = rup; + TRasterGR8P down8 = rdown; + TRasterGR8P out8 = rout; + + if (up8 && down8 && out8) { + FOR_EACH_PIXEL_8_BEGIN_LOOP + + outPix->value = + upPix->value < downPix->value ? upPix->value : downPix->value; + + FOR_EACH_PIXEL_8_END_LOOP + } else + throw TRopException("TRop::min invalid raster combination"); + } + } } //----------------------------------------------------------------------------- -void TRop::ropmax(const TRasterP &rup, const TRasterP &rdown, const TRasterP &rout) -{ - TRaster32P up32 = rup; - TRaster32P down32 = rdown; - TRaster32P out32 = rout; - - if (up32 && down32 && out32) { - FOR_EACH_PIXEL_32_BEGIN_LOOP - - outPix->r = upPix->r > downPix->r ? upPix->r : downPix->r; - outPix->g = upPix->g > downPix->g ? upPix->g : downPix->g; - outPix->b = upPix->b > downPix->b ? upPix->b : downPix->b; - outPix->m = upPix->m > downPix->m ? upPix->m : downPix->m; - - FOR_EACH_PIXEL_32_END_LOOP - } else { - TRaster64P up64 = rup; - TRaster64P down64 = rdown; - TRaster64P out64 = rout; - - if (up64 && down64 && out64) { - FOR_EACH_PIXEL_64_BEGIN_LOOP - - outPix->r = upPix->r > downPix->r ? upPix->r : downPix->r; - outPix->g = upPix->g > downPix->g ? upPix->g : downPix->g; - outPix->b = upPix->b > downPix->b ? upPix->b : downPix->b; - outPix->m = upPix->m > downPix->m ? upPix->m : downPix->m; - - FOR_EACH_PIXEL_64_END_LOOP - } else { - TRasterGR8P up8 = rup; - TRasterGR8P down8 = rdown; - TRasterGR8P out8 = rout; - - if (up8 && down8 && out8) { - FOR_EACH_PIXEL_8_BEGIN_LOOP - - outPix->value = upPix->value > downPix->value ? upPix->value : downPix->value; - - FOR_EACH_PIXEL_8_END_LOOP - } else - throw TRopException("TRop::max invalid raster combination"); - } - } +void TRop::ropmax(const TRasterP &rup, const TRasterP &rdown, + const TRasterP &rout) { + TRaster32P up32 = rup; + TRaster32P down32 = rdown; + TRaster32P out32 = rout; + + if (up32 && down32 && out32) { + FOR_EACH_PIXEL_32_BEGIN_LOOP + + outPix->r = upPix->r > downPix->r ? upPix->r : downPix->r; + outPix->g = upPix->g > downPix->g ? upPix->g : downPix->g; + outPix->b = upPix->b > downPix->b ? upPix->b : downPix->b; + outPix->m = upPix->m > downPix->m ? upPix->m : downPix->m; + + FOR_EACH_PIXEL_32_END_LOOP + } else { + TRaster64P up64 = rup; + TRaster64P down64 = rdown; + TRaster64P out64 = rout; + + if (up64 && down64 && out64) { + FOR_EACH_PIXEL_64_BEGIN_LOOP + + outPix->r = upPix->r > downPix->r ? upPix->r : downPix->r; + outPix->g = upPix->g > downPix->g ? upPix->g : downPix->g; + outPix->b = upPix->b > downPix->b ? upPix->b : downPix->b; + outPix->m = upPix->m > downPix->m ? upPix->m : downPix->m; + + FOR_EACH_PIXEL_64_END_LOOP + } else { + TRasterGR8P up8 = rup; + TRasterGR8P down8 = rdown; + TRasterGR8P out8 = rout; + + if (up8 && down8 && out8) { + FOR_EACH_PIXEL_8_BEGIN_LOOP + + outPix->value = + upPix->value > downPix->value ? upPix->value : downPix->value; + + FOR_EACH_PIXEL_8_END_LOOP + } else + throw TRopException("TRop::max invalid raster combination"); + } + } } //----------------------------------------------------------------------------- -void TRop::linearburn(const TRasterP &rup, const TRasterP &rdown, const TRasterP &rout) -{ - TRaster32P up32 = rup; - TRaster32P down32 = rdown; - TRaster32P out32 = rout; - - if (up32 && down32 && out32) { - FOR_EACH_PIXEL_32_BEGIN_LOOP - if (upPix->m) { - TPixel32 app; - if (downPix->m) { - TINT32 r, g, b, m; - TPixel32 tmpPix; - tmpPix = depremultiply(*downPix); - r = tmpPix.r + upPix->r - 255; - g = tmpPix.g + upPix->g - 255; - b = tmpPix.b + upPix->b - 255; - m = tmpPix.m + upPix->m - 255; - - app.r = (UCHAR)tcrop(r, (TINT32)0, (TINT32)255); - app.g = (UCHAR)tcrop(g, (TINT32)0, (TINT32)255); - app.b = (UCHAR)tcrop(b, (TINT32)0, (TINT32)255); - //app.m = (UCHAR)tcrop (m, (TINT32)0, (TINT32)255); - app.m = upPix->m; - } else - app = *upPix; - overPix(*outPix, *downPix, app); - } - FOR_EACH_PIXEL_32_END_LOOP - } else { - TRaster64P up64 = rup; - TRaster64P down64 = rdown; - TRaster64P out64 = rout; - - if (up64 && down64 && out64) { - FOR_EACH_PIXEL_64_BEGIN_LOOP - - if (upPix->m) { - TPixel64 app; - if (downPix->m) { - TINT32 r, g, b, m; - TPixel64 tmpPix; - tmpPix = depremultiply(*downPix); - r = tmpPix.r + upPix->r - 65535; - g = tmpPix.g + upPix->g - 65535; - b = tmpPix.b + upPix->b - 65535; - m = tmpPix.m + upPix->m - 65535; - - app.r = (USHORT)tcrop(r, 0, 0xffff); - app.g = (USHORT)tcrop(g, 0, 0xffff); - app.b = (USHORT)tcrop(b, 0, 0xffff); - //app.m = (UCHAR)tcrop (m, (TINT32)0, (TINT32)255); - app.m = upPix->m; - } else - app = *upPix; - overPix(*outPix, *downPix, app); - } - - FOR_EACH_PIXEL_64_END_LOOP - } else { - TRasterGR8P up8 = rup; - TRasterGR8P down8 = rdown; - TRasterGR8P out8 = rout; - - if (up8 && down8 && out8) { - FOR_EACH_PIXEL_8_BEGIN_LOOP - USHORT value = troundp(upPix->value + downPix->value - 255); - - outPix->value = (UCHAR)tcrop(value, 0, 255); - - FOR_EACH_PIXEL_8_END_LOOP - } else - throw TRopException("TRop::max invalid raster combination"); - } - } +void TRop::linearburn(const TRasterP &rup, const TRasterP &rdown, + const TRasterP &rout) { + TRaster32P up32 = rup; + TRaster32P down32 = rdown; + TRaster32P out32 = rout; + + if (up32 && down32 && out32) { + FOR_EACH_PIXEL_32_BEGIN_LOOP + if (upPix->m) { + TPixel32 app; + if (downPix->m) { + TINT32 r, g, b, m; + TPixel32 tmpPix; + tmpPix = depremultiply(*downPix); + r = tmpPix.r + upPix->r - 255; + g = tmpPix.g + upPix->g - 255; + b = tmpPix.b + upPix->b - 255; + m = tmpPix.m + upPix->m - 255; + + app.r = (UCHAR)tcrop(r, (TINT32)0, (TINT32)255); + app.g = (UCHAR)tcrop(g, (TINT32)0, (TINT32)255); + app.b = (UCHAR)tcrop(b, (TINT32)0, (TINT32)255); + // app.m = (UCHAR)tcrop (m, (TINT32)0, (TINT32)255); + app.m = upPix->m; + } else + app = *upPix; + overPix(*outPix, *downPix, app); + } + FOR_EACH_PIXEL_32_END_LOOP + } else { + TRaster64P up64 = rup; + TRaster64P down64 = rdown; + TRaster64P out64 = rout; + + if (up64 && down64 && out64) { + FOR_EACH_PIXEL_64_BEGIN_LOOP + + if (upPix->m) { + TPixel64 app; + if (downPix->m) { + TINT32 r, g, b, m; + TPixel64 tmpPix; + tmpPix = depremultiply(*downPix); + r = tmpPix.r + upPix->r - 65535; + g = tmpPix.g + upPix->g - 65535; + b = tmpPix.b + upPix->b - 65535; + m = tmpPix.m + upPix->m - 65535; + + app.r = (USHORT)tcrop(r, 0, 0xffff); + app.g = (USHORT)tcrop(g, 0, 0xffff); + app.b = (USHORT)tcrop(b, 0, 0xffff); + // app.m = (UCHAR)tcrop (m, (TINT32)0, (TINT32)255); + app.m = upPix->m; + } else + app = *upPix; + overPix(*outPix, *downPix, app); + } + + FOR_EACH_PIXEL_64_END_LOOP + } else { + TRasterGR8P up8 = rup; + TRasterGR8P down8 = rdown; + TRasterGR8P out8 = rout; + + if (up8 && down8 && out8) { + FOR_EACH_PIXEL_8_BEGIN_LOOP + USHORT value = troundp(upPix->value + downPix->value - 255); + + outPix->value = (UCHAR)tcrop(value, 0, 255); + + FOR_EACH_PIXEL_8_END_LOOP + } else + throw TRopException("TRop::max invalid raster combination"); + } + } } //----------------------------------------------------------------------------- -void TRop::overlay(const TRasterP &rup, const TRasterP &rdown, const TRasterP &rout) -{ - TRaster32P up32 = rup; - TRaster32P down32 = rdown; - TRaster32P out32 = rout; - - if (up32 && down32 && out32) { - FOR_EACH_PIXEL_32_BEGIN_LOOP - if (upPix->m) { - TPixel32 app; - TPixel32 tmpPix, tmp2Pix; - if (downPix->m) { - tmpPix = *downPix; - tmp2Pix = depremultiply(*upPix); - if (tmpPix.r < 128) - app.r = troundp(2 * tmp2Pix.r * (tmpPix.r / 255.0)); - else { - SHORT r = 255 * (1 - 2 * (1.0 - tmpPix.r / 255.0) * (1.0 - tmp2Pix.r / 255.0)); - app.r = (UCHAR)tcrop(r, 0, 255); - } - if (tmpPix.g < 128) - app.g = troundp(2 * tmp2Pix.g * (tmpPix.g / 255.0)); - else { - SHORT g = 255 * (1 - 2 * (1.0 - tmpPix.g / 255.0) * (1.0 - tmp2Pix.g / 255.0)); - app.g = (UCHAR)tcrop(g, 0, 255); - } - if (tmpPix.b < 128) - app.b = troundp(2 * tmp2Pix.b * (tmpPix.b / 255.0)); - else { - SHORT b = 255 * (1 - 2 * (1.0 - tmpPix.b / 255.0) * (1.0 - tmp2Pix.b / 255.0)); - app.b = (UCHAR)tcrop(b, 0, 255); - } - app.m = tmp2Pix.m; - app = premultiply(app); - } else - app = *upPix; - overPix(*outPix, *downPix, app); - } - FOR_EACH_PIXEL_32_END_LOOP - } else { - TRaster64P up64 = rup; - TRaster64P down64 = rdown; - TRaster64P out64 = rout; - - if (up64 && down64 && out64) { - FOR_EACH_PIXEL_64_BEGIN_LOOP - - if (upPix->m) { - TPixel64 app; - TPixel64 tmpPix, tmp2Pix; - if (downPix->m) { - tmpPix = *downPix; - tmp2Pix = depremultiply(*upPix); - if (tmpPix.r < 32768) - app.r = troundp(2 * tmp2Pix.r * (tmpPix.r / 65535.0)); - else { - SHORT r = 65535 * (1 - 2 * (1.0 - tmpPix.r / 65535.0) * (1.0 - tmp2Pix.r / 65535.0)); - app.r = (USHORT)tcrop(r, 0, 65535); - } - if (tmpPix.g < 32768) - app.g = troundp(2 * tmp2Pix.g * (tmpPix.g / 65535.0)); - else { - SHORT g = 65535 * (1 - 2 * (1.0 - tmpPix.g / 65535.0) * (1.0 - tmp2Pix.g / 65535.0)); - app.g = (USHORT)tcrop(g, 0, 65535); - } - if (tmpPix.b < 32768) - app.b = troundp(2 * tmp2Pix.b * (tmpPix.b / 65535.0)); - else { - SHORT b = 65535 * (1 - 2 * (1.0 - tmpPix.b / 65535.0) * (1.0 - tmp2Pix.b / 65535.0)); - app.b = (USHORT)tcrop(b, 0, 65535); - } - app.m = tmp2Pix.m; - app = premultiply(app); - } else - app = *upPix; - overPix(*outPix, *downPix, app); - } - FOR_EACH_PIXEL_64_END_LOOP - } else { - TRasterGR8P up8 = rup; - TRasterGR8P down8 = rdown; - TRasterGR8P out8 = rout; - - if (up8 && down8 && out8) { - FOR_EACH_PIXEL_8_BEGIN_LOOP - - USHORT value; - if (downPix->value < 128) - value = troundp(2 * upPix->value * (downPix->value / 255.0)); - else - value = 255 * (1 - 2 * (1.0 - downPix->value / 255.0) * (1.0 - upPix->value / 255.0)); - outPix->value = (UCHAR)tcrop(value, 0, 255); - - FOR_EACH_PIXEL_8_END_LOOP - } else - throw TRopException("TRop::max invalid raster combination"); - } - } +void TRop::overlay(const TRasterP &rup, const TRasterP &rdown, + const TRasterP &rout) { + TRaster32P up32 = rup; + TRaster32P down32 = rdown; + TRaster32P out32 = rout; + + if (up32 && down32 && out32) { + FOR_EACH_PIXEL_32_BEGIN_LOOP + if (upPix->m) { + TPixel32 app; + TPixel32 tmpPix, tmp2Pix; + if (downPix->m) { + tmpPix = *downPix; + tmp2Pix = depremultiply(*upPix); + if (tmpPix.r < 128) + app.r = troundp(2 * tmp2Pix.r * (tmpPix.r / 255.0)); + else { + SHORT r = + 255 * + (1 - 2 * (1.0 - tmpPix.r / 255.0) * (1.0 - tmp2Pix.r / 255.0)); + app.r = (UCHAR)tcrop(r, 0, 255); + } + if (tmpPix.g < 128) + app.g = troundp(2 * tmp2Pix.g * (tmpPix.g / 255.0)); + else { + SHORT g = + 255 * + (1 - 2 * (1.0 - tmpPix.g / 255.0) * (1.0 - tmp2Pix.g / 255.0)); + app.g = (UCHAR)tcrop(g, 0, 255); + } + if (tmpPix.b < 128) + app.b = troundp(2 * tmp2Pix.b * (tmpPix.b / 255.0)); + else { + SHORT b = + 255 * + (1 - 2 * (1.0 - tmpPix.b / 255.0) * (1.0 - tmp2Pix.b / 255.0)); + app.b = (UCHAR)tcrop(b, 0, 255); + } + app.m = tmp2Pix.m; + app = premultiply(app); + } else + app = *upPix; + overPix(*outPix, *downPix, app); + } + FOR_EACH_PIXEL_32_END_LOOP + } else { + TRaster64P up64 = rup; + TRaster64P down64 = rdown; + TRaster64P out64 = rout; + + if (up64 && down64 && out64) { + FOR_EACH_PIXEL_64_BEGIN_LOOP + + if (upPix->m) { + TPixel64 app; + TPixel64 tmpPix, tmp2Pix; + if (downPix->m) { + tmpPix = *downPix; + tmp2Pix = depremultiply(*upPix); + if (tmpPix.r < 32768) + app.r = troundp(2 * tmp2Pix.r * (tmpPix.r / 65535.0)); + else { + SHORT r = 65535 * (1 - + 2 * (1.0 - tmpPix.r / 65535.0) * + (1.0 - tmp2Pix.r / 65535.0)); + app.r = (USHORT)tcrop(r, 0, 65535); + } + if (tmpPix.g < 32768) + app.g = troundp(2 * tmp2Pix.g * (tmpPix.g / 65535.0)); + else { + SHORT g = 65535 * (1 - + 2 * (1.0 - tmpPix.g / 65535.0) * + (1.0 - tmp2Pix.g / 65535.0)); + app.g = (USHORT)tcrop(g, 0, 65535); + } + if (tmpPix.b < 32768) + app.b = troundp(2 * tmp2Pix.b * (tmpPix.b / 65535.0)); + else { + SHORT b = 65535 * (1 - + 2 * (1.0 - tmpPix.b / 65535.0) * + (1.0 - tmp2Pix.b / 65535.0)); + app.b = (USHORT)tcrop(b, 0, 65535); + } + app.m = tmp2Pix.m; + app = premultiply(app); + } else + app = *upPix; + overPix(*outPix, *downPix, app); + } + FOR_EACH_PIXEL_64_END_LOOP + } else { + TRasterGR8P up8 = rup; + TRasterGR8P down8 = rdown; + TRasterGR8P out8 = rout; + + if (up8 && down8 && out8) { + FOR_EACH_PIXEL_8_BEGIN_LOOP + + USHORT value; + if (downPix->value < 128) + value = troundp(2 * upPix->value * (downPix->value / 255.0)); + else + value = 255 * (1 - + 2 * (1.0 - downPix->value / 255.0) * + (1.0 - upPix->value / 255.0)); + outPix->value = (UCHAR)tcrop(value, 0, 255); + + FOR_EACH_PIXEL_8_END_LOOP + } else + throw TRopException("TRop::max invalid raster combination"); + } + } } //----------------------------------------------------------------------------- -void TRop::premultiply(const TRasterP &ras) -{ - ras->lock(); - TRaster32P ras32 = ras; - if (ras32) { - TPixel32 *endPix, *upPix = 0, *upRow = ras32->pixels(); - TPixel32 *lastPix = upRow + ras32->getWrap() * (ras32->getLy() - 1) + ras32->getLx(); - - while (upPix < lastPix) { - upPix = upRow; - endPix = upPix + ras32->getLx(); - while (upPix < endPix) { - premult(*upPix); - ++upPix; - } - upRow += ras32->getWrap(); - } - } else { - TRaster64P ras64 = ras; - if (ras64) { - TPixel64 *endPix, *upPix = 0, *upRow = ras64->pixels(); - TPixel64 *lastPix = upRow + ras64->getWrap() * (ras64->getLy() - 1) + ras64->getLx(); - - while (upPix < lastPix) { - upPix = upRow; - endPix = upPix + ras64->getLx(); - while (upPix < endPix) { - premult(*upPix); - ++upPix; - } - upRow += ras64->getWrap(); - } - } else { - ras->unlock(); - throw TException("TRop::premultiply invalid raster type"); - } - } - ras->unlock(); +void TRop::premultiply(const TRasterP &ras) { + ras->lock(); + TRaster32P ras32 = ras; + if (ras32) { + TPixel32 *endPix, *upPix = 0, *upRow = ras32->pixels(); + TPixel32 *lastPix = + upRow + ras32->getWrap() * (ras32->getLy() - 1) + ras32->getLx(); + + while (upPix < lastPix) { + upPix = upRow; + endPix = upPix + ras32->getLx(); + while (upPix < endPix) { + premult(*upPix); + ++upPix; + } + upRow += ras32->getWrap(); + } + } else { + TRaster64P ras64 = ras; + if (ras64) { + TPixel64 *endPix, *upPix = 0, *upRow = ras64->pixels(); + TPixel64 *lastPix = + upRow + ras64->getWrap() * (ras64->getLy() - 1) + ras64->getLx(); + + while (upPix < lastPix) { + upPix = upRow; + endPix = upPix + ras64->getLx(); + while (upPix < endPix) { + premult(*upPix); + ++upPix; + } + upRow += ras64->getWrap(); + } + } else { + ras->unlock(); + throw TException("TRop::premultiply invalid raster type"); + } + } + ras->unlock(); } //----------------------------------------------------------------------------- -void TRop::depremultiply(const TRasterP &ras) -{ - ras->lock(); - TRaster32P ras32 = ras; - if (ras32) { - TPixel32 *endPix, *upPix = 0, *upRow = ras32->pixels(); - TPixel32 *lastPix = upRow + ras32->getWrap() * (ras32->getLy() - 1) + ras32->getLx(); - - while (upPix < lastPix) { - upPix = upRow; - endPix = upPix + ras32->getLx(); - while (upPix < endPix) { - depremult(*upPix); - ++upPix; - } - upRow += ras32->getWrap(); - } - } else { - TRaster64P ras64 = ras; - if (ras64) { - TPixel64 *endPix, *upPix = 0, *upRow = ras64->pixels(); - TPixel64 *lastPix = upRow + ras64->getWrap() * (ras64->getLy() - 1) + ras64->getLx(); - - while (upPix < lastPix) { - upPix = upRow; - endPix = upPix + ras64->getLx(); - while (upPix < endPix) { - depremult(*upPix); - ++upPix; - } - upRow += ras64->getWrap(); - } - } else { - ras->unlock(); - throw TException("TRop::depremultiply invalid raster type"); - } - } - ras->unlock(); +void TRop::depremultiply(const TRasterP &ras) { + ras->lock(); + TRaster32P ras32 = ras; + if (ras32) { + TPixel32 *endPix, *upPix = 0, *upRow = ras32->pixels(); + TPixel32 *lastPix = + upRow + ras32->getWrap() * (ras32->getLy() - 1) + ras32->getLx(); + + while (upPix < lastPix) { + upPix = upRow; + endPix = upPix + ras32->getLx(); + while (upPix < endPix) { + depremult(*upPix); + ++upPix; + } + upRow += ras32->getWrap(); + } + } else { + TRaster64P ras64 = ras; + if (ras64) { + TPixel64 *endPix, *upPix = 0, *upRow = ras64->pixels(); + TPixel64 *lastPix = + upRow + ras64->getWrap() * (ras64->getLy() - 1) + ras64->getLx(); + + while (upPix < lastPix) { + upPix = upRow; + endPix = upPix + ras64->getLx(); + while (upPix < endPix) { + depremult(*upPix); + ++upPix; + } + upRow += ras64->getWrap(); + } + } else { + ras->unlock(); + throw TException("TRop::depremultiply invalid raster type"); + } + } + ras->unlock(); } //----------------------------------------------------------------------------- -void TRop::whiteTransp(const TRasterP &ras) -{ - ras->lock(); - TRaster32P ras32 = ras; - if (ras32) { - TPixel32 *endPix, *upPix = 0, *upRow = ras32->pixels(); - TPixel32 *lastPix = upRow + ras32->getWrap() * (ras32->getLy() - 1) + ras32->getLx(); - - while (upPix < lastPix) { - upPix = upRow; - endPix = upPix + ras32->getLx(); - while (upPix < endPix) { - if (*upPix == TPixel::White) - *upPix = TPixel::Transparent; - ++upPix; - } - upRow += ras32->getWrap(); - } - } else { - TRaster64P ras64 = ras; - if (ras64) { - TPixel64 *endPix, *upPix = 0, *upRow = ras64->pixels(); - TPixel64 *lastPix = upRow + ras64->getWrap() * (ras64->getLy() - 1) + ras64->getLx(); - - while (upPix < lastPix) { - upPix = upRow; - endPix = upPix + ras64->getLx(); - while (upPix < endPix) { - if (*upPix == TPixel64::White) - *upPix = TPixel64::Transparent; - ++upPix; - } - upRow += ras64->getWrap(); - } - } else { - ras->unlock(); - throw TException("TRop::premultiply invalid raster type"); - } - } - ras->unlock(); +void TRop::whiteTransp(const TRasterP &ras) { + ras->lock(); + TRaster32P ras32 = ras; + if (ras32) { + TPixel32 *endPix, *upPix = 0, *upRow = ras32->pixels(); + TPixel32 *lastPix = + upRow + ras32->getWrap() * (ras32->getLy() - 1) + ras32->getLx(); + + while (upPix < lastPix) { + upPix = upRow; + endPix = upPix + ras32->getLx(); + while (upPix < endPix) { + if (*upPix == TPixel::White) *upPix = TPixel::Transparent; + ++upPix; + } + upRow += ras32->getWrap(); + } + } else { + TRaster64P ras64 = ras; + if (ras64) { + TPixel64 *endPix, *upPix = 0, *upRow = ras64->pixels(); + TPixel64 *lastPix = + upRow + ras64->getWrap() * (ras64->getLy() - 1) + ras64->getLx(); + + while (upPix < lastPix) { + upPix = upRow; + endPix = upPix + ras64->getLx(); + while (upPix < endPix) { + if (*upPix == TPixel64::White) *upPix = TPixel64::Transparent; + ++upPix; + } + upRow += ras64->getWrap(); + } + } else { + ras->unlock(); + throw TException("TRop::premultiply invalid raster type"); + } + } + ras->unlock(); } //----------------------------------------------------------------------------- template -const double *premultiplyTable() -{ - static double *table = 0; - if (!table) { - int maxChannelValue = (std::numeric_limits::max)(); - int chanValuesCount = maxChannelValue + 1; - double maxD = maxChannelValue; +const double *premultiplyTable() { + static double *table = 0; + if (!table) { + int maxChannelValue = (std::numeric_limits::max)(); + int chanValuesCount = maxChannelValue + 1; + double maxD = maxChannelValue; - table = new double[chanValuesCount]; + table = new double[chanValuesCount]; - for (int i = 0; i < chanValuesCount; ++i) - table[i] = i / maxD; - } + for (int i = 0; i < chanValuesCount; ++i) table[i] = i / maxD; + } - return table; + return table; } template DVAPI const double *premultiplyTable(); @@ -1595,22 +1643,20 @@ template DVAPI const double *premultiplyTable(); //----------------------------------------------------------------------------- template -const double *depremultiplyTable() -{ - static double *table = 0; - if (!table) { - int maxChannelValue = (std::numeric_limits::max)(); - int chanValuesCount = maxChannelValue + 1; - double maxD = maxChannelValue; - - table = new double[chanValuesCount]; - - table[0] = 0.0; - for (int i = 1; i < chanValuesCount; ++i) - table[i] = maxD / i; - } - - return table; +const double *depremultiplyTable() { + static double *table = 0; + if (!table) { + int maxChannelValue = (std::numeric_limits::max)(); + int chanValuesCount = maxChannelValue + 1; + double maxD = maxChannelValue; + + table = new double[chanValuesCount]; + + table[0] = 0.0; + for (int i = 1; i < chanValuesCount; ++i) table[i] = maxD / i; + } + + return table; } template DVAPI const double *depremultiplyTable(); diff --git a/toonz/sources/common/trop/tover.cpp b/toonz/sources/common/trop/tover.cpp index 0291c1c..d03825b 100644 --- a/toonz/sources/common/trop/tover.cpp +++ b/toonz/sources/common/trop/tover.cpp @@ -8,508 +8,487 @@ #include "tpalette.h" #ifdef _WIN32 -#include // per SSE2 +#include // per SSE2 #endif //----------------------------------------------------------------------------- -namespace -{ +namespace { -inline bool transp(const TPixel32 &p) -{ - return p.m == 0; -} -inline bool transp(const TPixel64 &p) -{ - return p.m == 0; -} +inline bool transp(const TPixel32 &p) { return p.m == 0; } +inline bool transp(const TPixel64 &p) { return p.m == 0; } //----------------------------------------------------------------------------- -inline bool opaque(const TPixel32 &p) -{ - return p.m == 0xff; -} -inline bool opaque(const TPixel64 &p) -{ - return p.m == 0xffff; -} +inline bool opaque(const TPixel32 &p) { return p.m == 0xff; } +inline bool opaque(const TPixel64 &p) { return p.m == 0xffff; } //----------------------------------------------------------------------------- #define MODO2 #define VELOCE template -void do_overT3(TRasterPT rout, const TRasterPT &rdn, const TRasterPT &rup) -{ - - for (int y = 0; y < rout->getLy(); y++) { +void do_overT3(TRasterPT rout, const TRasterPT &rdn, + const TRasterPT &rup) { + for (int y = 0; y < rout->getLy(); y++) { #ifdef MODO1 - const T *dn_pix = rdn->pixels(y); - const T *up_pix = rup->pixels(y); - T *out_pix = rout->pixels(y); + const T *dn_pix = rdn->pixels(y); + const T *up_pix = rup->pixels(y); + T *out_pix = rout->pixels(y); #else #ifdef MODO2 - const T *dn_pix = ((T *)rdn->getRawData()) + y * rdn->getWrap(); - const T *up_pix = ((T *)rup->getRawData()) + y * rup->getWrap(); + const T *dn_pix = ((T *)rdn->getRawData()) + y * rdn->getWrap(); + const T *up_pix = ((T *)rup->getRawData()) + y * rup->getWrap(); - T *out_pix = ((T *)rout->getRawData()) + y * rout->getWrap(); + T *out_pix = ((T *)rout->getRawData()) + y * rout->getWrap(); #endif #endif - const T *dn_limit = dn_pix + rdn->getLx(); - for (; dn_pix < dn_limit; dn_pix++, up_pix++, out_pix++) { + const T *dn_limit = dn_pix + rdn->getLx(); + for (; dn_pix < dn_limit; dn_pix++, up_pix++, out_pix++) { #ifdef VELOCE - if (transp(*up_pix)) - *out_pix = *dn_pix; - else if (opaque(*up_pix)) - *out_pix = *up_pix; - else { - *out_pix = overPix(*dn_pix, *up_pix); - } + if (transp(*up_pix)) + *out_pix = *dn_pix; + else if (opaque(*up_pix)) + *out_pix = *up_pix; + else { + *out_pix = overPix(*dn_pix, *up_pix); + } #else - T topval = *up_pix; - if (transp(topval)) - *out_pix = *dn_pix; - else if (opaque(topval)) - *out_pix = topval; - else { - *out_pix = overPix(*dn_pix, topval); - } + T topval = *up_pix; + if (transp(topval)) + *out_pix = *dn_pix; + else if (opaque(topval)) + *out_pix = topval; + else { + *out_pix = overPix(*dn_pix, topval); + } #endif - } - } + } + } } //----------------------------------------------------------------------------- template void do_over(TRasterPT rout, const TRasterPT &rdn, - const TRasterPT &rup, const TRasterGR8P rmask) -{ - - for (int y = 0; y < rout->getLy(); y++) { - const PixTypeDn *dn_pix = ((PixTypeDn *)rdn->getRawData()) + y * rdn->getWrap(); - const PixTypeUp *up_pix = ((PixTypeUp *)rup->getRawData()) + y * rup->getWrap(); - - PixTypeOut *out_pix = ((PixTypeOut *)rout->getRawData()) + y * rout->getWrap(); - TPixelGR8 *mask_pix = ((TPixelGR8 *)rmask->getRawData()) + y * rmask->getWrap(); - - const PixTypeDn *dn_limit = dn_pix + rout->getLx(); - for (; dn_pix < dn_limit; dn_pix++, up_pix++, out_pix++, mask_pix++) { - if (mask_pix->value == 0x00) - *out_pix = *dn_pix; - else if (mask_pix->value == 0xff) - *out_pix = *up_pix; - else { - PixTypeUp p(*up_pix); - p.m = mask_pix->value; - *out_pix = overPix(*dn_pix, p); //hei! - } - } - } + const TRasterPT &rup, const TRasterGR8P rmask) { + for (int y = 0; y < rout->getLy(); y++) { + const PixTypeDn *dn_pix = + ((PixTypeDn *)rdn->getRawData()) + y * rdn->getWrap(); + const PixTypeUp *up_pix = + ((PixTypeUp *)rup->getRawData()) + y * rup->getWrap(); + + PixTypeOut *out_pix = + ((PixTypeOut *)rout->getRawData()) + y * rout->getWrap(); + TPixelGR8 *mask_pix = + ((TPixelGR8 *)rmask->getRawData()) + y * rmask->getWrap(); + + const PixTypeDn *dn_limit = dn_pix + rout->getLx(); + for (; dn_pix < dn_limit; dn_pix++, up_pix++, out_pix++, mask_pix++) { + if (mask_pix->value == 0x00) + *out_pix = *dn_pix; + else if (mask_pix->value == 0xff) + *out_pix = *up_pix; + else { + PixTypeUp p(*up_pix); + p.m = mask_pix->value; + *out_pix = overPix(*dn_pix, p); // hei! + } + } + } } //----------------------------------------------------------------------------- -void do_over(TRasterCM32P rout, const TRasterCM32P &rup) -{ - assert(rout->getSize() == rup->getSize()); - for (int y = 0; y < rout->getLy(); y++) { - TPixelCM32 *out_pix = rout->pixels(y); - TPixelCM32 *const out_end = out_pix + rout->getLx(); - const TPixelCM32 *up_pix = rup->pixels(y); - - for (; out_pix < out_end; ++out_pix, ++up_pix) { - if (!up_pix->isPureInk() && - up_pix->getPaint() != 0) // BackgroundStyle) - *out_pix = *up_pix; - else if (!up_pix->isPurePaint()) { - TUINT32 *outl = (TUINT32 *)out_pix, *upl = (TUINT32 *)up_pix; - - *outl = ((*upl) & (TPixelCM32::getInkMask())) | - ((*outl) & (TPixelCM32::getPaintMask())) | - std::min(up_pix->getTone(), out_pix->getTone()); - } - } - } +void do_over(TRasterCM32P rout, const TRasterCM32P &rup) { + assert(rout->getSize() == rup->getSize()); + for (int y = 0; y < rout->getLy(); y++) { + TPixelCM32 *out_pix = rout->pixels(y); + TPixelCM32 *const out_end = out_pix + rout->getLx(); + const TPixelCM32 *up_pix = rup->pixels(y); + + for (; out_pix < out_end; ++out_pix, ++up_pix) { + if (!up_pix->isPureInk() && up_pix->getPaint() != 0) // BackgroundStyle) + *out_pix = *up_pix; + else if (!up_pix->isPurePaint()) { + TUINT32 *outl = (TUINT32 *)out_pix, *upl = (TUINT32 *)up_pix; + + *outl = ((*upl) & (TPixelCM32::getInkMask())) | + ((*outl) & (TPixelCM32::getPaintMask())) | + std::min(up_pix->getTone(), out_pix->getTone()); + } + } + } } //----------------------------------------------------------------------------- template -void do_overT2(TRasterPT rout, const TRasterPT &rup) -{ - UINT max = T::maxChannelValue; - double maxD = max; - - assert(rout->getSize() == rup->getSize()); - for (int y = 0; y < rout->getLy(); y++) { - T *out_pix = rout->pixels(y); - T *const out_end = out_pix + rout->getLx(); - const T *up_pix = rup->pixels(y); - - for (; out_pix < out_end; ++out_pix, ++up_pix) { - if (up_pix->m == max) - *out_pix = *up_pix; - else if (up_pix->m > 0) { - TUINT32 r, g, b; - r = up_pix->r + (out_pix->r * (max - up_pix->m)) / maxD; - g = up_pix->g + (out_pix->g * (max - up_pix->m)) / maxD; - b = up_pix->b + (out_pix->b * (max - up_pix->m)) / maxD; - - out_pix->r = (r < max) ? (Q)r : (Q)max; - out_pix->g = (g < max) ? (Q)g : (Q)max; - out_pix->b = (b < max) ? (Q)b : (Q)max; - out_pix->m = up_pix->m + (out_pix->m * (max - up_pix->m)) / maxD; - } - } - } +void do_overT2(TRasterPT rout, const TRasterPT &rup) { + UINT max = T::maxChannelValue; + double maxD = max; + + assert(rout->getSize() == rup->getSize()); + for (int y = 0; y < rout->getLy(); y++) { + T *out_pix = rout->pixels(y); + T *const out_end = out_pix + rout->getLx(); + const T *up_pix = rup->pixels(y); + + for (; out_pix < out_end; ++out_pix, ++up_pix) { + if (up_pix->m == max) + *out_pix = *up_pix; + else if (up_pix->m > 0) { + TUINT32 r, g, b; + r = up_pix->r + (out_pix->r * (max - up_pix->m)) / maxD; + g = up_pix->g + (out_pix->g * (max - up_pix->m)) / maxD; + b = up_pix->b + (out_pix->b * (max - up_pix->m)) / maxD; + + out_pix->r = (r < max) ? (Q)r : (Q)max; + out_pix->g = (g < max) ? (Q)g : (Q)max; + out_pix->b = (b < max) ? (Q)b : (Q)max; + out_pix->m = up_pix->m + (out_pix->m * (max - up_pix->m)) / maxD; + } + } + } } //----------------------------------------------------------------------------- #ifdef _WIN32 -void do_over_SSE2(TRaster32P rout, const TRaster32P &rup) -{ - __m128i zeros = _mm_setzero_si128(); - __m128i out_pix_packed_i, up_pix_packed_i; - __m128 out_pix_packed, up_pix_packed; - - float maxChannelValue = 255.0; - float maxChannelValueInv = 1.0f / maxChannelValue; - - __m128 maxChanneValue_packed = _mm_load1_ps(&maxChannelValue); - - assert(rout->getSize() == rup->getSize()); - for (int y = 0; y < rout->getLy(); y++) { - TPixel32 *out_pix = rout->pixels(y); - TPixel32 *const out_end = out_pix + rout->getLx(); - const TPixel32 *up_pix = rup->pixels(y); - - for (; out_pix < out_end; ++out_pix, ++up_pix) { - if (up_pix->m == 0xff) - *out_pix = *up_pix; - else if (up_pix->m > 0) { - float factor = (255.0f - up_pix->m) / 255.0f; - __m128 factor_packed = _mm_load1_ps(&factor); - - // carica up_pix e out_pix in due registri a 128 bit - up_pix_packed_i = _mm_unpacklo_epi8(_mm_cvtsi32_si128(*(DWORD *)up_pix), zeros); - up_pix_packed = _mm_cvtepi32_ps(_mm_unpacklo_epi16(up_pix_packed_i, zeros)); - - out_pix_packed_i = _mm_unpacklo_epi8(_mm_cvtsi32_si128(*(DWORD *)out_pix), zeros); - out_pix_packed = _mm_cvtepi32_ps(_mm_unpacklo_epi16(out_pix_packed_i, zeros)); - - out_pix_packed = _mm_add_ps(up_pix_packed, _mm_mul_ps(out_pix_packed, factor_packed)); - out_pix_packed = _mm_min_ps(maxChanneValue_packed, out_pix_packed); - - out_pix_packed_i = _mm_cvtps_epi32(out_pix_packed); - out_pix_packed_i = _mm_packs_epi32(out_pix_packed_i, zeros); - out_pix_packed_i = _mm_packus_epi16(out_pix_packed_i, zeros); - *(DWORD *)(out_pix) = _mm_cvtsi128_si32(out_pix_packed_i); - } - } - } +void do_over_SSE2(TRaster32P rout, const TRaster32P &rup) { + __m128i zeros = _mm_setzero_si128(); + __m128i out_pix_packed_i, up_pix_packed_i; + __m128 out_pix_packed, up_pix_packed; + + float maxChannelValue = 255.0; + float maxChannelValueInv = 1.0f / maxChannelValue; + + __m128 maxChanneValue_packed = _mm_load1_ps(&maxChannelValue); + + assert(rout->getSize() == rup->getSize()); + for (int y = 0; y < rout->getLy(); y++) { + TPixel32 *out_pix = rout->pixels(y); + TPixel32 *const out_end = out_pix + rout->getLx(); + const TPixel32 *up_pix = rup->pixels(y); + + for (; out_pix < out_end; ++out_pix, ++up_pix) { + if (up_pix->m == 0xff) + *out_pix = *up_pix; + else if (up_pix->m > 0) { + float factor = (255.0f - up_pix->m) / 255.0f; + __m128 factor_packed = _mm_load1_ps(&factor); + + // carica up_pix e out_pix in due registri a 128 bit + up_pix_packed_i = + _mm_unpacklo_epi8(_mm_cvtsi32_si128(*(DWORD *)up_pix), zeros); + up_pix_packed = + _mm_cvtepi32_ps(_mm_unpacklo_epi16(up_pix_packed_i, zeros)); + + out_pix_packed_i = + _mm_unpacklo_epi8(_mm_cvtsi32_si128(*(DWORD *)out_pix), zeros); + out_pix_packed = + _mm_cvtepi32_ps(_mm_unpacklo_epi16(out_pix_packed_i, zeros)); + + out_pix_packed = _mm_add_ps(up_pix_packed, + _mm_mul_ps(out_pix_packed, factor_packed)); + out_pix_packed = _mm_min_ps(maxChanneValue_packed, out_pix_packed); + + out_pix_packed_i = _mm_cvtps_epi32(out_pix_packed); + out_pix_packed_i = _mm_packs_epi32(out_pix_packed_i, zeros); + out_pix_packed_i = _mm_packus_epi16(out_pix_packed_i, zeros); + *(DWORD *)(out_pix) = _mm_cvtsi128_si32(out_pix_packed_i); + } + } + } } #endif //----------------------------------------------------------------------------- -void do_over(TRaster32P rout, const TRasterGR8P &rup) -{ - assert(rout->getSize() == rup->getSize()); - for (int y = rout->getLy(); --y >= 0;) { - TPixel32 *out_pix = rout->pixels(y); - TPixel32 *const out_end = out_pix + rout->getLx(); - const TPixelGR8 *up_pix = rup->pixels(y); - - for (; out_pix < out_end; ++out_pix, ++up_pix) { - int v = up_pix->value; - out_pix->r = out_pix->r * v / 255; - out_pix->g = out_pix->r; - out_pix->b = out_pix->r; - } - } +void do_over(TRaster32P rout, const TRasterGR8P &rup) { + assert(rout->getSize() == rup->getSize()); + for (int y = rout->getLy(); --y >= 0;) { + TPixel32 *out_pix = rout->pixels(y); + TPixel32 *const out_end = out_pix + rout->getLx(); + const TPixelGR8 *up_pix = rup->pixels(y); + + for (; out_pix < out_end; ++out_pix, ++up_pix) { + int v = up_pix->value; + out_pix->r = out_pix->r * v / 255; + out_pix->g = out_pix->r; + out_pix->b = out_pix->r; + } + } } //----------------------------------------------------------------------------- -void do_over(TRasterGR8P rout, const TRaster32P &rup) -{ - assert(rout->getSize() == rup->getSize()); - for (int y = rout->getLy(); --y >= 0;) { - TPixelGR8 *out_pix = rout->pixels(y); - TPixelGR8 *const out_end = out_pix + rout->getLx(); - const TPixel32 *up_pix = rup->pixels(y); - TPixel32 *temp_pix = new TPixel32(); - for (; out_pix < out_end; ++out_pix, ++up_pix) { - temp_pix->r = out_pix->value; - temp_pix->g = out_pix->value; - temp_pix->b = out_pix->value; - temp_pix->m = 0xff; - TPixel32 out32_pix = overPix(*temp_pix, *up_pix); - *out_pix = out_pix->from(out32_pix); - } - delete temp_pix; - } +void do_over(TRasterGR8P rout, const TRaster32P &rup) { + assert(rout->getSize() == rup->getSize()); + for (int y = rout->getLy(); --y >= 0;) { + TPixelGR8 *out_pix = rout->pixels(y); + TPixelGR8 *const out_end = out_pix + rout->getLx(); + const TPixel32 *up_pix = rup->pixels(y); + TPixel32 *temp_pix = new TPixel32(); + for (; out_pix < out_end; ++out_pix, ++up_pix) { + temp_pix->r = out_pix->value; + temp_pix->g = out_pix->value; + temp_pix->b = out_pix->value; + temp_pix->m = 0xff; + TPixel32 out32_pix = overPix(*temp_pix, *up_pix); + *out_pix = out_pix->from(out32_pix); + } + delete temp_pix; + } } -} // namespace +} // namespace //----------------------------------------------------------------------------- -void do_over(TRaster32P rout, const TRasterGR8P &rup, const TPixel32 &color) -{ - assert(rout->getSize() == rup->getSize()); - for (int y = rout->getLy(); --y >= 0;) { - TPixel32 *out_pix = rout->pixels(y); - TPixel32 *const out_end = out_pix + rout->getLx(); - const TPixelGR8 *up_pix = rup->pixels(y); - - for (; out_pix < out_end; ++out_pix, ++up_pix) { - double v = up_pix->value / 255.0; - TPixel32 up(troundp(v * color.r), troundp(v * color.g), troundp(v * color.b), troundp(v * color.m)); - *out_pix = overPix(*out_pix, up); - } - } +void do_over(TRaster32P rout, const TRasterGR8P &rup, const TPixel32 &color) { + assert(rout->getSize() == rup->getSize()); + for (int y = rout->getLy(); --y >= 0;) { + TPixel32 *out_pix = rout->pixels(y); + TPixel32 *const out_end = out_pix + rout->getLx(); + const TPixelGR8 *up_pix = rup->pixels(y); + + for (; out_pix < out_end; ++out_pix, ++up_pix) { + double v = up_pix->value / 255.0; + TPixel32 up(troundp(v * color.r), troundp(v * color.g), + troundp(v * color.b), troundp(v * color.m)); + *out_pix = overPix(*out_pix, up); + } + } } //----------------------------------------------------------------------------- -void TRop::over(TRaster32P rout, const TRasterGR8P &rup, const TPixel32 &color) -{ - rout->lock(); - do_over(rout, rup, color); - rout->unlock(); +void TRop::over(TRaster32P rout, const TRasterGR8P &rup, + const TPixel32 &color) { + rout->lock(); + do_over(rout, rup, color); + rout->unlock(); } //----------------------------------------------------------------------------- -void TRop::over(const TRasterP &rout, const TRasterP &rdn, const TRasterP &rup) -{ - TRect rect = rout->getBounds() * rdn->getBounds() * rup->getBounds(); - if (rect.isEmpty()) - return; - - TRasterP cRout = rout->extract(rect); - TRasterP cRdn = rdn->extract(rect); - TRasterP cRup = rup->extract(rect); - rout->lock(); - rdn->lock(); - rup->lock(); - TRaster32P rout32 = cRout, rdn32 = cRdn, rup32 = cRup; - TRaster64P rout64 = cRout, rdn64 = cRdn, rup64 = cRup; - if (rout32 && rdn32 && rup32) - do_overT3(rout32, rdn32, rup32); - else if (rout64 && rdn64 && rup64) - do_overT3(rout64, rdn64, rup64); - else { - rout->unlock(); - rdn->unlock(); - rup->unlock(); - throw TRopException("unsupported pixel type"); - } - - rout->unlock(); - rdn->unlock(); - rup->unlock(); +void TRop::over(const TRasterP &rout, const TRasterP &rdn, + const TRasterP &rup) { + TRect rect = rout->getBounds() * rdn->getBounds() * rup->getBounds(); + if (rect.isEmpty()) return; + + TRasterP cRout = rout->extract(rect); + TRasterP cRdn = rdn->extract(rect); + TRasterP cRup = rup->extract(rect); + rout->lock(); + rdn->lock(); + rup->lock(); + TRaster32P rout32 = cRout, rdn32 = cRdn, rup32 = cRup; + TRaster64P rout64 = cRout, rdn64 = cRdn, rup64 = cRup; + if (rout32 && rdn32 && rup32) + do_overT3(rout32, rdn32, rup32); + else if (rout64 && rdn64 && rup64) + do_overT3(rout64, rdn64, rup64); + else { + rout->unlock(); + rdn->unlock(); + rup->unlock(); + throw TRopException("unsupported pixel type"); + } + + rout->unlock(); + rdn->unlock(); + rup->unlock(); } //----------------------------------------------------------------------------- -void TRop::over(const TRasterP &rout, const TRasterP &rup, const TPoint &pos) -{ - TRect outRect(rout->getBounds()); - TRect upRect(rup->getBounds() + pos); - TRect intersection = outRect * upRect; - if (intersection.isEmpty()) - return; +void TRop::over(const TRasterP &rout, const TRasterP &rup, const TPoint &pos) { + TRect outRect(rout->getBounds()); + TRect upRect(rup->getBounds() + pos); + TRect intersection = outRect * upRect; + if (intersection.isEmpty()) return; - TRasterP cRout = rout->extract(intersection); - TRect r = intersection - pos; - TRasterP cRup = rup->extract(r); + TRasterP cRout = rout->extract(intersection); + TRect r = intersection - pos; + TRasterP cRup = rup->extract(r); - TRaster32P rout32 = cRout, rup32 = cRup; - TRaster64P rout64 = cRout, rup64 = cRup; + TRaster32P rout32 = cRout, rup32 = cRup; + TRaster64P rout64 = cRout, rup64 = cRup; - TRasterGR8P rout8 = cRout, rup8 = cRup; + TRasterGR8P rout8 = cRout, rup8 = cRup; - TRasterCM32P routCM32 = cRout, rupCM32 = cRup; + TRasterCM32P routCM32 = cRout, rupCM32 = cRup; - rout->lock(); - rup->lock(); + rout->lock(); + rup->lock(); - // TRaster64P rout64 = rout, rin64 = rin; - if (rout32 && rup32) { + // TRaster64P rout64 = rout, rin64 = rin; + if (rout32 && rup32) { #ifdef _WIN32 - if (TSystem::getCPUExtensions() & TSystem::CpuSupportsSse2) - do_over_SSE2(rout32, rup32); - else + if (TSystem::getCPUExtensions() & TSystem::CpuSupportsSse2) + do_over_SSE2(rout32, rup32); + else #endif - do_overT2(rout32, rup32); - } else if (rout64) { - if (!rup64) { - TRaster64P raux(cRup->getSize()); - TRop::convert(raux, cRup); - rup64 = raux; - } - do_overT2(rout64, rup64); - } else if (rout32 && rup8) - do_over(rout32, rup8); - else if (rout8 && rup32) - do_over(rout8, rup32); - else if (rout8 && rup8) - TRop::copy(rout8, rup8); - else if (routCM32 && rupCM32) - do_over(routCM32, rupCM32); - else { - rout->unlock(); - rup->unlock(); - throw TRopException("unsupported pixel type"); - } - - rout->unlock(); - rup->unlock(); + do_overT2(rout32, rup32); + } else if (rout64) { + if (!rup64) { + TRaster64P raux(cRup->getSize()); + TRop::convert(raux, cRup); + rup64 = raux; + } + do_overT2(rout64, rup64); + } else if (rout32 && rup8) + do_over(rout32, rup8); + else if (rout8 && rup32) + do_over(rout8, rup32); + else if (rout8 && rup8) + TRop::copy(rout8, rup8); + else if (routCM32 && rupCM32) + do_over(routCM32, rupCM32); + else { + rout->unlock(); + rup->unlock(); + throw TRopException("unsupported pixel type"); + } + + rout->unlock(); + rup->unlock(); } //----------------------------------------------------------------------------- -static void addBackground32(TRaster32P ras, const TPixel32 &col) -{ - ras->lock(); - int nrows = ras->getLy(); - while (nrows-- > 0) { - TPixel32 *pix = ras->pixels(nrows); - TPixel32 *endPix = pix + ras->getLx(); - while (pix < endPix) { - *pix = overPix(col, *pix); - pix++; - } - } - ras->unlock(); +static void addBackground32(TRaster32P ras, const TPixel32 &col) { + ras->lock(); + int nrows = ras->getLy(); + while (nrows-- > 0) { + TPixel32 *pix = ras->pixels(nrows); + TPixel32 *endPix = pix + ras->getLx(); + while (pix < endPix) { + *pix = overPix(col, *pix); + pix++; + } + } + ras->unlock(); } //----------------------------------------------------------------------------- -void TRop::addBackground(TRasterP ras, const TPixel32 &col) -{ - TRaster32P ras32 = ras; - if (ras32) - addBackground32(ras32, col); - else - throw TRopException("unsupported pixel type"); +void TRop::addBackground(TRasterP ras, const TPixel32 &col) { + TRaster32P ras32 = ras; + if (ras32) + addBackground32(ras32, col); + else + throw TRopException("unsupported pixel type"); } //=================================================================== -//Usata tinylinetest -static void my_do_over(TRaster32P rout, const TRasterGR8P &rup) -{ - assert(rout->getSize() == rup->getSize()); - for (int y = rout->getLy(); --y >= 0;) { - TPixel32 *out_pix = rout->pixels(y); - TPixel32 *const out_end = out_pix + rout->getLx(); - const TPixelGR8 *up_pix = rup->pixels(y); - - for (; out_pix < out_end; ++out_pix, ++up_pix) { - int v = up_pix->value; - out_pix->r = out_pix->r * v / 255; - out_pix->g = out_pix->r; - out_pix->b = out_pix->r; - } - } +// Usata tinylinetest +static void my_do_over(TRaster32P rout, const TRasterGR8P &rup) { + assert(rout->getSize() == rup->getSize()); + for (int y = rout->getLy(); --y >= 0;) { + TPixel32 *out_pix = rout->pixels(y); + TPixel32 *const out_end = out_pix + rout->getLx(); + const TPixelGR8 *up_pix = rup->pixels(y); + + for (; out_pix < out_end; ++out_pix, ++up_pix) { + int v = up_pix->value; + out_pix->r = out_pix->r * v / 255; + out_pix->g = out_pix->r; + out_pix->b = out_pix->r; + } + } } //=================================================================== -void TRop::over(const TRasterP &out, - const TRasterP &up, - const TAffine &aff, - ResampleFilterType filterType) -{ - out->lock(); - up->lock(); - - if (filterType == ClosestPixel || filterType == Bilinear) - ::quickPut(out, up, aff, filterType); - else { - TRect rasterBounds = up->getBounds(); - TRectD dbounds(rasterBounds.x0, rasterBounds.y0, rasterBounds.x1 + 1, rasterBounds.y1 + 1); - dbounds = aff * dbounds; - TRect bounds(tfloor(dbounds.x0), tfloor(dbounds.y0), tceil(dbounds.x1) - 1, tceil(dbounds.y1) - 1); - TRasterP tmp = up->create(bounds.getLx(), bounds.getLy()); - resample(tmp, up, TTranslation(-bounds.x0, -bounds.y0) * aff, filterType); - over(out, tmp, bounds.getP00()); - } - out->unlock(); - up->unlock(); +void TRop::over(const TRasterP &out, const TRasterP &up, const TAffine &aff, + ResampleFilterType filterType) { + out->lock(); + up->lock(); + + if (filterType == ClosestPixel || filterType == Bilinear) + ::quickPut(out, up, aff, filterType); + else { + TRect rasterBounds = up->getBounds(); + TRectD dbounds(rasterBounds.x0, rasterBounds.y0, rasterBounds.x1 + 1, + rasterBounds.y1 + 1); + dbounds = aff * dbounds; + TRect bounds(tfloor(dbounds.x0), tfloor(dbounds.y0), tceil(dbounds.x1) - 1, + tceil(dbounds.y1) - 1); + TRasterP tmp = up->create(bounds.getLx(), bounds.getLy()); + resample(tmp, up, TTranslation(-bounds.x0, -bounds.y0) * aff, filterType); + over(out, tmp, bounds.getP00()); + } + out->unlock(); + up->unlock(); } -void TRop::over(const TRasterP &out, const TRasterP &up, const TPoint &pos, const TAffine &aff, - ResampleFilterType filterType) -{ - if (aff.isIdentity()) - //simple over with offset - TRop::over(out, up, pos); - else { - TRect rasterBounds = up->getBounds(); - TRectD dbounds(rasterBounds.x0, rasterBounds.y0, rasterBounds.x1, rasterBounds.y1); - dbounds = aff * dbounds; - TRect bounds(tfloor(dbounds.x0), tfloor(dbounds.y0), tceil(dbounds.x1), tceil(dbounds.y1)); - TRasterP tmp = up->create(bounds.getLx(), bounds.getLy()); - resample(tmp, up, TTranslation(-dbounds.getP00()) * aff, filterType); - TRop::over(out, tmp, pos); - } +void TRop::over(const TRasterP &out, const TRasterP &up, const TPoint &pos, + const TAffine &aff, ResampleFilterType filterType) { + if (aff.isIdentity()) + // simple over with offset + TRop::over(out, up, pos); + else { + TRect rasterBounds = up->getBounds(); + TRectD dbounds(rasterBounds.x0, rasterBounds.y0, rasterBounds.x1, + rasterBounds.y1); + dbounds = aff * dbounds; + TRect bounds(tfloor(dbounds.x0), tfloor(dbounds.y0), tceil(dbounds.x1), + tceil(dbounds.y1)); + TRasterP tmp = up->create(bounds.getLx(), bounds.getLy()); + resample(tmp, up, TTranslation(-dbounds.getP00()) * aff, filterType); + TRop::over(out, tmp, pos); + } } -void TRop::over(TRasterP rout, const TRasterCM32P &rup, TPalette *palette, const TPoint &point, const TAffine &aff) -{ - TRaster32P app(rup->getSize()); - TRop::convert(app, rup, palette); - TRop::over(rout, app, point, aff); +void TRop::over(TRasterP rout, const TRasterCM32P &rup, TPalette *palette, + const TPoint &point, const TAffine &aff) { + TRaster32P app(rup->getSize()); + TRop::convert(app, rup, palette); + TRop::over(rout, app, point, aff); } //=================================================================== -void TRop::quickPut(const TRasterP &out, - const TRasterP &up, - const TAffine &aff, - const TPixel32 &colorScale, - bool doPremultiply, bool whiteTransp, bool firstColumn, - bool doRasterDarkenBlendedView) -{ - ::quickPut(out, up, aff, ClosestPixel, colorScale, doPremultiply, whiteTransp, firstColumn, doRasterDarkenBlendedView); +void TRop::quickPut(const TRasterP &out, const TRasterP &up, const TAffine &aff, + const TPixel32 &colorScale, bool doPremultiply, + bool whiteTransp, bool firstColumn, + bool doRasterDarkenBlendedView) { + ::quickPut(out, up, aff, ClosestPixel, colorScale, doPremultiply, whiteTransp, + firstColumn, doRasterDarkenBlendedView); } //=================================================================== -void TRop::over(const TRasterP &out, const TRasterP &dn, const TRasterP &up, const TRasterGR8P &mask) -{ - out->lock(); - up->lock(); - dn->lock(); - - TRaster32P out32 = out; - TRaster32P dn32 = dn; - TRaster32P up32 = up; - - if (out32 && dn32 && up32) - do_over(out32, dn32, up32, mask); - else { - TRaster64P out64 = out; - TRaster64P dn64 = dn; - TRaster64P up64 = up; - if (out64 && dn64 && up64) - do_over(out64, dn64, up64, mask); - else - throw TRopException("unsupported pixel type"); - } - out->unlock(); - up->unlock(); - dn->unlock(); +void TRop::over(const TRasterP &out, const TRasterP &dn, const TRasterP &up, + const TRasterGR8P &mask) { + out->lock(); + up->lock(); + dn->lock(); + + TRaster32P out32 = out; + TRaster32P dn32 = dn; + TRaster32P up32 = up; + + if (out32 && dn32 && up32) + do_over(out32, dn32, up32, mask); + else { + TRaster64P out64 = out; + TRaster64P dn64 = dn; + TRaster64P up64 = up; + if (out64 && dn64 && up64) + do_over(out64, dn64, up64, mask); + else + throw TRopException("unsupported pixel type"); + } + out->unlock(); + up->unlock(); + dn->unlock(); } diff --git a/toonz/sources/common/trop/traylit.cpp b/toonz/sources/common/trop/traylit.cpp index 60e6c23..ccd3a88 100644 --- a/toonz/sources/common/trop/traylit.cpp +++ b/toonz/sources/common/trop/traylit.cpp @@ -9,318 +9,361 @@ // Local namespace stuff //*********************************************************************************************** -namespace -{ +namespace { template struct RaylitFuncTraits { - typedef void (*function_type)(T *, T *, int, int, int, int, const TRect &, const TRect &, const TRop::RaylitParams &); + typedef void (*function_type)(T *, T *, int, int, int, int, const TRect &, + const TRect &, const TRop::RaylitParams &); }; //-------------------------------------------------------------------------------------------- template -void performStandardRaylit(T *bufIn, T *bufOut, - int dxIn, int dyIn, int dxOut, int dyOut, - const TRect &srcRect, const TRect &dstRect, - const TRop::RaylitParams ¶ms) -{ - /* NOTATION: Diagram assuming octant 1 - - / | - / | - / - ray_final_y | octLy - / 1 | - +---- | - _____ octLx - - - So, octLx and octLy are the octant's lx and ly; ray_final_y is the final height of the ray we're tracing - */ - - // Build colors-related variables - int max = T::maxChannelValue; - /*-- 透明部分の色 --*/ - int transp_val = (params.m_invert) ? max : 0, opaque_val = max - transp_val; - int value, val_r, val_g, val_b, val_m; - double lightness, r_fac, g_fac, b_fac, m_fac; - /*-- 8bit/16bitの違いを吸収する係数 --*/ - double factor = max / 255.0; - - double scale = params.m_scale; // NOTE: These variable initializations are, well, - double decay = log(params.m_decay / 100.0 + 1.0) + 1.0; // heuristic at least. They were probably tested - double intensity = 1e8 * log(params.m_intensity / 100.0 + 1.0) / scale; // to be good, but didn't quite make any REAL sense. - double smoothness = log(params.m_smoothness * 5.0 / 100.0 + 1.0); // - // They could be done MUCH better, but changing them - /*-- 1ステップ進んだ時、次のピクセルで光源が無かったときの光の弱まる割合 --*/ - double neg_delta_p = smoothness * intensity; // would alter the way raylit has been applied until now. - /*-- 1ステップ進んだ時、次のピクセルで光源が有ったときの光の強まる割合 --*/ - double quot_delta_p = intensity / max; // - // Should be changed at some point, though... - /*-- m_colorはRaylitFxのColor値。r_fac、g_fac、b_facは各チャンネルをPremultiplyした値 --*/ - m_fac = (params.m_color.m / 255.0); - r_fac = m_fac * (params.m_color.r / 255.0); - g_fac = m_fac * (params.m_color.g / 255.0); - b_fac = m_fac * (params.m_color.b / 255.0); - - // Geometry-related variables - int x, y, ray_final_y; - int octLx = dstRect.x1 - dstRect.x0; - - double rayPosIncrementX = 1.0 / scale; - - double sq_z = sq(params.m_lightOriginSrc.z); // We'll be making square distances from p, so square it once now - - // Perform raylit - T *pixIn, *pixOut; - - for (ray_final_y = 0; ray_final_y < octLx; ++ray_final_y) { - // Initialize increment variables - lightness = 0.0; - - double rayPosIncrementY = rayPosIncrementX * (ray_final_y / (double)octLx); - - // Use an integer counter to know when y must increase. Will add ray_final_y as long as - // a multiple of octLx-1 is reached, then increase - int yIncrementCounter = 0, yIncrementThreshold = octLx - 1; - - // Trace a single ray of light - TPointD rayPos(rayPosIncrementX, rayPosIncrementY); - - for (x = dstRect.x0, y = dstRect.y0, pixIn = bufIn, pixOut = bufOut; (x < dstRect.x1) && (y < dstRect.y1); ++x) { - bool insideSrc = (x >= srcRect.x0) && (x < srcRect.x1) && (y >= srcRect.y0) && (y < srcRect.y1); - if (insideSrc) { - // Add a light component depending on source's matte - if (pixIn->m == opaque_val) - lightness = std::max(0.0, lightness - neg_delta_p); // No light source - ray fading - else { - if (pixIn->m == transp_val) - lightness += intensity; // Full light source - ray enforcing - else - lightness = std::max(0.0, lightness + // Half light source - (params.m_invert ? pixIn->m : (max - pixIn->m)) * quot_delta_p); // matte-linear enforcing - } - - if (params.m_includeInput) { - val_r = pixIn->r; - val_g = pixIn->g; - val_b = pixIn->b; - val_m = pixIn->m; - } else - val_r = val_g = val_b = val_m = 0; - } else { - if (!params.m_invert) - lightness += intensity; - else - lightness = std::max(0.0, lightness - neg_delta_p); - - val_r = val_g = val_b = val_m = 0; - } - - bool insideDst = (x >= 0) && (y >= 0); - if (insideDst) { - // Write the corresponding destination pixel - if (lightness > 0.0) - value = (int)(factor * lightness / (rayPos.x * pow((double)(sq(rayPos.x) + sq(rayPos.y) + sq_z), decay)) + 0.5); // * ^-d... 0.5 rounds - else - value = 0; - - //NOTE: pow() could be slow. If that is the case, it could be cached for the whole octant along the longest ray at integer positions, - // and then linearly interpolated between those... Have to profile this before resorting to that... - - val_r += value * r_fac; - val_g += value * g_fac; - val_b += value * b_fac; - val_m += value * m_fac; - - pixOut->r = (val_r > max) ? max : val_r; - pixOut->g = (val_g > max) ? max : val_g; - pixOut->b = (val_b > max) ? max : val_b; - pixOut->m = (val_m > max) ? max : val_m; - } - - // Increment variables along the x-axis - pixIn += dxIn, pixOut += dxOut; - - rayPos.x += rayPosIncrementX, rayPos.y += rayPosIncrementY; - - // Increment variables along the y-axis - if ((yIncrementCounter += ray_final_y) >= yIncrementThreshold) { - ++y, pixIn += dyIn, pixOut += dyOut; - yIncrementCounter -= yIncrementThreshold; - } - } - } +void performStandardRaylit(T *bufIn, T *bufOut, int dxIn, int dyIn, int dxOut, + int dyOut, const TRect &srcRect, + const TRect &dstRect, + const TRop::RaylitParams ¶ms) { + /* NOTATION: Diagram assuming octant 1 + + / | + / | +/ - ray_final_y | octLy +/ 1 | ++---- | +_____ octLx + + +So, octLx and octLy are the octant's lx and ly; ray_final_y is the final height +of the ray we're tracing +*/ + + // Build colors-related variables + int max = T::maxChannelValue; + /*-- 透明部分の色 --*/ + int transp_val = (params.m_invert) ? max : 0, opaque_val = max - transp_val; + int value, val_r, val_g, val_b, val_m; + double lightness, r_fac, g_fac, b_fac, m_fac; + /*-- 8bit/16bitの違いを吸収する係数 --*/ + double factor = max / 255.0; + + double scale = + params.m_scale; // NOTE: These variable initializations are, well, + double decay = log(params.m_decay / 100.0 + 1.0) + + 1.0; // heuristic at least. They were probably tested + double intensity = + 1e8 * log(params.m_intensity / 100.0 + 1.0) / + scale; // to be good, but didn't quite make any REAL sense. + double smoothness = log(params.m_smoothness * 5.0 / 100.0 + 1.0); // + // They could be done MUCH better, but changing them + /*-- 1ステップ進んだ時、次のピクセルで光源が無かったときの光の弱まる割合 --*/ + double neg_delta_p = + smoothness * + intensity; // would alter the way raylit has been applied until now. + /*-- 1ステップ進んだ時、次のピクセルで光源が有ったときの光の強まる割合 --*/ + double quot_delta_p = intensity / max; // + // Should be changed at some point, though... + /*-- + * m_colorはRaylitFxのColor値。r_fac、g_fac、b_facは各チャンネルをPremultiplyした値 + * --*/ + m_fac = (params.m_color.m / 255.0); + r_fac = m_fac * (params.m_color.r / 255.0); + g_fac = m_fac * (params.m_color.g / 255.0); + b_fac = m_fac * (params.m_color.b / 255.0); + + // Geometry-related variables + int x, y, ray_final_y; + int octLx = dstRect.x1 - dstRect.x0; + + double rayPosIncrementX = 1.0 / scale; + + double sq_z = sq(params.m_lightOriginSrc.z); // We'll be making square + // distances from p, so square + // it once now + + // Perform raylit + T *pixIn, *pixOut; + + for (ray_final_y = 0; ray_final_y < octLx; ++ray_final_y) { + // Initialize increment variables + lightness = 0.0; + + double rayPosIncrementY = rayPosIncrementX * (ray_final_y / (double)octLx); + + // Use an integer counter to know when y must increase. Will add ray_final_y + // as long as + // a multiple of octLx-1 is reached, then increase + int yIncrementCounter = 0, yIncrementThreshold = octLx - 1; + + // Trace a single ray of light + TPointD rayPos(rayPosIncrementX, rayPosIncrementY); + + for (x = dstRect.x0, y = dstRect.y0, pixIn = bufIn, pixOut = bufOut; + (x < dstRect.x1) && (y < dstRect.y1); ++x) { + bool insideSrc = (x >= srcRect.x0) && (x < srcRect.x1) && + (y >= srcRect.y0) && (y < srcRect.y1); + if (insideSrc) { + // Add a light component depending on source's matte + if (pixIn->m == opaque_val) + lightness = std::max( + 0.0, lightness - neg_delta_p); // No light source - ray fading + else { + if (pixIn->m == transp_val) + lightness += intensity; // Full light source - ray enforcing + else + lightness = std::max( + 0.0, lightness + // Half light source + (params.m_invert ? pixIn->m : (max - pixIn->m)) * + quot_delta_p); // matte-linear enforcing + } + + if (params.m_includeInput) { + val_r = pixIn->r; + val_g = pixIn->g; + val_b = pixIn->b; + val_m = pixIn->m; + } else + val_r = val_g = val_b = val_m = 0; + } else { + if (!params.m_invert) + lightness += intensity; + else + lightness = std::max(0.0, lightness - neg_delta_p); + + val_r = val_g = val_b = val_m = 0; + } + + bool insideDst = (x >= 0) && (y >= 0); + if (insideDst) { + // Write the corresponding destination pixel + if (lightness > 0.0) + value = (int)(factor * lightness / + (rayPos.x * + pow((double)(sq(rayPos.x) + sq(rayPos.y) + sq_z), + decay)) + + 0.5); // * ^-d... 0.5 rounds + else + value = 0; + + // NOTE: pow() could be slow. If that is the case, it could be cached + // for the whole octant along the longest ray at integer positions, + // and then linearly interpolated between those... Have to profile this + // before resorting to that... + + val_r += value * r_fac; + val_g += value * g_fac; + val_b += value * b_fac; + val_m += value * m_fac; + + pixOut->r = (val_r > max) ? max : val_r; + pixOut->g = (val_g > max) ? max : val_g; + pixOut->b = (val_b > max) ? max : val_b; + pixOut->m = (val_m > max) ? max : val_m; + } + + // Increment variables along the x-axis + pixIn += dxIn, pixOut += dxOut; + + rayPos.x += rayPosIncrementX, rayPos.y += rayPosIncrementY; + + // Increment variables along the y-axis + if ((yIncrementCounter += ray_final_y) >= yIncrementThreshold) { + ++y, pixIn += dyIn, pixOut += dyOut; + yIncrementCounter -= yIncrementThreshold; + } + } + } } //-------------------------------------------------------------------------------------------- template -void performColorRaylit(T *bufIn, T *bufOut, - int dxIn, int dyIn, int dxOut, int dyOut, - const TRect &srcRect, const TRect &dstRect, - const TRop::RaylitParams ¶ms) -{ - // Build colors-related variables - int max = T::maxChannelValue; - - int val_r, val_g, val_b, val_m; - double lightness_r, lightness_g, lightness_b; - double factor = max / 255.0; - - double scale = params.m_scale; // NOTE: These variable initializations are, well, - double decay = log(params.m_decay / 100.0 + 1.0) + 1.0; // heuristic at least. They were probably tested - double intensity = 1e8 * log(params.m_intensity / 100.0 + 1.0) / scale; // to be good, but didn't quite make any REAL sense. - double smoothness = log(params.m_smoothness * 5.0 / 100.0 + 1.0); // - // They could be done MUCH better, but changing them - double neg_delta_p = smoothness * intensity; // would alter the way raylit has been applied until now. - double quot_delta_p = intensity / max; // - // Should be changed at some point, though... - - // Geometry-related variables - int x, y, ray_final_y; - int octLx = dstRect.x1 - dstRect.x0; - - double rayPosIncrementX = 1.0 / scale; - - double fac, sq_z = sq(params.m_lightOriginSrc.z); // We'll be making square distances from p, so square it once now - - // Perform raylit - T *pixIn, *pixOut; - - for (ray_final_y = 0; ray_final_y < octLx; ++ray_final_y) { - // Initialize increment variables - lightness_r = lightness_g = lightness_b = 0.0; - int l, l_max; - - double rayPosIncrementY = rayPosIncrementX * (ray_final_y / (double)octLx); - - // Use an integer counter to know when y must increase. Will add ray_final_y as long as - // a multiple of octLx-1 is reached, then increase - int yIncrementCounter = 0, yIncrementThreshold = octLx - 1; - - // Trace a single ray of light - TPointD rayPos(rayPosIncrementX, rayPosIncrementY); - - for (x = dstRect.x0, y = dstRect.y0, pixIn = bufIn, pixOut = bufOut; (x < dstRect.x1) && (y < dstRect.y1); ++x) { - bool insideSrc = (x >= srcRect.x0) && (x < srcRect.x1) && (y >= srcRect.y0) && (y < srcRect.y1); - if (insideSrc) { - val_r = pixIn->r; - val_g = pixIn->g; - val_b = pixIn->b; - val_m = pixIn->m; - - lightness_r = std::max(0.0, val_r ? lightness_r + val_r * quot_delta_p : lightness_r - neg_delta_p); - lightness_g = std::max(0.0, val_g ? lightness_g + val_g * quot_delta_p : lightness_g - neg_delta_p); - lightness_b = std::max(0.0, val_b ? lightness_b + val_b * quot_delta_p : lightness_b - neg_delta_p); - - if (!params.m_includeInput) - val_r = val_g = val_b = val_m = 0; - } else { - lightness_r = std::max(0.0, lightness_r - neg_delta_p); - lightness_g = std::max(0.0, lightness_g - neg_delta_p); - lightness_b = std::max(0.0, lightness_b - neg_delta_p); - - val_r = val_g = val_b = val_m = 0; - } - - bool insideDst = (x >= 0) && (y >= 0); - if (insideDst) { - // Write the corresponding destination pixel - fac = factor / (rayPos.x * pow((double)(sq(rayPos.x) + sq(rayPos.y) + sq_z), decay)); - - //NOTE: pow() could be slow. If that is the case, it could be cached for the whole octant along the longest ray at integer positions, - // and then linearly interpolated between those... Have to profile this before resorting to that... - - val_r += l = (int)(fac * lightness_r + 0.5); - l_max = l; - val_g += l = (int)(fac * lightness_g + 0.5); - l_max = std::max(l, l_max); - val_b += l = (int)(fac * lightness_b + 0.5); - l_max = std::max(l, l_max); - val_m += l_max; - - pixOut->r = (val_r > max) ? max : val_r; - pixOut->g = (val_g > max) ? max : val_g; - pixOut->b = (val_b > max) ? max : val_b; - pixOut->m = (val_m > max) ? max : val_m; - } - - // Increment variables along the x-axis - pixIn += dxIn, pixOut += dxOut; - - rayPos.x += rayPosIncrementX, rayPos.y += rayPosIncrementY; - - // Increment variables along the y-axis - if ((yIncrementCounter += ray_final_y) >= yIncrementThreshold) { - ++y, pixIn += dyIn, pixOut += dyOut; - yIncrementCounter -= yIncrementThreshold; - } - } - } +void performColorRaylit(T *bufIn, T *bufOut, int dxIn, int dyIn, int dxOut, + int dyOut, const TRect &srcRect, const TRect &dstRect, + const TRop::RaylitParams ¶ms) { + // Build colors-related variables + int max = T::maxChannelValue; + + int val_r, val_g, val_b, val_m; + double lightness_r, lightness_g, lightness_b; + double factor = max / 255.0; + + double scale = + params.m_scale; // NOTE: These variable initializations are, well, + double decay = log(params.m_decay / 100.0 + 1.0) + + 1.0; // heuristic at least. They were probably tested + double intensity = + 1e8 * log(params.m_intensity / 100.0 + 1.0) / + scale; // to be good, but didn't quite make any REAL sense. + double smoothness = log(params.m_smoothness * 5.0 / 100.0 + 1.0); // + // They could be done MUCH better, but changing them + double neg_delta_p = + smoothness * + intensity; // would alter the way raylit has been applied until now. + double quot_delta_p = intensity / max; // + // Should be changed at some point, though... + + // Geometry-related variables + int x, y, ray_final_y; + int octLx = dstRect.x1 - dstRect.x0; + + double rayPosIncrementX = 1.0 / scale; + + double fac, sq_z = sq(params.m_lightOriginSrc.z); // We'll be making square + // distances from p, so + // square it once now + + // Perform raylit + T *pixIn, *pixOut; + + for (ray_final_y = 0; ray_final_y < octLx; ++ray_final_y) { + // Initialize increment variables + lightness_r = lightness_g = lightness_b = 0.0; + int l, l_max; + + double rayPosIncrementY = rayPosIncrementX * (ray_final_y / (double)octLx); + + // Use an integer counter to know when y must increase. Will add ray_final_y + // as long as + // a multiple of octLx-1 is reached, then increase + int yIncrementCounter = 0, yIncrementThreshold = octLx - 1; + + // Trace a single ray of light + TPointD rayPos(rayPosIncrementX, rayPosIncrementY); + + for (x = dstRect.x0, y = dstRect.y0, pixIn = bufIn, pixOut = bufOut; + (x < dstRect.x1) && (y < dstRect.y1); ++x) { + bool insideSrc = (x >= srcRect.x0) && (x < srcRect.x1) && + (y >= srcRect.y0) && (y < srcRect.y1); + if (insideSrc) { + val_r = pixIn->r; + val_g = pixIn->g; + val_b = pixIn->b; + val_m = pixIn->m; + + lightness_r = std::max(0.0, val_r ? lightness_r + val_r * quot_delta_p + : lightness_r - neg_delta_p); + lightness_g = std::max(0.0, val_g ? lightness_g + val_g * quot_delta_p + : lightness_g - neg_delta_p); + lightness_b = std::max(0.0, val_b ? lightness_b + val_b * quot_delta_p + : lightness_b - neg_delta_p); + + if (!params.m_includeInput) val_r = val_g = val_b = val_m = 0; + } else { + lightness_r = std::max(0.0, lightness_r - neg_delta_p); + lightness_g = std::max(0.0, lightness_g - neg_delta_p); + lightness_b = std::max(0.0, lightness_b - neg_delta_p); + + val_r = val_g = val_b = val_m = 0; + } + + bool insideDst = (x >= 0) && (y >= 0); + if (insideDst) { + // Write the corresponding destination pixel + fac = + factor / (rayPos.x * + pow((double)(sq(rayPos.x) + sq(rayPos.y) + sq_z), decay)); + + // NOTE: pow() could be slow. If that is the case, it could be cached + // for the whole octant along the longest ray at integer positions, + // and then linearly interpolated between those... Have to profile this + // before resorting to that... + + val_r += l = (int)(fac * lightness_r + 0.5); + l_max = l; + val_g += l = (int)(fac * lightness_g + 0.5); + l_max = std::max(l, l_max); + val_b += l = (int)(fac * lightness_b + 0.5); + l_max = std::max(l, l_max); + val_m += l_max; + + pixOut->r = (val_r > max) ? max : val_r; + pixOut->g = (val_g > max) ? max : val_g; + pixOut->b = (val_b > max) ? max : val_b; + pixOut->m = (val_m > max) ? max : val_m; + } + + // Increment variables along the x-axis + pixIn += dxIn, pixOut += dxOut; + + rayPos.x += rayPosIncrementX, rayPos.y += rayPosIncrementY; + + // Increment variables along the y-axis + if ((yIncrementCounter += ray_final_y) >= yIncrementThreshold) { + ++y, pixIn += dyIn, pixOut += dyOut; + yIncrementCounter -= yIncrementThreshold; + } + } + } } //-------------------------------------------------------------------------------------------- /*-- ピザ状に8分割された領域の1つを計算する --*/ template -void computeOctant(const TRasterPT &src, const TRasterPT &dst, - int octant, const TRop::RaylitParams ¶ms, - typename RaylitFuncTraits::function_type raylitFunc) -{ - // Build octant geometry variables - int x0, x1, lxIn, lxOut, dxIn, dxOut; - int y0, y1, lyIn, lyOut, dyIn, dyOut; - - const T3DPoint &pIn = params.m_lightOriginSrc, &pOut = params.m_lightOriginDst; - int srcWrap = src->getWrap(), dstWrap = dst->getWrap(); - - T *bufIn = (T *)src->getRawData() + tfloor(pIn.y) * srcWrap + tfloor(pIn.x); - T *bufOut = (T *)dst->getRawData() + tfloor(pOut.y) * dstWrap + tfloor(pOut.x); - - TRect srcRect(src->getBounds() + TPoint(tround(pOut.x - pIn.x), tround(pOut.y - pIn.y))); - - lxIn = src->getLx(), lxOut = dst->getLx(); - lyIn = src->getLy(), lyOut = dst->getLy(); - - /*-- 1ピクセルずつ進むときの移動値 --*/ - // Vertical octant pairs - if (octant == 1 || octant == 8) - dxIn = 1, dxOut = 1, x0 = tfloor(pOut.x), x1 = lxOut; - if (octant == 2 || octant == 7) - dyIn = 1, dyOut = 1, y0 = tfloor(pOut.x), y1 = lxOut; - if (octant == 3 || octant == 6) - dyIn = -1, dyOut = -1, y0 = lxOut - tfloor(pOut.x) - 1, y1 = lxOut, tswap(srcRect.x0, srcRect.x1), srcRect.x0 = lxOut - srcRect.x0, srcRect.x1 = lxOut - srcRect.x1; - if (octant == 4 || octant == 5) - dxIn = -1, dxOut = -1, x0 = lxOut - tfloor(pOut.x) - 1, x1 = lxOut, tswap(srcRect.x0, srcRect.x1), srcRect.x0 = lxOut - srcRect.x0, srcRect.x1 = lxOut - srcRect.x1; - - // Horizontal octant pairs - if (octant == 2 || octant == 3) - dxIn = srcWrap, dxOut = dstWrap, x0 = tfloor(pOut.y), x1 = lyOut; - if (octant == 1 || octant == 4) - dyIn = srcWrap, dyOut = dstWrap, y0 = tfloor(pOut.y), y1 = lyOut; - if (octant == 5 || octant == 8) - dyIn = -srcWrap, dyOut = -dstWrap, y0 = lyOut - tfloor(pOut.y) - 1, y1 = lyOut, tswap(srcRect.y0, srcRect.y1), srcRect.y0 = lyOut - srcRect.y0, srcRect.y1 = lyOut - srcRect.y1; - if (octant == 6 || octant == 7) - dxIn = -srcWrap, dxOut = -dstWrap, x0 = lyOut - tfloor(pOut.y) - 1, x1 = lyOut, tswap(srcRect.y0, srcRect.y1), srcRect.y0 = lyOut - srcRect.y0, srcRect.y1 = lyOut - srcRect.y1; - - /*-- 縦向きのピザ領域を計算する場合は、90度回転してから --*/ - // Swap x and y axis where necessary - if (octant == 2 || octant == 3 || octant == 6 || octant == 7) { - tswap(lxIn, lyIn), tswap(lxOut, lyOut); - tswap(srcRect.x0, srcRect.y0), tswap(srcRect.x1, srcRect.y1); - } - - int octLx = (x1 - x0), octLy = (y1 - y0); - - assert(octLx > 0 && octLy > 0); - if (octLx <= 0 && octLy <= 0) - return; - - raylitFunc( - bufIn, bufOut, - dxIn, dyIn, dxOut, dyOut, - srcRect, TRect(x0, y0, x1, y1), - params); +void computeOctant(const TRasterPT &src, const TRasterPT &dst, int octant, + const TRop::RaylitParams ¶ms, + typename RaylitFuncTraits::function_type raylitFunc) { + // Build octant geometry variables + int x0, x1, lxIn, lxOut, dxIn, dxOut; + int y0, y1, lyIn, lyOut, dyIn, dyOut; + + const T3DPoint &pIn = params.m_lightOriginSrc, + &pOut = params.m_lightOriginDst; + int srcWrap = src->getWrap(), dstWrap = dst->getWrap(); + + T *bufIn = (T *)src->getRawData() + tfloor(pIn.y) * srcWrap + tfloor(pIn.x); + T *bufOut = + (T *)dst->getRawData() + tfloor(pOut.y) * dstWrap + tfloor(pOut.x); + + TRect srcRect(src->getBounds() + + TPoint(tround(pOut.x - pIn.x), tround(pOut.y - pIn.y))); + + lxIn = src->getLx(), lxOut = dst->getLx(); + lyIn = src->getLy(), lyOut = dst->getLy(); + + /*-- 1ピクセルずつ進むときの移動値 --*/ + // Vertical octant pairs + if (octant == 1 || octant == 8) + dxIn = 1, dxOut = 1, x0 = tfloor(pOut.x), x1 = lxOut; + if (octant == 2 || octant == 7) + dyIn = 1, dyOut = 1, y0 = tfloor(pOut.x), y1 = lxOut; + if (octant == 3 || octant == 6) + dyIn = -1, dyOut = -1, y0 = lxOut - tfloor(pOut.x) - 1, y1 = lxOut, + tswap(srcRect.x0, srcRect.x1), srcRect.x0 = lxOut - srcRect.x0, + srcRect.x1 = lxOut - srcRect.x1; + if (octant == 4 || octant == 5) + dxIn = -1, dxOut = -1, x0 = lxOut - tfloor(pOut.x) - 1, x1 = lxOut, + tswap(srcRect.x0, srcRect.x1), srcRect.x0 = lxOut - srcRect.x0, + srcRect.x1 = lxOut - srcRect.x1; + + // Horizontal octant pairs + if (octant == 2 || octant == 3) + dxIn = srcWrap, dxOut = dstWrap, x0 = tfloor(pOut.y), x1 = lyOut; + if (octant == 1 || octant == 4) + dyIn = srcWrap, dyOut = dstWrap, y0 = tfloor(pOut.y), y1 = lyOut; + if (octant == 5 || octant == 8) + dyIn = -srcWrap, dyOut = -dstWrap, y0 = lyOut - tfloor(pOut.y) - 1, + y1 = lyOut, tswap(srcRect.y0, srcRect.y1), srcRect.y0 = lyOut - srcRect.y0, + srcRect.y1 = lyOut - srcRect.y1; + if (octant == 6 || octant == 7) + dxIn = -srcWrap, dxOut = -dstWrap, x0 = lyOut - tfloor(pOut.y) - 1, + x1 = lyOut, tswap(srcRect.y0, srcRect.y1), srcRect.y0 = lyOut - srcRect.y0, + srcRect.y1 = lyOut - srcRect.y1; + + /*-- 縦向きのピザ領域を計算する場合は、90度回転してから --*/ + // Swap x and y axis where necessary + if (octant == 2 || octant == 3 || octant == 6 || octant == 7) { + tswap(lxIn, lyIn), tswap(lxOut, lyOut); + tswap(srcRect.x0, srcRect.y0), tswap(srcRect.x1, srcRect.y1); + } + + int octLx = (x1 - x0), octLy = (y1 - y0); + + assert(octLx > 0 && octLy > 0); + if (octLx <= 0 && octLy <= 0) return; + + raylitFunc(bufIn, bufOut, dxIn, dyIn, dxOut, dyOut, srcRect, + TRect(x0, y0, x1, y1), params); } //-------------------------------------------------------------------------------------------- @@ -340,69 +383,71 @@ void computeOctant(const TRasterPT &src, const TRasterPT &dst, */ template -void doRaylit(const TRasterPT &src, const TRasterPT &dst, const TRop::RaylitParams ¶ms, - typename RaylitFuncTraits::function_type raylitFunc) -{ - int lxOut = dst->getLx(), lyOut = dst->getLy(); - const T3DPoint &p = params.m_lightOriginDst; - - src->lock(); - dst->lock(); - - // Depending on the position of p, only some of the quadrants need to be built - if (p.y < lyOut) { - if (p.x < lxOut) { - // Compute the raylit fx on each octant independently - computeOctant(src, dst, 1, params, raylitFunc); - computeOctant(src, dst, 2, params, raylitFunc); - } - - if (p.x >= 0) { - computeOctant(src, dst, 3, params, raylitFunc); - computeOctant(src, dst, 4, params, raylitFunc); - } - } - - if (p.y >= 0) { - if (p.x >= 0) { - computeOctant(src, dst, 5, params, raylitFunc); - computeOctant(src, dst, 6, params, raylitFunc); - } - - if (p.x < lxOut) { - computeOctant(src, dst, 7, params, raylitFunc); - computeOctant(src, dst, 8, params, raylitFunc); - } - } - - dst->unlock(); - src->unlock(); +void doRaylit(const TRasterPT &src, const TRasterPT &dst, + const TRop::RaylitParams ¶ms, + typename RaylitFuncTraits::function_type raylitFunc) { + int lxOut = dst->getLx(), lyOut = dst->getLy(); + const T3DPoint &p = params.m_lightOriginDst; + + src->lock(); + dst->lock(); + + // Depending on the position of p, only some of the quadrants need to be built + if (p.y < lyOut) { + if (p.x < lxOut) { + // Compute the raylit fx on each octant independently + computeOctant(src, dst, 1, params, raylitFunc); + computeOctant(src, dst, 2, params, raylitFunc); + } + + if (p.x >= 0) { + computeOctant(src, dst, 3, params, raylitFunc); + computeOctant(src, dst, 4, params, raylitFunc); + } + } + + if (p.y >= 0) { + if (p.x >= 0) { + computeOctant(src, dst, 5, params, raylitFunc); + computeOctant(src, dst, 6, params, raylitFunc); + } + + if (p.x < lxOut) { + computeOctant(src, dst, 7, params, raylitFunc); + computeOctant(src, dst, 8, params, raylitFunc); + } + } + + dst->unlock(); + src->unlock(); } -} // namespace +} // namespace //*********************************************************************************************** // TRop::raylit implementation //*********************************************************************************************** -void TRop::raylit(const TRasterP &dstRas, const TRasterP &srcRas, const RaylitParams ¶ms) -{ - if ((TRaster32P)dstRas && (TRaster32P)srcRas) - doRaylit(srcRas, dstRas, params, &performStandardRaylit); - else if ((TRaster64P)dstRas && (TRaster64P)srcRas) - doRaylit(srcRas, dstRas, params, &performStandardRaylit); - else - throw TException("TRop::raylit unsupported pixel type"); +void TRop::raylit(const TRasterP &dstRas, const TRasterP &srcRas, + const RaylitParams ¶ms) { + if ((TRaster32P)dstRas && (TRaster32P)srcRas) + doRaylit(srcRas, dstRas, params, + &performStandardRaylit); + else if ((TRaster64P)dstRas && (TRaster64P)srcRas) + doRaylit(srcRas, dstRas, params, + &performStandardRaylit); + else + throw TException("TRop::raylit unsupported pixel type"); } //-------------------------------------------------------------------------------------------- -void TRop::glassRaylit(const TRasterP &dstRas, const TRasterP &srcRas, const RaylitParams ¶ms) -{ - if ((TRaster32P)dstRas && (TRaster32P)srcRas) - doRaylit(srcRas, dstRas, params, &performColorRaylit); - else if ((TRaster64P)dstRas && (TRaster64P)srcRas) - doRaylit(srcRas, dstRas, params, &performColorRaylit); - else - throw TException("TRop::raylit unsupported pixel type"); +void TRop::glassRaylit(const TRasterP &dstRas, const TRasterP &srcRas, + const RaylitParams ¶ms) { + if ((TRaster32P)dstRas && (TRaster32P)srcRas) + doRaylit(srcRas, dstRas, params, &performColorRaylit); + else if ((TRaster64P)dstRas && (TRaster64P)srcRas) + doRaylit(srcRas, dstRas, params, &performColorRaylit); + else + throw TException("TRop::raylit unsupported pixel type"); } diff --git a/toonz/sources/common/trop/tresample.cpp b/toonz/sources/common/trop/tresample.cpp index 155e5a4..5751f02 100644 --- a/toonz/sources/common/trop/tresample.cpp +++ b/toonz/sources/common/trop/tresample.cpp @@ -19,7 +19,7 @@ using namespace TConsts; #ifdef _WIN32 -#include // per SSE2 +#include // per SSE2 #endif #include @@ -109,7 +109,8 @@ min_ref_out_fg <= ref_out_fg <= max_ref_out_fg -filter_fg_radius < pix_out_fg < filter_fg_radius -filter_fg_radius < pix_ref_fg + ref_out_fg < filter_fg_radius -filter_fg_radius - ref_out_fg < pix_ref_fg < filter_fg_radius - ref_out_fg --filter_fg_radius - max_ref_out_fg < pix_ref_fg < filter_fg_radius - min_ref_out_fg +-filter_fg_radius - max_ref_out_fg < pix_ref_fg < filter_fg_radius - +min_ref_out_fg Scarto quelli che non soddisfano questa condizione @@ -131,10 +132,10 @@ Come e' fatto il filtro: TNZ_LITTLE_ENDIAN undefined !! #endif - //2^36 * 1.5, (52-_shiftamt=36) uses limited precision to floor - const double _double2fixmagic = 68719476736.0 * 1.5; + // 2^36 * 1.5, (52-_shiftamt=36) uses limited precision to floor + const double _double2fixmagic = 68719476736.0 * 1.5; -//16.16 fixed point representation +// 16.16 fixed point representation const TINT32 _shiftamt = 16; #if TNZ_LITTLE_ENDIAN @@ -145,78 +146,77 @@ const TINT32 _shiftamt = 16; #define iman_ 1 #endif -inline TINT32 Double2Int(double val) -{ - val = val + _double2fixmagic; - return ((TINT32 *)&val)[iman_] >> _shiftamt; +inline TINT32 Double2Int(double val) { + val = val + _double2fixmagic; + return ((TINT32 *)&val)[iman_] >> _shiftamt; } -#define DOUBLE_TO_INT32(D) (d2iaux = D, d2iaux += _double2fixmagic, (((TINT32 *)&(d2iaux))[iman_] >> _shiftamt)) +#define DOUBLE_TO_INT32(D) \ + (d2iaux = D, d2iaux += _double2fixmagic, \ + (((TINT32 *)&(d2iaux))[iman_] >> _shiftamt)) //#define USE_DOUBLE_TO_INT //=========================================================================== -inline double sinc0(double x, int a) -{ - return sin((pi / (a)) * (x)) / ((pi / (a)) * (x)); +inline double sinc0(double x, int a) { + return sin((M_PI / (a)) * (x)) / ((M_PI / (a)) * (x)); } -inline double sinc(double x, int a) -{ - return (x) == 0.0 ? 1.0 : sin((pi / (a)) * (x)) / ((pi / (a)) * (x)); +inline double sinc(double x, int a) { + return (x) == 0.0 ? 1.0 : sin((M_PI / (a)) * (x)) / ((M_PI / (a)) * (x)); } -inline UCHAR TO8BIT(float X) -{ - return (((X) < 0.0F) ? 0 : (((X) > 255.0F) ? 255 : tround(X))); +inline UCHAR TO8BIT(float X) { + return (((X) < 0.0F) ? 0 : (((X) > 255.0F) ? 255 : tround(X))); } const UCHAR BORDER_GR8 = 255; -const UCHAR GREY_GR8 = 127; +const UCHAR GREY_GR8 = 127; #ifdef USE_INLINE_FUNS //--------------------------------------------------------------------------- -inline double aff0MV1(const TAffine &aff, double v1, double v2) -{ - return aff.a11 * v1 + aff.a12 * v2; +inline double aff0MV1(const TAffine &aff, double v1, double v2) { + return aff.a11 * v1 + aff.a12 * v2; } //--------------------------------------------------------------------------- -inline double affMV1(const TAffine &aff, double v1, double v2) -{ - return aff.a11 * v1 + aff.a12 * v2 + aff.a13; +inline double affMV1(const TAffine &aff, double v1, double v2) { + return aff.a11 * v1 + aff.a12 * v2 + aff.a13; } //--------------------------------------------------------------------------- -inline double aff0MV2(const TAffine &aff, double v1, double v2) -{ - return aff.a21 * v1 + aff.a22 * v2; +inline double aff0MV2(const TAffine &aff, double v1, double v2) { + return aff.a21 * v1 + aff.a22 * v2; } //--------------------------------------------------------------------------- -inline double affMV2(const TAffine &aff, double v1, double v2) -{ - return aff.a21 * v1 + aff.a22 * v2 + aff.a23; +inline double affMV2(const TAffine &aff, double v1, double v2) { + return aff.a21 * v1 + aff.a22 * v2 + aff.a23; } -#else // !USE_INLINE_FUNS +#else // !USE_INLINE_FUNS #ifndef USE_DOUBLE_TO_INT -#define ROUND(x) ((int)(((int)(-0.9F) == 0 && (x) < 0.0F) ? ((x)-0.5F) : ((x) + 0.5F))) +#define ROUND(x) \ + ((int)(((int)(-0.9F) == 0 && (x) < 0.0F) ? ((x)-0.5F) : ((x) + 0.5F))) #define ROUNDP(x) ((int)((x) + 0.5F)) #define FLOOR(x) ((int)(x) > (x) ? (int)(x)-1 : (int)(x)) #define CEIL(x) ((int)(x) < (x) ? (int)(x) + 1 : (int)(x)) #else -#define ROUND(x) (DOUBLE_TO_INT32(((int)(-0.9F) == 0 && (x) < 0.0F) ? ((x)-0.5F) : ((x) + 0.5F))) +#define ROUND(x) \ + (DOUBLE_TO_INT32(((int)(-0.9F) == 0 && (x) < 0.0F) ? ((x)-0.5F) \ + : ((x) + 0.5F))) #define ROUNDP(x) (DOUBLE_TO_INT32((x) + 0.5F)) -#define FLOOR(x) (DOUBLE_TO_INT32(x) > (x) ? DOUBLE_TO_INT32(x) - 1 : DOUBLE_TO_INT32(x)) -#define CEIL(x) (DOUBLE_TO_INT32(x) < (x) ? DOUBLE_TO_INT32(x) + 1 : DOUBLE_TO_INT32(x)) +#define FLOOR(x) \ + (DOUBLE_TO_INT32(x) > (x) ? DOUBLE_TO_INT32(x) - 1 : DOUBLE_TO_INT32(x)) +#define CEIL(x) \ + (DOUBLE_TO_INT32(x) < (x) ? DOUBLE_TO_INT32(x) + 1 : DOUBLE_TO_INT32(x)) #endif #define INTLE(x) (FLOOR(x)) @@ -224,16 +224,14 @@ inline double affMV2(const TAffine &aff, double v1, double v2) #define INTLT(x) (CEIL(x) - 1) #define INTGE(x) (CEIL(x)) -#define NOT_LESS_THAN(MIN, X) \ - { \ - if ((X) < (MIN)) \ - (X) = (MIN); \ - } -#define NOT_MORE_THAN(MAX, X) \ - { \ - if ((X) > (MAX)) \ - (X) = (MAX); \ - } +#define NOT_LESS_THAN(MIN, X) \ + { \ + if ((X) < (MIN)) (X) = (MIN); \ + } +#define NOT_MORE_THAN(MAX, X) \ + { \ + if ((X) > (MAX)) (X) = (MAX); \ + } #define tround ROUND #define troundp ROUNDP @@ -260,93 +258,90 @@ inline double affMV2(const TAffine &aff, double v1, double v2) #define affMV1 AFF_M_V_1 #define affMV2 AFF_M_V_2 -#endif // USE_INLINE_FUNS +#endif // USE_INLINE_FUNS //--------------------------------------------------------------------------- struct FILTER { - int first, last; - float *w; - float *w_base; + int first, last; + float *w; + float *w_base; }; struct NOCALC { - int first, last; + int first, last; }; //--------------------------------------------------------------------------- -inline int get_filter_radius(TRop::ResampleFilterType flt_type) -{ - switch (flt_type) { - case TRop::Triangle: - return 1; - case TRop::Mitchell: - return 2; - case TRop::Cubic5: - return 2; - case TRop::Cubic75: - return 2; - case TRop::Cubic1: - return 2; - case TRop::Hann2: - return 2; - case TRop::Hann3: - return 3; - case TRop::Hamming2: - return 2; - case TRop::Hamming3: - return 3; - case TRop::Lanczos2: - return 2; - case TRop::Lanczos3: - return 3; - case TRop::Gauss: - return 2; - default: - assert(!"bad filter type"); - } - return 0; +inline int get_filter_radius(TRop::ResampleFilterType flt_type) { + switch (flt_type) { + case TRop::Triangle: + return 1; + case TRop::Mitchell: + return 2; + case TRop::Cubic5: + return 2; + case TRop::Cubic75: + return 2; + case TRop::Cubic1: + return 2; + case TRop::Hann2: + return 2; + case TRop::Hann3: + return 3; + case TRop::Hamming2: + return 2; + case TRop::Hamming3: + return 3; + case TRop::Lanczos2: + return 2; + case TRop::Lanczos3: + return 3; + case TRop::Gauss: + return 2; + default: + assert(!"bad filter type"); + } + return 0; } //--------------------------------------------------------------------------- -//!Equivalent to aff * TRectD(u0, v0, u1, v0). -inline void minmax(double u0, double v0, - double u1, double v1, const TAffine &aff, - double &x0, double &y0, - double &x1, double &y1) -{ - double xmin, ymin; - double xmax, ymax; - double x_a, y_a; - double x_b, y_b; - double x_c, y_c; - double x_d, y_d; - - x_a = affMV1(aff, u0, v0); - y_a = affMV2(aff, u0, v0); - x_b = affMV1(aff, u1, v0); - y_b = affMV2(aff, u1, v0); - x_c = affMV1(aff, u1, v1); - y_c = affMV2(aff, u1, v1); - x_d = affMV1(aff, u0, v1); - y_d = affMV2(aff, u0, v1); - xmin = std::min(x_a, x_b); - xmax = std::max(x_a, x_b); - xmin = std::min(xmin, x_c); - xmax = std::max(xmax, x_c); - xmin = std::min(xmin, x_d); - xmax = std::max(xmax, x_d); - ymin = std::min(y_a, y_b); - ymax = std::max(y_a, y_b); - ymin = std::min(ymin, y_c); - ymax = std::max(ymax, y_c); - ymin = std::min(ymin, y_d); - ymax = std::max(ymax, y_d); - x0 = xmin; - y0 = ymin; - x1 = xmax; - y1 = ymax; +//! Equivalent to aff * TRectD(u0, v0, u1, v0). +inline void minmax(double u0, double v0, double u1, double v1, + const TAffine &aff, double &x0, double &y0, double &x1, + double &y1) { + double xmin, ymin; + double xmax, ymax; + double x_a, y_a; + double x_b, y_b; + double x_c, y_c; + double x_d, y_d; + + x_a = affMV1(aff, u0, v0); + y_a = affMV2(aff, u0, v0); + x_b = affMV1(aff, u1, v0); + y_b = affMV2(aff, u1, v0); + x_c = affMV1(aff, u1, v1); + y_c = affMV2(aff, u1, v1); + x_d = affMV1(aff, u0, v1); + y_d = affMV2(aff, u0, v1); + xmin = std::min(x_a, x_b); + xmax = std::max(x_a, x_b); + xmin = std::min(xmin, x_c); + xmax = std::max(xmax, x_c); + xmin = std::min(xmin, x_d); + xmax = std::max(xmax, x_d); + ymin = std::min(y_a, y_b); + ymax = std::max(y_a, y_b); + ymin = std::min(ymin, y_c); + ymax = std::max(ymax, y_c); + ymin = std::min(ymin, y_d); + ymax = std::max(ymax, y_d); + x0 = xmin; + y0 = ymin; + x1 = xmax; + y1 = ymax; } /*---------------------------------------------------------------------------*/ @@ -389,316 +384,301 @@ return true; static double p0, p2, p3, q0, q1, q2, q3; -inline void mitchellinit(double b, double c) -{ - p0 = (6.0 - 2.0 * b) / 6.0; - p2 = (-18.0 + 12.0 * b + 6.0 * c) / 6.0; - p3 = (12.0 - 9.0 * b - 6.0 * c) / 6.0; - q0 = (8.0 * b + 24.0 * c) / 6.0; - q1 = (-12.0 * b - 48.0 * c) / 6.0; - q2 = (6.0 * b + 30.0 * c) / 6.0; - q3 = (-b - 6.0 * c) / 6.0; +inline void mitchellinit(double b, double c) { + p0 = (6.0 - 2.0 * b) / 6.0; + p2 = (-18.0 + 12.0 * b + 6.0 * c) / 6.0; + p3 = (12.0 - 9.0 * b - 6.0 * c) / 6.0; + q0 = (8.0 * b + 24.0 * c) / 6.0; + q1 = (-12.0 * b - 48.0 * c) / 6.0; + q2 = (6.0 * b + 30.0 * c) / 6.0; + q3 = (-b - 6.0 * c) / 6.0; } const int fltradMitchell = 2; -static inline double flt_mitchell(double x) /*Mitchell & Netravali's two-param cubic*/ +static inline double flt_mitchell( + double x) /*Mitchell & Netravali's two-param cubic*/ { - static int mitfirsted; - - if (!mitfirsted) { - mitchellinit(1.0 / 3.0, 1.0 / 3.0); - mitfirsted = 1; - } - if (x < -2.0) - return 0.0; - if (x < -1.0) - return (q0 - x * (q1 - x * (q2 - x * q3))); - if (x < 0.0) - return (p0 + x * x * (p2 - x * p3)); - if (x < 1.0) - return (p0 + x * x * (p2 + x * p3)); - if (x < 2.0) - return (q0 + x * (q1 + x * (q2 + x * q3))); - return 0.0; + static int mitfirsted; + + if (!mitfirsted) { + mitchellinit(1.0 / 3.0, 1.0 / 3.0); + mitfirsted = 1; + } + if (x < -2.0) return 0.0; + if (x < -1.0) return (q0 - x * (q1 - x * (q2 - x * q3))); + if (x < 0.0) return (p0 + x * x * (p2 - x * p3)); + if (x < 1.0) return (p0 + x * x * (p2 + x * p3)); + if (x < 2.0) return (q0 + x * (q1 + x * (q2 + x * q3))); + return 0.0; } //----------------------------------------------------------------------------- const int fltradTriangle = 1; -static inline double flt_triangle(double x) -{ - if (x < -1.0) - return 0.0; - if (x < 0.0) - return 1.0 + x; - if (x < 1.0) - return 1.0 - x; - return 0.0; +static inline double flt_triangle(double x) { + if (x < -1.0) return 0.0; + if (x < 0.0) return 1.0 + x; + if (x < 1.0) return 1.0 - x; + return 0.0; } //----------------------------------------------------------------------------- const int fltradCubic5 = 2; -static inline double flt_cubic_5(double x) -{ - if (x < 0.0) - x = -x; - if (x < 1.0) - return 2.5 * x * x * x - 3.5 * x * x + 1; - if (x < 2.0) - return 0.5 * x * x * x - 2.5 * x * x + 4 * x - 2; - return 0.0; +static inline double flt_cubic_5(double x) { + if (x < 0.0) x = -x; + if (x < 1.0) return 2.5 * x * x * x - 3.5 * x * x + 1; + if (x < 2.0) return 0.5 * x * x * x - 2.5 * x * x + 4 * x - 2; + return 0.0; } //----------------------------------------------------------------------------- const int fltradCubic75 = 2; -static inline double flt_cubic_75(double x) -{ - if (x < 0.0) - x = -x; - if (x < 1.0) - return 2.75 * x * x * x - 3.75 * x * x + 1; - if (x < 2.0) - return 0.75 * x * x * x - 3.75 * x * x + 6 * x - 3; - return 0.0; +static inline double flt_cubic_75(double x) { + if (x < 0.0) x = -x; + if (x < 1.0) return 2.75 * x * x * x - 3.75 * x * x + 1; + if (x < 2.0) return 0.75 * x * x * x - 3.75 * x * x + 6 * x - 3; + return 0.0; } //----------------------------------------------------------------------------- const int fltradCubic1 = 2; -static inline double flt_cubic_1(double x) -{ - if (x < 0.0) - x = -x; - if (x < 1.0) - return 3 * x * x * x - 4 * x * x + 1; - if (x < 2.0) - return x * x * x - 5 * x * x + 8 * x - 4; - return 0.0; +static inline double flt_cubic_1(double x) { + if (x < 0.0) x = -x; + if (x < 1.0) return 3 * x * x * x - 4 * x * x + 1; + if (x < 2.0) return x * x * x - 5 * x * x + 8 * x - 4; + return 0.0; } //----------------------------------------------------------------------------- const int fltradHann2 = 2; -static inline double flt_hann2(double x) -{ - if (x <= -2.0) - return 0.0; - if (x < 2.0) - return sinc(x, 1) * (0.5 + 0.5 * cos((pi / 2) * x)); - return 0.0; +static inline double flt_hann2(double x) { + if (x <= -2.0) return 0.0; + if (x < 2.0) return sinc(x, 1) * (0.5 + 0.5 * cos(M_PI_2 * x)); + return 0.0; } //----------------------------------------------------------------------------- const int fltradHann3 = 3; -static inline double flt_hann3(double x) -{ - if (x <= -3.0) - return 0.0; - if (x < 3.0) - return sinc(x, 1) * (0.5 + 0.5 * cos((pi / 3) * x)); - return 0.0; +static inline double flt_hann3(double x) { + if (x <= -3.0) return 0.0; + if (x < 3.0) return sinc(x, 1) * (0.5 + 0.5 * cos(M_PI_3 * x)); + return 0.0; } //----------------------------------------------------------------------------- const int fltradHamming2 = 2; -static inline double flt_hamming2(double x) -{ - if (x <= -2.0) - return 0.0; - if (x < 2.0) - return sinc(x, 1) * (0.54 + 0.46 * cos((pi / 2) * x)); - return 0.0; +static inline double flt_hamming2(double x) { + if (x <= -2.0) return 0.0; + if (x < 2.0) return sinc(x, 1) * (0.54 + 0.46 * cos(M_PI_2 * x)); + return 0.0; } //----------------------------------------------------------------------------- const int fltradHamming3 = 3; -static inline double flt_hamming3(double x) -{ - if (x <= -3.0) - return 0.0; - if (x < 3.0) - return sinc(x, 1) * (0.54 + 0.46 * cos((pi / 3) * x)); - return 0.0; +static inline double flt_hamming3(double x) { + if (x <= -3.0) return 0.0; + if (x < 3.0) return sinc(x, 1) * (0.54 + 0.46 * cos(M_PI_3 * x)); + return 0.0; } //----------------------------------------------------------------------------- const int fltradLanczos2 = 2; -static inline double flt_lanczos2(double x) -{ - if (x <= -2.0) - return 0.0; - if (x < 2.0) - return sinc(x, 1) * sinc(x, 2); - return 0.0; +static inline double flt_lanczos2(double x) { + if (x <= -2.0) return 0.0; + if (x < 2.0) return sinc(x, 1) * sinc(x, 2); + return 0.0; } //----------------------------------------------------------------------------- const int fltradLanczos3 = 3; -static inline double flt_lanczos3(double x) -{ - if (x <= -3.0) - return 0.0; - if (x < 3.0) - return sinc(x, 1) * sinc(x, 3); - return 0.0; +static inline double flt_lanczos3(double x) { + if (x <= -3.0) return 0.0; + if (x < 3.0) return sinc(x, 1) * sinc(x, 3); + return 0.0; } //----------------------------------------------------------------------------- const int fltradGauss = 2; -static inline double flt_gauss(double x) -{ - if (x <= -2.0) - return 0.0; - if (x < 2.0) - return exp((-pi) * x * x); - return 0.0; /* exp(-M_PI*2*2)~=3.5*10^-6 */ +static inline double flt_gauss(double x) { + if (x <= -2.0) return 0.0; + if (x < 2.0) return exp(-M_PI * x * x); + return 0.0; /* exp(-M_PI*2*2)~=3.5*10^-6 */ } //----------------------------------------------------------------------------- const int fltradW1 = 2; -static inline double flt_w_1(double x) -{ - if (x < 0.0) - x = -x; - if (x < 0.5) - return 1 - 0.5 * x; - if (x < 1.0) - return 1.5 - 1.5 * x; - if (x < 1.5) - return 0.5 - 0.5 * x; - if (x < 2.0) - return 0.5 * x - 1.0; - return 0.0; +static inline double flt_w_1(double x) { + if (x < 0.0) x = -x; + if (x < 0.5) return 1 - 0.5 * x; + if (x < 1.0) return 1.5 - 1.5 * x; + if (x < 1.5) return 0.5 - 0.5 * x; + if (x < 2.0) return 0.5 * x - 1.0; + return 0.0; } //----------------------------------------------------------------------------- static inline void get_flt_fun_rad(TRop::ResampleFilterType flt_type, - double (**flt_fun)(double), double &flt_rad) -{ - double (*fun)(double); - double rad; - - switch (flt_type) { - case TRop::Triangle: fun = flt_triangle; rad = fltradTriangle; break; - case TRop::Mitchell: fun = flt_mitchell; rad = fltradMitchell; break; - case TRop::Cubic5 : fun = flt_cubic_5 ; rad = fltradCubic5 ; break; - case TRop::Cubic75 : fun = flt_cubic_75; rad = fltradCubic75 ; break; - case TRop::Cubic1 : fun = flt_cubic_1 ; rad = fltradCubic1 ; break; - case TRop::Hann2 : fun = flt_hann2 ; rad = fltradHann2 ; break; - case TRop::Hann3 : fun = flt_hann3 ; rad = fltradHann3 ; break; - case TRop::Hamming2: fun = flt_hamming2; rad = fltradHamming2; break; - case TRop::Hamming3: fun = flt_hamming3; rad = fltradHamming3; break; - case TRop::Lanczos2: fun = flt_lanczos2; rad = fltradLanczos2; break; - case TRop::Lanczos3: fun = flt_lanczos3; rad = fltradLanczos3; break; - case TRop::Gauss : fun = flt_gauss ; rad = fltradGauss ; break; - case 101 : fun = flt_w_1 ; rad = fltradW1 ; break; - default : fun = flt_triangle; rad = fltradTriangle; break; - } - if (flt_fun) - *flt_fun = fun; - flt_rad = rad; + double (**flt_fun)(double), + double &flt_rad) { + double (*fun)(double); + double rad; + + switch (flt_type) { + case TRop::Triangle: + fun = flt_triangle; + rad = fltradTriangle; + break; + case TRop::Mitchell: + fun = flt_mitchell; + rad = fltradMitchell; + break; + case TRop::Cubic5: + fun = flt_cubic_5; + rad = fltradCubic5; + break; + case TRop::Cubic75: + fun = flt_cubic_75; + rad = fltradCubic75; + break; + case TRop::Cubic1: + fun = flt_cubic_1; + rad = fltradCubic1; + break; + case TRop::Hann2: + fun = flt_hann2; + rad = fltradHann2; + break; + case TRop::Hann3: + fun = flt_hann3; + rad = fltradHann3; + break; + case TRop::Hamming2: + fun = flt_hamming2; + rad = fltradHamming2; + break; + case TRop::Hamming3: + fun = flt_hamming3; + rad = fltradHamming3; + break; + case TRop::Lanczos2: + fun = flt_lanczos2; + rad = fltradLanczos2; + break; + case TRop::Lanczos3: + fun = flt_lanczos3; + rad = fltradLanczos3; + break; + case TRop::Gauss: + fun = flt_gauss; + rad = fltradGauss; + break; + case 101: + fun = flt_w_1; + rad = fltradW1; + break; + default: + fun = flt_triangle; + rad = fltradTriangle; + break; + } + if (flt_fun) *flt_fun = fun; + flt_rad = rad; } //--------------------------------------------------------------------------- static FILTER *create_filter(TRop::ResampleFilterType flt_type, double blur, - double dx_du, double delta_x, int lx, - double &xrad, int &umin, int &umax, int &uwidth) -{ - double (*flt_fun)(double); - FILTER *filter, *f; - double du_dx; - int x; - double u_; - int u, ulo, uhi, ulomin, uhimax, m, n, nmax; - double flt_rad, rad_u, rad_x, nodedist_u, nodefreq_u, sum, norm, w; + double dx_du, double delta_x, int lx, double &xrad, + int &umin, int &umax, int &uwidth) { + double (*flt_fun)(double); + FILTER *filter, *f; + double du_dx; + int x; + double u_; + int u, ulo, uhi, ulomin, uhimax, m, n, nmax; + double flt_rad, rad_u, rad_x, nodedist_u, nodefreq_u, sum, norm, w; #ifdef USE_DOUBLE_TO_INT - double d2iaux; + double d2iaux; #endif - get_flt_fun_rad(flt_type, &flt_fun, flt_rad); - du_dx = 1 / dx_du; - if (dx_du > 1) - nodedist_u = blur; /* magnification */ - else - nodedist_u = du_dx * blur; /* minification */ - rad_u = flt_rad * nodedist_u; - rad_x = rad_u * dx_du; - nodefreq_u = 1 / nodedist_u; - /* + get_flt_fun_rad(flt_type, &flt_fun, flt_rad); + du_dx = 1 / dx_du; + if (dx_du > 1) + nodedist_u = blur; /* magnification */ + else + nodedist_u = du_dx * blur; /* minification */ + rad_u = flt_rad * nodedist_u; + rad_x = rad_u * dx_du; + nodefreq_u = 1 / nodedist_u; + /* mu = lu - 1; */ - filter = new FILTER[lx]; - nmax = 0; - ulomin = c_maxint - 1; - uhimax = c_minint + 1; - for (x = 0; x < lx; x++) { - f = filter + x; - u_ = (x - delta_x) * du_dx; - ulo = intGT(u_ - rad_u); - uhi = intLT(u_ + rad_u); - /* - NOT_LESS_THAN( 0, ulo) - NOT_MORE_THAN(mu, uhi) + filter = new FILTER[lx]; + nmax = 0; + ulomin = c_maxint - 1; + uhimax = c_minint + 1; + for (x = 0; x < lx; x++) { + f = filter + x; + u_ = (x - delta_x) * du_dx; + ulo = intGT(u_ - rad_u); + uhi = intLT(u_ + rad_u); + /* +NOT_LESS_THAN( 0, ulo) +NOT_MORE_THAN(mu, uhi) */ - m = uhi - ulo + 1; - if (m > 0) { - f->w_base = new float[m]; - f->w = f->w_base - ulo; - for (sum = 0.0, u = ulo; u <= uhi; u++) { - w = (*flt_fun)((u - u_) * nodefreq_u); - sum += w; - f->w[u] = (float)w; - } - for (; ulo <= uhi; ulo++) - if (f->w[ulo]) - break; - for (; uhi >= ulo; uhi--) - if (f->w[uhi]) - break; - if (ulo < ulomin) - ulomin = ulo; - if (uhi > uhimax) - uhimax = uhi; - n = uhi - ulo + 1; - if (n > nmax) - nmax = n; - f->first = ulo; - f->last = uhi; - norm = 1 / sum; - for (u = ulo; u <= uhi; u++) - f->w[u] *= (float)norm; - } else { - f->w_base = 0; - f->first = ulo; - f->last = uhi; - } - } - xrad = rad_x; - umin = ulomin; - umax = uhimax; - uwidth = nmax; - return filter; + m = uhi - ulo + 1; + if (m > 0) { + f->w_base = new float[m]; + f->w = f->w_base - ulo; + for (sum = 0.0, u = ulo; u <= uhi; u++) { + w = (*flt_fun)((u - u_) * nodefreq_u); + sum += w; + f->w[u] = (float)w; + } + for (; ulo <= uhi; ulo++) + if (f->w[ulo]) break; + for (; uhi >= ulo; uhi--) + if (f->w[uhi]) break; + if (ulo < ulomin) ulomin = ulo; + if (uhi > uhimax) uhimax = uhi; + n = uhi - ulo + 1; + if (n > nmax) nmax = n; + f->first = ulo; + f->last = uhi; + norm = 1 / sum; + for (u = ulo; u <= uhi; u++) f->w[u] *= (float)norm; + } else { + f->w_base = 0; + f->first = ulo; + f->last = uhi; + } + } + xrad = rad_x; + umin = ulomin; + umax = uhimax; + uwidth = nmax; + return filter; } //----------------------------------------------------------------------------- static NOCALC *create_nocalc(TRop::ResampleFilterType flt_type, double blur, - double dx_du, double delta_x, int lx, - int umin, int umax, int &xwidth) -{ - /* + double dx_du, double delta_x, int lx, int umin, + int umax, int &xwidth) { + /* Il nocalc serve a stabilire che un insieme di pixel u (di ingresso) non ha bisogno di essere calcolato, perche tutti i pixel x (di uscita) @@ -731,39 +711,39 @@ INT_GT (2*radx_) = width */ - NOCALC *nocalc; - int width; - double flt_rad; - double rad_x; - double du_dx; - double ulo_, uhi_; - int ulo, uhi; - int x; + NOCALC *nocalc; + int width; + double flt_rad; + double rad_x; + double du_dx; + double ulo_, uhi_; + int ulo, uhi; + int x; #ifdef USE_DOUBLE_TO_INT - double d2iaux; + double d2iaux; #endif - du_dx = 1 / dx_du; - get_flt_fun_rad(flt_type, 0, flt_rad); - if (dx_du > 1) /* sto ingrandendo */ - rad_x = flt_rad * blur * dx_du; - else - rad_x = flt_rad * blur; - rad_x += 0.5; /* ?!?!?!?!? */ - width = intGT(2 * rad_x + 1); - nocalc = new NOCALC[lx + width - 1]; - for (x = 0; x < lx + width - 1; x++) { - ulo_ = (x - rad_x - delta_x) * du_dx; - uhi_ = ulo_ + du_dx; - ulo = intGE(ulo_); - uhi = intLT(uhi_); - nocalc[x].first = std::max(umin, ulo); - nocalc[x].last = std::min(umax, uhi); - } - xwidth = width; - - return nocalc; + du_dx = 1 / dx_du; + get_flt_fun_rad(flt_type, 0, flt_rad); + if (dx_du > 1) /* sto ingrandendo */ + rad_x = flt_rad * blur * dx_du; + else + rad_x = flt_rad * blur; + rad_x += 0.5; /* ?!?!?!?!? */ + width = intGT(2 * rad_x + 1); + nocalc = new NOCALC[lx + width - 1]; + for (x = 0; x < lx + width - 1; x++) { + ulo_ = (x - rad_x - delta_x) * du_dx; + uhi_ = ulo_ + du_dx; + ulo = intGE(ulo_); + uhi = intLT(uhi_); + nocalc[x].first = std::max(umin, ulo); + nocalc[x].last = std::min(umax, uhi); + } + xwidth = width; + + return nocalc; } //--------------------------------------------------------------------------- @@ -792,937 +772,889 @@ inline void calcValueNoCalc(UINT &calc_value){ calc_value &= ~0x80U; } */ -#define CALC_VALUE_INIT \ - { \ - calc_value = 0xffffU; \ - } +#define CALC_VALUE_INIT \ + { calc_value = 0xffffU; } #define CALC_VALUE_EMPTY (calc_value == 0xffffU) #define CALC_VALUE_READY (calc_value <= 0x1ffU) -#define CALC_VALUE_ADVANCE \ - { \ - calc_value >>= 1; \ - } -#define CALC_VALUE_NOCALC \ - { \ - calc_value &= ~0x80U; \ - } +#define CALC_VALUE_ADVANCE \ + { calc_value >>= 1; } +#define CALC_VALUE_NOCALC \ + { calc_value &= ~0x80U; } template #ifdef _WIN32 __forceinline #endif - void - ResampleCalcAlgo(PixType *buffer_in, int lu, int lv, int wrap_in, int max_pix_ref_u, int min_pix_ref_u, int max_pix_ref_v, int min_pix_ref_v, UCHAR *calc, int calc_bytesize, int calc_bytewrap) + void + ResampleCalcAlgo(PixType *buffer_in, int lu, int lv, int wrap_in, + int max_pix_ref_u, int min_pix_ref_u, int max_pix_ref_v, + int min_pix_ref_v, UCHAR *calc, int calc_bytesize, + int calc_bytewrap) /* lu = width lv = height wrap_in = wrap */ { - PixType *prev_line_in; - PixType *last_line_in; - PixType prev_value; - PixType left_value; - PixType last_value; - - UINT calc_value; - UCHAR *calc_byte = 0; - int goodcols; - std::unique_ptr col_height(new int[lu]); - int ref_u, ref_v; - int filter_diam_u = max_pix_ref_u - min_pix_ref_u + 1; - int filter_diam_v = max_pix_ref_v - min_pix_ref_v + 1; - int last_u, last_v; - - int *ch; - int *ch_end; - - assert(col_height); - - CALC_VALUE_INIT - ch = col_height.get(); - ch_end = ch + lu; - - while (ch < ch_end) { - *ch = filter_diam_v; - ++ch; - } - - last_line_in = buffer_in; - for (last_v = 1, ref_v = last_v - max_pix_ref_v; ref_v < 0; last_v++, ref_v++) { - prev_line_in = last_line_in; - last_line_in = buffer_in + last_v * wrap_in; - for (last_u = 0; last_u < lu; last_u++) { - last_value = last_line_in[last_u]; - prev_value = prev_line_in[last_u]; - if (last_value == prev_value) - col_height[last_u]++; - else - col_height[last_u] = 1; - } - } - - for (; last_v < lv; last_v++, ref_v++) { - prev_line_in = last_line_in; - last_line_in = buffer_in + last_v * wrap_in; - last_value = last_line_in[0]; - goodcols = 0; - for (last_u = 0, ref_u = last_u - max_pix_ref_u; ref_u < 0; last_u++, ref_u++) { - left_value = last_value; - last_value = last_line_in[last_u]; - prev_value = prev_line_in[last_u]; - if (last_value == prev_value) { - col_height[last_u]++; - if (col_height[last_u] >= filter_diam_v) - if (last_value == left_value) - goodcols++; - else - goodcols = 1; - else - goodcols = 0; - } else { - col_height[last_u] = 1; - goodcols = 0; - } - } - calc_byte = calc + calc_bytewrap * ref_v; - CALC_VALUE_INIT - for (; last_u < lu; last_u++, ref_u++) { - left_value = last_value; - last_value = last_line_in[last_u]; - prev_value = prev_line_in[last_u]; - if (last_value == prev_value) { - col_height[last_u]++; - if (col_height[last_u] >= filter_diam_v) - if (last_value == left_value) { - goodcols++; - if (goodcols >= filter_diam_u) - CALC_VALUE_NOCALC - } else - goodcols = 1; - else - goodcols = 0; - } else { - col_height[last_u] = 1; - goodcols = 0; - } - if (CALC_VALUE_READY) { - *calc_byte++ = (UCHAR)calc_value; - CALC_VALUE_INIT - } else - CALC_VALUE_ADVANCE - } - for (; ref_u < lu; last_u++, ref_u++) { - if (CALC_VALUE_READY) { - *calc_byte++ = (UCHAR)calc_value; - CALC_VALUE_INIT - } else - CALC_VALUE_ADVANCE - } - if (!CALC_VALUE_EMPTY) { - while (!CALC_VALUE_READY) - CALC_VALUE_ADVANCE - *calc_byte++ = (UCHAR)calc_value; - } - } - - for (; ref_v < lv; last_v++, ref_v++) { - for (last_u = 0, ref_u = last_u - max_pix_ref_u; ref_u < 0; last_u++, ref_u++) { - } - calc_byte = calc + calc_bytewrap * ref_v; - CALC_VALUE_INIT - for (; last_u < lu; last_u++, ref_u++) { - if (CALC_VALUE_READY) { - *calc_byte++ = (UCHAR)calc_value; - CALC_VALUE_INIT - } else - CALC_VALUE_ADVANCE - } - for (; ref_u < lu; last_u++, ref_u++) { - if (CALC_VALUE_READY) { - *calc_byte++ = (UCHAR)calc_value; - CALC_VALUE_INIT - } else - CALC_VALUE_ADVANCE - } - if (!CALC_VALUE_EMPTY) { - while (!CALC_VALUE_READY) - CALC_VALUE_ADVANCE - *calc_byte++ = (UCHAR)calc_value; - } - } - assert(!calc_byte || calc_byte == calc + calc_bytesize); + PixType *prev_line_in; + PixType *last_line_in; + PixType prev_value; + PixType left_value; + PixType last_value; + + UINT calc_value; + UCHAR *calc_byte = 0; + int goodcols; + std::unique_ptr col_height(new int[lu]); + int ref_u, ref_v; + int filter_diam_u = max_pix_ref_u - min_pix_ref_u + 1; + int filter_diam_v = max_pix_ref_v - min_pix_ref_v + 1; + int last_u, last_v; + + int *ch; + int *ch_end; + + assert(col_height); + + CALC_VALUE_INIT + ch = col_height.get(); + ch_end = ch + lu; + + while (ch < ch_end) { + *ch = filter_diam_v; + ++ch; + } + + last_line_in = buffer_in; + for (last_v = 1, ref_v = last_v - max_pix_ref_v; ref_v < 0; + last_v++, ref_v++) { + prev_line_in = last_line_in; + last_line_in = buffer_in + last_v * wrap_in; + for (last_u = 0; last_u < lu; last_u++) { + last_value = last_line_in[last_u]; + prev_value = prev_line_in[last_u]; + if (last_value == prev_value) + col_height[last_u]++; + else + col_height[last_u] = 1; + } + } + + for (; last_v < lv; last_v++, ref_v++) { + prev_line_in = last_line_in; + last_line_in = buffer_in + last_v * wrap_in; + last_value = last_line_in[0]; + goodcols = 0; + for (last_u = 0, ref_u = last_u - max_pix_ref_u; ref_u < 0; + last_u++, ref_u++) { + left_value = last_value; + last_value = last_line_in[last_u]; + prev_value = prev_line_in[last_u]; + if (last_value == prev_value) { + col_height[last_u]++; + if (col_height[last_u] >= filter_diam_v) + if (last_value == left_value) + goodcols++; + else + goodcols = 1; + else + goodcols = 0; + } else { + col_height[last_u] = 1; + goodcols = 0; + } + } + calc_byte = calc + calc_bytewrap * ref_v; + CALC_VALUE_INIT + for (; last_u < lu; last_u++, ref_u++) { + left_value = last_value; + last_value = last_line_in[last_u]; + prev_value = prev_line_in[last_u]; + if (last_value == prev_value) { + col_height[last_u]++; + if (col_height[last_u] >= filter_diam_v) + if (last_value == left_value) { + goodcols++; + if (goodcols >= filter_diam_u) CALC_VALUE_NOCALC + } else + goodcols = 1; + else + goodcols = 0; + } else { + col_height[last_u] = 1; + goodcols = 0; + } + if (CALC_VALUE_READY) { + *calc_byte++ = (UCHAR)calc_value; + CALC_VALUE_INIT + } else + CALC_VALUE_ADVANCE + } + for (; ref_u < lu; last_u++, ref_u++) { + if (CALC_VALUE_READY) { + *calc_byte++ = (UCHAR)calc_value; + CALC_VALUE_INIT + } else + CALC_VALUE_ADVANCE + } + if (!CALC_VALUE_EMPTY) { + while (!CALC_VALUE_READY) CALC_VALUE_ADVANCE + *calc_byte++ = (UCHAR)calc_value; + } + } + + for (; ref_v < lv; last_v++, ref_v++) { + for (last_u = 0, ref_u = last_u - max_pix_ref_u; ref_u < 0; + last_u++, ref_u++) { + } + calc_byte = calc + calc_bytewrap * ref_v; + CALC_VALUE_INIT + for (; last_u < lu; last_u++, ref_u++) { + if (CALC_VALUE_READY) { + *calc_byte++ = (UCHAR)calc_value; + CALC_VALUE_INIT + } else + CALC_VALUE_ADVANCE + } + for (; ref_u < lu; last_u++, ref_u++) { + if (CALC_VALUE_READY) { + *calc_byte++ = (UCHAR)calc_value; + CALC_VALUE_INIT + } else + CALC_VALUE_ADVANCE + } + if (!CALC_VALUE_EMPTY) { + while (!CALC_VALUE_READY) CALC_VALUE_ADVANCE + *calc_byte++ = (UCHAR)calc_value; + } + } + assert(!calc_byte || calc_byte == calc + calc_bytesize); } /*---------------------------------------------------------------------------*/ template -void create_calc(const TRasterPT &rin, - int min_pix_ref_u, int max_pix_ref_u, - int min_pix_ref_v, int max_pix_ref_v, - UCHAR *&p_calc, int &p_calc_allocsize, int &p_calc_bytewrap) -{ - UCHAR *calc; - int lu, lv; - int wrap_in; - int calc_bytesize; - int calc_bytewrap; - - lu = rin->getLx(); - lv = rin->getLy(); - wrap_in = rin->getWrap(); - - p_calc_bytewrap = (lu + 7) >> 3; // ceil(lu/8) - calc_bytewrap = p_calc_bytewrap; - calc_bytesize = calc_bytewrap * lv; // lv * ceil(lu/8) - if (calc_bytesize > p_calc_allocsize) { - if (p_calc_allocsize) - delete[](p_calc); - //TMALLOC (*p_calc, calc_bytesize) - p_calc = new UCHAR[calc_bytesize]; - assert(p_calc); - memset(p_calc, 0xff, calc_bytesize); - p_calc_allocsize = calc_bytesize; - } - calc = p_calc; - if (lu < max_pix_ref_u + 1 || lv < max_pix_ref_v + 1) { - memset(calc, 0xff, calc_bytesize); - return; - } - - //RESAMPLE_CALC_ALGO - - ResampleCalcAlgo(rin->pixels(), lu, lv, wrap_in, max_pix_ref_u, min_pix_ref_u, - max_pix_ref_v, min_pix_ref_v, calc, calc_bytesize, calc_bytewrap); - +void create_calc(const TRasterPT &rin, int min_pix_ref_u, int max_pix_ref_u, + int min_pix_ref_v, int max_pix_ref_v, UCHAR *&p_calc, + int &p_calc_allocsize, int &p_calc_bytewrap) { + UCHAR *calc; + int lu, lv; + int wrap_in; + int calc_bytesize; + int calc_bytewrap; + + lu = rin->getLx(); + lv = rin->getLy(); + wrap_in = rin->getWrap(); + + p_calc_bytewrap = (lu + 7) >> 3; // ceil(lu/8) + calc_bytewrap = p_calc_bytewrap; + calc_bytesize = calc_bytewrap * lv; // lv * ceil(lu/8) + if (calc_bytesize > p_calc_allocsize) { + if (p_calc_allocsize) delete[](p_calc); + // TMALLOC (*p_calc, calc_bytesize) + p_calc = new UCHAR[calc_bytesize]; + assert(p_calc); + memset(p_calc, 0xff, calc_bytesize); + p_calc_allocsize = calc_bytesize; + } + calc = p_calc; + if (lu < max_pix_ref_u + 1 || lv < max_pix_ref_v + 1) { + memset(calc, 0xff, calc_bytesize); + return; + } + + // RESAMPLE_CALC_ALGO + + ResampleCalcAlgo(rin->pixels(), lu, lv, wrap_in, max_pix_ref_u, + min_pix_ref_u, max_pix_ref_v, min_pix_ref_v, calc, + calc_bytesize, calc_bytewrap); } //--------------------------------------------------------------------------- -namespace -{ +namespace { template -class Converter -{ +class Converter { public: - static inline T convert(const TPixel32 &pixin) - { - return pixin; - } + static inline T convert(const TPixel32 &pixin) { return pixin; } }; #define BYTE_FROM_USHORT(u) (((256U * 255U + 1U) * u + (1 << 23)) >> 24) #define USHORT_FROM_BYTE(u) (u | u << 8) template <> -class Converter -{ +class Converter { public: - static inline TPixel64 convert(const TPixel32 &pix) - { - return TPixel64( - USHORT_FROM_BYTE(pix.r), - USHORT_FROM_BYTE(pix.g), - USHORT_FROM_BYTE(pix.b), - USHORT_FROM_BYTE(pix.m)); - } + static inline TPixel64 convert(const TPixel32 &pix) { + return TPixel64(USHORT_FROM_BYTE(pix.r), USHORT_FROM_BYTE(pix.g), + USHORT_FROM_BYTE(pix.b), USHORT_FROM_BYTE(pix.m)); + } }; //----------------------------------------------------------------------------- -inline double get_filter_value(TRop::ResampleFilterType flt_type, double x) -{ - //it is assumed that x != 0 (not checked only for speed reasons) - switch (flt_type) { - case TRop::Triangle: - if (x < -1.0) - return 0.0; - if (x < 0.0) - return 1.0 + x; - if (x < 1.0) - return 1.0 - x; - return 0.0; - - case TRop::Mitchell: { - static double p0, p2, p3, q0, q1, q2, q3; - - if (!p0) { - const double b = 1.0 / 3.0; - const double c = 1.0 / 3.0; - - p0 = (6.0 - 2.0 * b) / 6.0; - p2 = (-18.0 + 12.0 * b + 6.0 * c) / 6.0; - p3 = (12.0 - 9.0 * b - 6.0 * c) / 6.0; - q0 = (8.0 * b + 24.0 * c) / 6.0; - q1 = (-12.0 * b - 48.0 * c) / 6.0; - q2 = (6.0 * b + 30.0 * c) / 6.0; - q3 = (-b - 6.0 * c) / 6.0; - } - if (x < -2.0) - return 0.0; - if (x < -1.0) - return (q0 - x * (q1 - x * (q2 - x * q3))); - if (x < 0.0) - return (p0 + x * x * (p2 - x * p3)); - if (x < 1.0) - return (p0 + x * x * (p2 + x * p3)); - if (x < 2.0) - return (q0 + x * (q1 + x * (q2 + x * q3))); - - break; - } - - case TRop::Cubic5: - if (x < 0.0) x = -x; - if (x < 1.0) - return 2.5 * x * x * x - 3.5 * x * x + 1; - if (x < 2.0) - return 0.5 * x * x * x - 2.5 * x * x + 4 * x - 2; - break; - - case TRop::Cubic75: - if (x < 0.0) x = -x; - if (x < 1.0) - return 2.75 * x * x * x - 3.75 * x * x + 1; - if (x < 2.0) - return 0.75 * x * x * x - 3.75 * x * x + 6 * x - 3; - break; - - case TRop::Cubic1: - if (x < 0.0) x = -x; - if (x < 1.0) - return 3 * x * x * x - 4 * x * x + 1; - if (x < 2.0) - return x * x * x - 5 * x * x + 8 * x - 4; - break; - - case TRop::Hann2: - if (x <= -2.0) return 0.0; - if (x < 2.0) - return sinc0(x, 1) * (0.5 + 0.5 * cos((pi / 2) * x)); - break; - - case TRop::Hann3: - if (x <= -3.0) return 0.0; - if (x < 3.0) - return sinc0(x, 1) * (0.5 + 0.5 * cos((pi / 3) * x)); - break; - - case TRop::Hamming2: - if (x <= -2.0) return 0.0; - if (x < 2.0) - return sinc0(x, 1) * (0.54 + 0.46 * cos((pi / 2) * x)); - break; - - case TRop::Hamming3: - if (x <= -3.0) return 0.0; - if (x < 3.0) - return sinc0(x, 1) * (0.54 + 0.46 * cos((pi / 3) * x)); - break; - - case TRop::Lanczos2: - if (x <= -2.0) return 0.0; - if (x < 2.0) - return sinc0(x, 1) * sinc0(x, 2); - break; - - case TRop::Lanczos3: - if (x <= -3.0) return 0.0; - if (x < 3.0) - return sinc0(x, 1) * sinc0(x, 3); - break; - - case TRop::Gauss: - if (x <= -2.0) return 0.0; - if (x < 2.0) - return exp((-pi) * x * x); /* exp(-M_PI*2*2)~=3.5*10^-6 */ - break; - default: - assert(!"bad filter type"); - break; - } - return 0.0; +inline double get_filter_value(TRop::ResampleFilterType flt_type, double x) { + // it is assumed that x != 0 (not checked only for speed reasons) + switch (flt_type) { + case TRop::Triangle: + if (x < -1.0) return 0.0; + if (x < 0.0) return 1.0 + x; + if (x < 1.0) return 1.0 - x; + return 0.0; + + case TRop::Mitchell: { + static double p0, p2, p3, q0, q1, q2, q3; + + if (!p0) { + const double b = 1.0 / 3.0; + const double c = 1.0 / 3.0; + + p0 = (6.0 - 2.0 * b) / 6.0; + p2 = (-18.0 + 12.0 * b + 6.0 * c) / 6.0; + p3 = (12.0 - 9.0 * b - 6.0 * c) / 6.0; + q0 = (8.0 * b + 24.0 * c) / 6.0; + q1 = (-12.0 * b - 48.0 * c) / 6.0; + q2 = (6.0 * b + 30.0 * c) / 6.0; + q3 = (-b - 6.0 * c) / 6.0; + } + if (x < -2.0) return 0.0; + if (x < -1.0) return (q0 - x * (q1 - x * (q2 - x * q3))); + if (x < 0.0) return (p0 + x * x * (p2 - x * p3)); + if (x < 1.0) return (p0 + x * x * (p2 + x * p3)); + if (x < 2.0) return (q0 + x * (q1 + x * (q2 + x * q3))); + + break; + } + + case TRop::Cubic5: + if (x < 0.0) x = -x; + if (x < 1.0) return 2.5 * x * x * x - 3.5 * x * x + 1; + if (x < 2.0) return 0.5 * x * x * x - 2.5 * x * x + 4 * x - 2; + break; + + case TRop::Cubic75: + if (x < 0.0) x = -x; + if (x < 1.0) return 2.75 * x * x * x - 3.75 * x * x + 1; + if (x < 2.0) return 0.75 * x * x * x - 3.75 * x * x + 6 * x - 3; + break; + + case TRop::Cubic1: + if (x < 0.0) x = -x; + if (x < 1.0) return 3 * x * x * x - 4 * x * x + 1; + if (x < 2.0) return x * x * x - 5 * x * x + 8 * x - 4; + break; + + case TRop::Hann2: + if (x <= -2.0) return 0.0; + if (x < 2.0) return sinc0(x, 1) * (0.5 + 0.5 * cos(M_PI_2 * x)); + break; + + case TRop::Hann3: + if (x <= -3.0) return 0.0; + if (x < 3.0) return sinc0(x, 1) * (0.5 + 0.5 * cos(M_PI_3 * x)); + break; + + case TRop::Hamming2: + if (x <= -2.0) return 0.0; + if (x < 2.0) return sinc0(x, 1) * (0.54 + 0.46 * cos(M_PI_2 * x)); + break; + + case TRop::Hamming3: + if (x <= -3.0) return 0.0; + if (x < 3.0) return sinc0(x, 1) * (0.54 + 0.46 * cos(M_PI_3 * x)); + break; + + case TRop::Lanczos2: + if (x <= -2.0) return 0.0; + if (x < 2.0) return sinc0(x, 1) * sinc0(x, 2); + break; + + case TRop::Lanczos3: + if (x <= -3.0) return 0.0; + if (x < 3.0) return sinc0(x, 1) * sinc0(x, 3); + break; + + case TRop::Gauss: + if (x <= -2.0) return 0.0; + if (x < 2.0) return exp(-M_PI * x * x); /* exp(-M_PI*2*2)~=3.5*10^-6 */ + break; + default: + assert(!"bad filter type"); + break; + } + return 0.0; } //--------------------------------------------------------------------------- template -void resample_clear_rgbm(TRasterPT rout, T default_value) -{ - T *buffer_out; - buffer_out = rout->pixels(); - for (int out_y = 0; out_y < rout->getLy(); out_y++) - for (int out_x = 0; out_x < rout->getLx(); out_x++) - buffer_out[out_x + out_y * rout->getWrap()] = default_value; +void resample_clear_rgbm(TRasterPT rout, T default_value) { + T *buffer_out; + buffer_out = rout->pixels(); + for (int out_y = 0; out_y < rout->getLy(); out_y++) + for (int out_x = 0; out_x < rout->getLx(); out_x++) + buffer_out[out_x + out_y * rout->getWrap()] = default_value; } //--------------------------------------------------------------------------- template void resample_main_rgbm(TRasterPT rout, const TRasterPT &rin, - const TAffine &aff_xy2uv, - const TAffine &aff0_uv2fg, - int min_pix_ref_u, int min_pix_ref_v, - int max_pix_ref_u, int max_pix_ref_v, - int n_pix, - int *pix_ref_u, int *pix_ref_v, - int *pix_ref_f, int *pix_ref_g, - short *filter) -{ - const T *buffer_in; - T *buffer_out; - T *pix_out; - int lu, lv, wrap_in, mu, mv; - int lx, ly, wrap_out; - int out_x, out_y; - double out_x_, out_y_; - double out_u_, out_v_; - int ref_u, ref_v; - int pix_u, pix_v; - double ref_out_u_, ref_out_v_; - double ref_out_f_, ref_out_g_; - int ref_out_f, ref_out_g; - int pix_out_f, pix_out_g; - int filter_mu, filter_mv; - UINT inside_limit_u, inside_limit_v; - int inside_nonempty; - int outside_min_u, outside_min_v; - int outside_max_u, outside_max_v; - UCHAR *calc; - int calc_allocsize; - int calc_bytewrap; - UCHAR calc_value; - bool must_calc; - T pix_value, default_value(0, 0, 0, 0); - SUMS_TYPE weight, sum_weights; - double inv_sum_weights; - SUMS_TYPE sum_contribs_r, sum_contribs_g, sum_contribs_b, sum_contribs_m; - double out_fval_r, out_fval_g, out_fval_b, out_fval_m; - int out_value_r, out_value_g, out_value_b, out_value_m; - int i; + const TAffine &aff_xy2uv, const TAffine &aff0_uv2fg, + int min_pix_ref_u, int min_pix_ref_v, int max_pix_ref_u, + int max_pix_ref_v, int n_pix, int *pix_ref_u, + int *pix_ref_v, int *pix_ref_f, int *pix_ref_g, + short *filter) { + const T *buffer_in; + T *buffer_out; + T *pix_out; + int lu, lv, wrap_in, mu, mv; + int lx, ly, wrap_out; + int out_x, out_y; + double out_x_, out_y_; + double out_u_, out_v_; + int ref_u, ref_v; + int pix_u, pix_v; + double ref_out_u_, ref_out_v_; + double ref_out_f_, ref_out_g_; + int ref_out_f, ref_out_g; + int pix_out_f, pix_out_g; + int filter_mu, filter_mv; + UINT inside_limit_u, inside_limit_v; + int inside_nonempty; + int outside_min_u, outside_min_v; + int outside_max_u, outside_max_v; + UCHAR *calc; + int calc_allocsize; + int calc_bytewrap; + UCHAR calc_value; + bool must_calc; + T pix_value, default_value(0, 0, 0, 0); + SUMS_TYPE weight, sum_weights; + double inv_sum_weights; + SUMS_TYPE sum_contribs_r, sum_contribs_g, sum_contribs_b, sum_contribs_m; + double out_fval_r, out_fval_g, out_fval_b, out_fval_m; + int out_value_r, out_value_g, out_value_b, out_value_m; + int i; #ifdef USE_DOUBLE_TO_INT - double d2iaux; + double d2iaux; #endif - if (!(rout->getLx() > 0 && rout->getLy() > 0)) - return; - - if (!(rin->getLx() > 0 && rin->getLy() > 0)) { - rout->clear(); - return; - } - - calc = 0; - calc_allocsize = 0; - - //Create a bit array, each indicating whether a pixel has to be calculated or not - create_calc(rin, min_pix_ref_u, max_pix_ref_u, - min_pix_ref_v, max_pix_ref_v, - calc, calc_allocsize, calc_bytewrap); - - buffer_in = rin->pixels(); - buffer_out = rout->pixels(); - lu = rin->getLx(); - lx = rout->getLx(); - lv = rin->getLy(); - ly = rout->getLy(); - wrap_in = rin->getWrap(); - wrap_out = rout->getWrap(); - mu = lu - 1; - mv = lv - 1; - - filter_mu = max_pix_ref_u - min_pix_ref_u; - filter_mv = max_pix_ref_v - min_pix_ref_v; - inside_limit_u = lu - filter_mu; - inside_limit_v = lv - filter_mv; - inside_nonempty = (int)inside_limit_u > 0 && (int)inside_limit_v > 0; - outside_min_u = -max_pix_ref_u; - outside_min_v = -max_pix_ref_v; - outside_max_u = mu - min_pix_ref_u; - outside_max_v = mv - min_pix_ref_v; - - //For every pixel of the output image - for (out_y = 0, out_y_ = 0.5; out_y < ly; out_y++, out_y_ += 1.0) { - for (out_x = 0, out_x_ = 0.5; out_x < lx; out_x++, out_x_ += 1.0) { - pix_out = buffer_out + out_y * wrap_out + out_x; - - //Take the pre-image of the pixel through the passed affine - out_u_ = affMV1(aff_xy2uv, out_x_, out_y_); - out_v_ = affMV2(aff_xy2uv, out_x_, out_y_); - - //Convert to integer coordinates - ref_u = intLE(out_u_); - ref_v = intLE(out_v_); - - //NOTE: The following condition is equivalent to: - // (ref_u + min_pix_ref_u >= 0 && ref_v + min_pix_ref_v >= 0 && - // ref_u + max_pix_ref_u < lu && ref_v + max_pix_ref_v < lv) - // - since the presence of (UINT) makes integeres < 0 become >> 0 - if (inside_nonempty && - (UINT)(ref_u + min_pix_ref_u) < inside_limit_u && - (UINT)(ref_v + min_pix_ref_v) < inside_limit_v) { - //The filter mask starting around (ref_u, ref_v) is completely contained - //in the source raster - - //Get the calculation array mask byte - calc_value = calc[(ref_u >> 3) + ref_v * calc_bytewrap]; - if (calc_value && ((calc_value >> (ref_u & 7)) & 1)) //If the mask bit for this pixel is on - { - ref_out_u_ = ref_u - out_u_; //Fractionary part of the pre-image - ref_out_v_ = ref_v - out_v_; - ref_out_f_ = aff0MV1(aff0_uv2fg, ref_out_u_, ref_out_v_); //Make the image of it into fg - ref_out_g_ = aff0MV2(aff0_uv2fg, ref_out_u_, ref_out_v_); - ref_out_f = tround(ref_out_f_); //Convert to integer coordinates - ref_out_g = tround(ref_out_g_); - - sum_weights = 0; - sum_contribs_r = 0; - sum_contribs_g = 0; - sum_contribs_b = 0; - sum_contribs_m = 0; - - //Make the weighted sum of source pixels - for (i = n_pix - 1; i >= 0; --i) { - //Build the weight for this pixel - pix_out_f = pix_ref_f[i] + ref_out_f; //image of the integer part + that of the fractionary part - pix_out_g = pix_ref_g[i] + ref_out_g; - weight = (filter[pix_out_f] * filter[pix_out_g]) >> 16; - - //Add the weighted pixel contribute - pix_u = pix_ref_u[i] + ref_u; - pix_v = pix_ref_v[i] + ref_v; - - pix_value = buffer_in[pix_u + pix_v * wrap_in]; - sum_contribs_r += (SUMS_TYPE)pix_value.r * weight; - sum_contribs_g += (SUMS_TYPE)pix_value.g * weight; - sum_contribs_b += (SUMS_TYPE)pix_value.b * weight; - sum_contribs_m += (SUMS_TYPE)pix_value.m * weight; - sum_weights += weight; - } - - inv_sum_weights = 1.0 / sum_weights; - out_fval_r = sum_contribs_r * inv_sum_weights; - out_fval_g = sum_contribs_g * inv_sum_weights; - out_fval_b = sum_contribs_b * inv_sum_weights; - out_fval_m = sum_contribs_m * inv_sum_weights; - notLessThan(0.0, out_fval_r); - notLessThan(0.0, out_fval_g); - notLessThan(0.0, out_fval_b); - notLessThan(0.0, out_fval_m); - out_value_r = troundp(out_fval_r); - out_value_g = troundp(out_fval_g); - out_value_b = troundp(out_fval_b); - out_value_m = troundp(out_fval_m); - notMoreThan(T::maxChannelValue, out_value_r); - notMoreThan(T::maxChannelValue, out_value_g); - notMoreThan(T::maxChannelValue, out_value_b); - notMoreThan(T::maxChannelValue, out_value_m); - pix_out->r = out_value_r; - pix_out->g = out_value_g; - pix_out->b = out_value_b; - pix_out->m = out_value_m; - } else - //The pixel is copied from the corresponding source... - *pix_out = buffer_in[ref_u + ref_v * wrap_in]; - } else if (outside_min_u <= ref_u && ref_u <= outside_max_u && - outside_min_v <= ref_v && ref_v <= outside_max_v) { - if ((UINT)ref_u >= (UINT)lu || (UINT)ref_v >= (UINT)lv) - must_calc = true; - else { - calc_value = calc[(ref_u >> 3) + ref_v * calc_bytewrap]; - must_calc = calc_value && ((calc_value >> (ref_u & 7)) & 1); - } - - if (must_calc) { - ref_out_u_ = ref_u - out_u_; - ref_out_v_ = ref_v - out_v_; - ref_out_f_ = aff0MV1(aff0_uv2fg, ref_out_u_, ref_out_v_); - ref_out_g_ = aff0MV2(aff0_uv2fg, ref_out_u_, ref_out_v_); - ref_out_f = tround(ref_out_f_); - ref_out_g = tround(ref_out_g_); - sum_weights = 0; - sum_contribs_r = 0; - sum_contribs_g = 0; - sum_contribs_b = 0; - sum_contribs_m = 0; - - for (i = n_pix - 1; i >= 0; --i) { - pix_out_f = pix_ref_f[i] + ref_out_f; - pix_out_g = pix_ref_g[i] + ref_out_g; - weight = (filter[pix_out_f] * filter[pix_out_g]) >> 16; - pix_u = pix_ref_u[i] + ref_u; - pix_v = pix_ref_v[i] + ref_v; - - if (pix_u < 0 || pix_u > mu || - pix_v < 0 || pix_v > mv) { - sum_weights += weight; //0-padding - continue; - } - - notLessThan(0, pix_u); //Copy-padding - notLessThan(0, pix_v); - notMoreThan(mu, pix_u); - notMoreThan(mv, pix_v); - - pix_value = buffer_in[pix_u + pix_v * wrap_in]; - sum_contribs_r += (SUMS_TYPE)pix_value.r * weight; - sum_contribs_g += (SUMS_TYPE)pix_value.g * weight; - sum_contribs_b += (SUMS_TYPE)pix_value.b * weight; - sum_contribs_m += (SUMS_TYPE)pix_value.m * weight; - sum_weights += weight; - } - - inv_sum_weights = 1.0 / sum_weights; - out_fval_r = sum_contribs_r * inv_sum_weights; - out_fval_g = sum_contribs_g * inv_sum_weights; - out_fval_b = sum_contribs_b * inv_sum_weights; - out_fval_m = sum_contribs_m * inv_sum_weights; - notLessThan(0.0, out_fval_r); - notLessThan(0.0, out_fval_g); - notLessThan(0.0, out_fval_b); - notLessThan(0.0, out_fval_m); - out_value_r = troundp(out_fval_r); - out_value_g = troundp(out_fval_g); - out_value_b = troundp(out_fval_b); - out_value_m = troundp(out_fval_m); - notMoreThan(T::maxChannelValue, out_value_r); - notMoreThan(T::maxChannelValue, out_value_g); - notMoreThan(T::maxChannelValue, out_value_b); - notMoreThan(T::maxChannelValue, out_value_m); - pix_out->r = out_value_r; - pix_out->g = out_value_g; - pix_out->b = out_value_b; - pix_out->m = out_value_m; - } else - *pix_out = buffer_in[ref_u + ref_v * wrap_in]; - } else - *pix_out = default_value; - } - } - - delete[] calc; + if (!(rout->getLx() > 0 && rout->getLy() > 0)) return; + + if (!(rin->getLx() > 0 && rin->getLy() > 0)) { + rout->clear(); + return; + } + + calc = 0; + calc_allocsize = 0; + + // Create a bit array, each indicating whether a pixel has to be calculated or + // not + create_calc(rin, min_pix_ref_u, max_pix_ref_u, min_pix_ref_v, max_pix_ref_v, + calc, calc_allocsize, calc_bytewrap); + + buffer_in = rin->pixels(); + buffer_out = rout->pixels(); + lu = rin->getLx(); + lx = rout->getLx(); + lv = rin->getLy(); + ly = rout->getLy(); + wrap_in = rin->getWrap(); + wrap_out = rout->getWrap(); + mu = lu - 1; + mv = lv - 1; + + filter_mu = max_pix_ref_u - min_pix_ref_u; + filter_mv = max_pix_ref_v - min_pix_ref_v; + inside_limit_u = lu - filter_mu; + inside_limit_v = lv - filter_mv; + inside_nonempty = (int)inside_limit_u > 0 && (int)inside_limit_v > 0; + outside_min_u = -max_pix_ref_u; + outside_min_v = -max_pix_ref_v; + outside_max_u = mu - min_pix_ref_u; + outside_max_v = mv - min_pix_ref_v; + + // For every pixel of the output image + for (out_y = 0, out_y_ = 0.5; out_y < ly; out_y++, out_y_ += 1.0) { + for (out_x = 0, out_x_ = 0.5; out_x < lx; out_x++, out_x_ += 1.0) { + pix_out = buffer_out + out_y * wrap_out + out_x; + + // Take the pre-image of the pixel through the passed affine + out_u_ = affMV1(aff_xy2uv, out_x_, out_y_); + out_v_ = affMV2(aff_xy2uv, out_x_, out_y_); + + // Convert to integer coordinates + ref_u = intLE(out_u_); + ref_v = intLE(out_v_); + + // NOTE: The following condition is equivalent to: + // (ref_u + min_pix_ref_u >= 0 && ref_v + min_pix_ref_v >= 0 && + // ref_u + max_pix_ref_u < lu && ref_v + max_pix_ref_v < lv) + // - since the presence of (UINT) makes integeres < 0 become >> 0 + if (inside_nonempty && (UINT)(ref_u + min_pix_ref_u) < inside_limit_u && + (UINT)(ref_v + min_pix_ref_v) < inside_limit_v) { + // The filter mask starting around (ref_u, ref_v) is completely + // contained + // in the source raster + + // Get the calculation array mask byte + calc_value = calc[(ref_u >> 3) + ref_v * calc_bytewrap]; + if (calc_value && ((calc_value >> (ref_u & 7)) & + 1)) // If the mask bit for this pixel is on + { + ref_out_u_ = ref_u - out_u_; // Fractionary part of the pre-image + ref_out_v_ = ref_v - out_v_; + ref_out_f_ = aff0MV1(aff0_uv2fg, ref_out_u_, + ref_out_v_); // Make the image of it into fg + ref_out_g_ = aff0MV2(aff0_uv2fg, ref_out_u_, ref_out_v_); + ref_out_f = tround(ref_out_f_); // Convert to integer coordinates + ref_out_g = tround(ref_out_g_); + + sum_weights = 0; + sum_contribs_r = 0; + sum_contribs_g = 0; + sum_contribs_b = 0; + sum_contribs_m = 0; + + // Make the weighted sum of source pixels + for (i = n_pix - 1; i >= 0; --i) { + // Build the weight for this pixel + pix_out_f = pix_ref_f[i] + ref_out_f; // image of the integer part + // + that of the fractionary + // part + pix_out_g = pix_ref_g[i] + ref_out_g; + weight = (filter[pix_out_f] * filter[pix_out_g]) >> 16; + + // Add the weighted pixel contribute + pix_u = pix_ref_u[i] + ref_u; + pix_v = pix_ref_v[i] + ref_v; + + pix_value = buffer_in[pix_u + pix_v * wrap_in]; + sum_contribs_r += (SUMS_TYPE)pix_value.r * weight; + sum_contribs_g += (SUMS_TYPE)pix_value.g * weight; + sum_contribs_b += (SUMS_TYPE)pix_value.b * weight; + sum_contribs_m += (SUMS_TYPE)pix_value.m * weight; + sum_weights += weight; + } + + inv_sum_weights = 1.0 / sum_weights; + out_fval_r = sum_contribs_r * inv_sum_weights; + out_fval_g = sum_contribs_g * inv_sum_weights; + out_fval_b = sum_contribs_b * inv_sum_weights; + out_fval_m = sum_contribs_m * inv_sum_weights; + notLessThan(0.0, out_fval_r); + notLessThan(0.0, out_fval_g); + notLessThan(0.0, out_fval_b); + notLessThan(0.0, out_fval_m); + out_value_r = troundp(out_fval_r); + out_value_g = troundp(out_fval_g); + out_value_b = troundp(out_fval_b); + out_value_m = troundp(out_fval_m); + notMoreThan(T::maxChannelValue, out_value_r); + notMoreThan(T::maxChannelValue, out_value_g); + notMoreThan(T::maxChannelValue, out_value_b); + notMoreThan(T::maxChannelValue, out_value_m); + pix_out->r = out_value_r; + pix_out->g = out_value_g; + pix_out->b = out_value_b; + pix_out->m = out_value_m; + } else + // The pixel is copied from the corresponding source... + *pix_out = buffer_in[ref_u + ref_v * wrap_in]; + } else if (outside_min_u <= ref_u && ref_u <= outside_max_u && + outside_min_v <= ref_v && ref_v <= outside_max_v) { + if ((UINT)ref_u >= (UINT)lu || (UINT)ref_v >= (UINT)lv) + must_calc = true; + else { + calc_value = calc[(ref_u >> 3) + ref_v * calc_bytewrap]; + must_calc = calc_value && ((calc_value >> (ref_u & 7)) & 1); + } + + if (must_calc) { + ref_out_u_ = ref_u - out_u_; + ref_out_v_ = ref_v - out_v_; + ref_out_f_ = aff0MV1(aff0_uv2fg, ref_out_u_, ref_out_v_); + ref_out_g_ = aff0MV2(aff0_uv2fg, ref_out_u_, ref_out_v_); + ref_out_f = tround(ref_out_f_); + ref_out_g = tround(ref_out_g_); + sum_weights = 0; + sum_contribs_r = 0; + sum_contribs_g = 0; + sum_contribs_b = 0; + sum_contribs_m = 0; + + for (i = n_pix - 1; i >= 0; --i) { + pix_out_f = pix_ref_f[i] + ref_out_f; + pix_out_g = pix_ref_g[i] + ref_out_g; + weight = (filter[pix_out_f] * filter[pix_out_g]) >> 16; + pix_u = pix_ref_u[i] + ref_u; + pix_v = pix_ref_v[i] + ref_v; + + if (pix_u < 0 || pix_u > mu || pix_v < 0 || pix_v > mv) { + sum_weights += weight; // 0-padding + continue; + } + + notLessThan(0, pix_u); // Copy-padding + notLessThan(0, pix_v); + notMoreThan(mu, pix_u); + notMoreThan(mv, pix_v); + + pix_value = buffer_in[pix_u + pix_v * wrap_in]; + sum_contribs_r += (SUMS_TYPE)pix_value.r * weight; + sum_contribs_g += (SUMS_TYPE)pix_value.g * weight; + sum_contribs_b += (SUMS_TYPE)pix_value.b * weight; + sum_contribs_m += (SUMS_TYPE)pix_value.m * weight; + sum_weights += weight; + } + + inv_sum_weights = 1.0 / sum_weights; + out_fval_r = sum_contribs_r * inv_sum_weights; + out_fval_g = sum_contribs_g * inv_sum_weights; + out_fval_b = sum_contribs_b * inv_sum_weights; + out_fval_m = sum_contribs_m * inv_sum_weights; + notLessThan(0.0, out_fval_r); + notLessThan(0.0, out_fval_g); + notLessThan(0.0, out_fval_b); + notLessThan(0.0, out_fval_m); + out_value_r = troundp(out_fval_r); + out_value_g = troundp(out_fval_g); + out_value_b = troundp(out_fval_b); + out_value_m = troundp(out_fval_m); + notMoreThan(T::maxChannelValue, out_value_r); + notMoreThan(T::maxChannelValue, out_value_g); + notMoreThan(T::maxChannelValue, out_value_b); + notMoreThan(T::maxChannelValue, out_value_m); + pix_out->r = out_value_r; + pix_out->g = out_value_g; + pix_out->b = out_value_b; + pix_out->m = out_value_m; + } else + *pix_out = buffer_in[ref_u + ref_v * wrap_in]; + } else + *pix_out = default_value; + } + } + + delete[] calc; } //--------------------------------------------------------------------------- #ifdef _WIN32 -namespace -{ +namespace { -__declspec(align(16)) class TPixelFloat -{ +__declspec(align(16)) class TPixelFloat { public: - TPixelFloat() : b(0), g(0), r(0), m(0) {} + TPixelFloat() : b(0), g(0), r(0), m(0) {} - TPixelFloat(float rr, float gg, float bb, float mm) - : b(bb), g(gg), r(rr), m(mm) {} + TPixelFloat(float rr, float gg, float bb, float mm) + : b(bb), g(gg), r(rr), m(mm) {} - TPixelFloat(const TPixel32 &pix) - : b(pix.b), g(pix.g), r(pix.r), m(pix.m) {} + TPixelFloat(const TPixel32 &pix) : b(pix.b), g(pix.g), r(pix.r), m(pix.m) {} - float b, g, r, m; + float b, g, r, m; }; -} // anonymous namespace +} // anonymous namespace //--------------------------------------------------------------------------- template void resample_main_rgbm_SSE2(TRasterPT rout, const TRasterPT &rin, - const TAffine &aff_xy2uv, - const TAffine &aff0_uv2fg, - int min_pix_ref_u, int min_pix_ref_v, - int max_pix_ref_u, int max_pix_ref_v, - int n_pix, - int *pix_ref_u, int *pix_ref_v, - int *pix_ref_f, int *pix_ref_g, - short *filter) -{ - __m128i zeros = _mm_setzero_si128(); - const T *buffer_in; - T *buffer_out; - int lu, lv, wrap_in, mu, mv; - int lx, ly, wrap_out; - int out_x, out_y; - double out_x_, out_y_; - double out_u_, out_v_; - int ref_u, ref_v; - int pix_u, pix_v; - double ref_out_u_, ref_out_v_; - double ref_out_f_, ref_out_g_; - int ref_out_f, ref_out_g; - int pix_out_f, pix_out_g; - int filter_mu, filter_mv; - UINT inside_limit_u, inside_limit_v; - int inside_nonempty; - //double outside_min_u_, outside_min_v_; - //double outside_max_u_, outside_max_v_; - int outside_min_u, outside_min_v; - int outside_max_u, outside_max_v; - UCHAR *calc; - int calc_allocsize; - int calc_bytewrap; - UCHAR calc_value; - bool must_calc; - T pix_value; - T default_value(0, 0, 0, 0); - float weight; - float sum_weights; - float inv_sum_weights; - int i; + const TAffine &aff_xy2uv, + const TAffine &aff0_uv2fg, int min_pix_ref_u, + int min_pix_ref_v, int max_pix_ref_u, + int max_pix_ref_v, int n_pix, int *pix_ref_u, + int *pix_ref_v, int *pix_ref_f, int *pix_ref_g, + short *filter) { + __m128i zeros = _mm_setzero_si128(); + const T *buffer_in; + T *buffer_out; + int lu, lv, wrap_in, mu, mv; + int lx, ly, wrap_out; + int out_x, out_y; + double out_x_, out_y_; + double out_u_, out_v_; + int ref_u, ref_v; + int pix_u, pix_v; + double ref_out_u_, ref_out_v_; + double ref_out_f_, ref_out_g_; + int ref_out_f, ref_out_g; + int pix_out_f, pix_out_g; + int filter_mu, filter_mv; + UINT inside_limit_u, inside_limit_v; + int inside_nonempty; + // double outside_min_u_, outside_min_v_; + // double outside_max_u_, outside_max_v_; + int outside_min_u, outside_min_v; + int outside_max_u, outside_max_v; + UCHAR *calc; + int calc_allocsize; + int calc_bytewrap; + UCHAR calc_value; + bool must_calc; + T pix_value; + T default_value(0, 0, 0, 0); + float weight; + float sum_weights; + float inv_sum_weights; + int i; #ifdef USE_DOUBLE_TO_INT - double d2iaux; + double d2iaux; #endif - T *pix_out; - - __m128 sum_contribs_packed; - - __m128i pix_value_packed_i; - __m128 pix_value_packed; - __m128 weight_packed; - - __m128 zeros2 = _mm_setzero_ps(); - - float maxChannelValue = (float)T::maxChannelValue; - __m128 maxChanneValue_packed = _mm_load1_ps(&maxChannelValue); - - if (!(rout->getLx() > 0 && rout->getLy() > 0)) - return; - if (!(rin->getLx() > 0 && rin->getLy() > 0)) { - resample_clear_rgbm(rout, default_value); - return; - } - calc = 0; - calc_allocsize = 0; - create_calc(rin, min_pix_ref_u, max_pix_ref_u, - min_pix_ref_v, max_pix_ref_v, - calc, calc_allocsize, calc_bytewrap); - - buffer_in = rin->pixels(); - buffer_out = rout->pixels(); - lu = rin->getLx(); - lx = rout->getLx(); - lv = rin->getLy(); - ly = rout->getLy(); - wrap_in = rin->getWrap(); - wrap_out = rout->getWrap(); - mu = lu - 1; - mv = lv - 1; - - filter_mu = max_pix_ref_u - min_pix_ref_u; - filter_mv = max_pix_ref_v - min_pix_ref_v; - inside_limit_u = lu - filter_mu; - inside_limit_v = lv - filter_mv; - inside_nonempty = (int)inside_limit_u > 0 && (int)inside_limit_v > 0; - outside_min_u = -max_pix_ref_u; - outside_min_v = -max_pix_ref_v; - outside_max_u = mu - min_pix_ref_u; - outside_max_v = mv - min_pix_ref_v; - - for (out_y = 0, out_y_ = 0.5; out_y < ly; out_y++, out_y_ += 1.0) { - for (out_x = 0, out_x_ = 0.5; out_x < lx; out_x++, out_x_ += 1.0) { - pix_out = buffer_out + out_y * wrap_out + out_x; - - out_u_ = affMV1(aff_xy2uv, out_x_, out_y_); - out_v_ = affMV2(aff_xy2uv, out_x_, out_y_); - ref_u = intLE(out_u_); - ref_v = intLE(out_v_); - - if (inside_nonempty && - (UINT)(ref_u + min_pix_ref_u) < inside_limit_u && - (UINT)(ref_v + min_pix_ref_v) < inside_limit_v) { - calc_value = calc[(ref_u >> 3) + ref_v * calc_bytewrap]; - - if (calc_value && ((calc_value >> (ref_u & 7)) & 1)) { - ref_out_u_ = ref_u - out_u_; - ref_out_v_ = ref_v - out_v_; - ref_out_f_ = aff0MV1(aff0_uv2fg, ref_out_u_, ref_out_v_); - ref_out_g_ = aff0MV2(aff0_uv2fg, ref_out_u_, ref_out_v_); - ref_out_f = tround(ref_out_f_); - ref_out_g = tround(ref_out_g_); - sum_weights = 0; - - sum_contribs_packed = _mm_setzero_ps(); - - for (i = n_pix - 1; i >= 0; i--) { - pix_out_f = pix_ref_f[i] + ref_out_f; - pix_out_g = pix_ref_g[i] + ref_out_g; - weight = (float)((filter[pix_out_f] * filter[pix_out_g]) >> 16); - pix_u = pix_ref_u[i] + ref_u; - pix_v = pix_ref_v[i] + ref_v; - - pix_value = buffer_in[pix_u + pix_v * wrap_in]; - pix_value_packed_i = _mm_unpacklo_epi8(_mm_cvtsi32_si128(*(DWORD *)&pix_value), zeros); - pix_value_packed = _mm_cvtepi32_ps(_mm_unpacklo_epi16(pix_value_packed_i, zeros)); - - weight_packed = _mm_load1_ps(&weight); - sum_contribs_packed = _mm_add_ps(sum_contribs_packed, _mm_mul_ps(pix_value_packed, weight_packed)); - - sum_weights += weight; - } - - inv_sum_weights = 1.0f / sum_weights; - __m128 inv_sum_weights_packed = _mm_load1_ps(&inv_sum_weights); - - __m128 out_fval_packed = _mm_mul_ps(sum_contribs_packed, inv_sum_weights_packed); - out_fval_packed = _mm_max_ps(out_fval_packed, zeros2); - out_fval_packed = _mm_min_ps(out_fval_packed, maxChanneValue_packed); - - __m128i out_value_packed_i = _mm_cvtps_epi32(out_fval_packed); - out_value_packed_i = _mm_packs_epi32(out_value_packed_i, zeros); - out_value_packed_i = _mm_packus_epi16(out_value_packed_i, zeros); - *(DWORD *)(pix_out) = _mm_cvtsi128_si32(out_value_packed_i); - } else - *pix_out = buffer_in[ref_u + ref_v * wrap_in]; - } else - //if( outside_min_u_ <= out_u_ && out_u_ <= outside_max_u_ && - // outside_min_v_ <= out_v_ && out_v_ <= outside_max_v_ ) - if (outside_min_u <= ref_u && ref_u <= outside_max_u && - outside_min_v <= ref_v && ref_v <= outside_max_v) { - if ((UINT)ref_u >= (UINT)lu || (UINT)ref_v >= (UINT)lv) - must_calc = true; - else { - calc_value = calc[(ref_u >> 3) + ref_v * calc_bytewrap]; - must_calc = calc_value && ((calc_value >> (ref_u & 7)) & 1); - } - - if (must_calc) { - ref_out_u_ = ref_u - out_u_; - ref_out_v_ = ref_v - out_v_; - ref_out_f_ = aff0MV1(aff0_uv2fg, ref_out_u_, ref_out_v_); - ref_out_g_ = aff0MV2(aff0_uv2fg, ref_out_u_, ref_out_v_); - ref_out_f = tround(ref_out_f_); - ref_out_g = tround(ref_out_g_); - sum_weights = 0; - sum_contribs_packed = _mm_setzero_ps(); - - for (i = n_pix - 1; i >= 0; i--) { - pix_out_f = pix_ref_f[i] + ref_out_f; - pix_out_g = pix_ref_g[i] + ref_out_g; - weight = (float)((filter[pix_out_f] * filter[pix_out_g]) >> 16); - pix_u = pix_ref_u[i] + ref_u; - pix_v = pix_ref_v[i] + ref_v; - - if (pix_u < 0 || pix_u > mu || - pix_v < 0 || pix_v > mv) { - sum_weights += weight; - continue; - } - - notLessThan(0, pix_u); - notLessThan(0, pix_v); - notMoreThan(mu, pix_u); - notMoreThan(mv, pix_v); - - pix_value = buffer_in[pix_u + pix_v * wrap_in]; - pix_value_packed_i = _mm_unpacklo_epi8(_mm_cvtsi32_si128(*(DWORD *)&pix_value), zeros); - pix_value_packed = _mm_cvtepi32_ps(_mm_unpacklo_epi16(pix_value_packed_i, zeros)); - - weight_packed = _mm_load1_ps(&weight); - sum_contribs_packed = _mm_add_ps(sum_contribs_packed, _mm_mul_ps(pix_value_packed, weight_packed)); - - sum_weights += weight; - } - inv_sum_weights = 1.0f / sum_weights; - - __m128 inv_sum_weights_packed = _mm_load1_ps(&inv_sum_weights); - __m128 out_fval_packed = _mm_mul_ps(sum_contribs_packed, inv_sum_weights_packed); - out_fval_packed = _mm_max_ps(out_fval_packed, zeros2); - out_fval_packed = _mm_min_ps(out_fval_packed, maxChanneValue_packed); - - __m128i out_value_packed_i = _mm_cvtps_epi32(out_fval_packed); - out_value_packed_i = _mm_packs_epi32(out_value_packed_i, zeros); - out_value_packed_i = _mm_packus_epi16(out_value_packed_i, zeros); - *(DWORD *)(pix_out) = _mm_cvtsi128_si32(out_value_packed_i); - } else - *pix_out = buffer_in[ref_u + ref_v * wrap_in]; - } else { - *pix_out = default_value; - } - } - } - if (calc) - delete[] calc; + T *pix_out; + + __m128 sum_contribs_packed; + + __m128i pix_value_packed_i; + __m128 pix_value_packed; + __m128 weight_packed; + + __m128 zeros2 = _mm_setzero_ps(); + + float maxChannelValue = (float)T::maxChannelValue; + __m128 maxChanneValue_packed = _mm_load1_ps(&maxChannelValue); + + if (!(rout->getLx() > 0 && rout->getLy() > 0)) return; + if (!(rin->getLx() > 0 && rin->getLy() > 0)) { + resample_clear_rgbm(rout, default_value); + return; + } + calc = 0; + calc_allocsize = 0; + create_calc(rin, min_pix_ref_u, max_pix_ref_u, min_pix_ref_v, max_pix_ref_v, + calc, calc_allocsize, calc_bytewrap); + + buffer_in = rin->pixels(); + buffer_out = rout->pixels(); + lu = rin->getLx(); + lx = rout->getLx(); + lv = rin->getLy(); + ly = rout->getLy(); + wrap_in = rin->getWrap(); + wrap_out = rout->getWrap(); + mu = lu - 1; + mv = lv - 1; + + filter_mu = max_pix_ref_u - min_pix_ref_u; + filter_mv = max_pix_ref_v - min_pix_ref_v; + inside_limit_u = lu - filter_mu; + inside_limit_v = lv - filter_mv; + inside_nonempty = (int)inside_limit_u > 0 && (int)inside_limit_v > 0; + outside_min_u = -max_pix_ref_u; + outside_min_v = -max_pix_ref_v; + outside_max_u = mu - min_pix_ref_u; + outside_max_v = mv - min_pix_ref_v; + + for (out_y = 0, out_y_ = 0.5; out_y < ly; out_y++, out_y_ += 1.0) { + for (out_x = 0, out_x_ = 0.5; out_x < lx; out_x++, out_x_ += 1.0) { + pix_out = buffer_out + out_y * wrap_out + out_x; + + out_u_ = affMV1(aff_xy2uv, out_x_, out_y_); + out_v_ = affMV2(aff_xy2uv, out_x_, out_y_); + ref_u = intLE(out_u_); + ref_v = intLE(out_v_); + + if (inside_nonempty && (UINT)(ref_u + min_pix_ref_u) < inside_limit_u && + (UINT)(ref_v + min_pix_ref_v) < inside_limit_v) { + calc_value = calc[(ref_u >> 3) + ref_v * calc_bytewrap]; + + if (calc_value && ((calc_value >> (ref_u & 7)) & 1)) { + ref_out_u_ = ref_u - out_u_; + ref_out_v_ = ref_v - out_v_; + ref_out_f_ = aff0MV1(aff0_uv2fg, ref_out_u_, ref_out_v_); + ref_out_g_ = aff0MV2(aff0_uv2fg, ref_out_u_, ref_out_v_); + ref_out_f = tround(ref_out_f_); + ref_out_g = tround(ref_out_g_); + sum_weights = 0; + + sum_contribs_packed = _mm_setzero_ps(); + + for (i = n_pix - 1; i >= 0; i--) { + pix_out_f = pix_ref_f[i] + ref_out_f; + pix_out_g = pix_ref_g[i] + ref_out_g; + weight = (float)((filter[pix_out_f] * filter[pix_out_g]) >> 16); + pix_u = pix_ref_u[i] + ref_u; + pix_v = pix_ref_v[i] + ref_v; + + pix_value = buffer_in[pix_u + pix_v * wrap_in]; + pix_value_packed_i = _mm_unpacklo_epi8( + _mm_cvtsi32_si128(*(DWORD *)&pix_value), zeros); + pix_value_packed = + _mm_cvtepi32_ps(_mm_unpacklo_epi16(pix_value_packed_i, zeros)); + + weight_packed = _mm_load1_ps(&weight); + sum_contribs_packed = + _mm_add_ps(sum_contribs_packed, + _mm_mul_ps(pix_value_packed, weight_packed)); + + sum_weights += weight; + } + + inv_sum_weights = 1.0f / sum_weights; + __m128 inv_sum_weights_packed = _mm_load1_ps(&inv_sum_weights); + + __m128 out_fval_packed = + _mm_mul_ps(sum_contribs_packed, inv_sum_weights_packed); + out_fval_packed = _mm_max_ps(out_fval_packed, zeros2); + out_fval_packed = _mm_min_ps(out_fval_packed, maxChanneValue_packed); + + __m128i out_value_packed_i = _mm_cvtps_epi32(out_fval_packed); + out_value_packed_i = _mm_packs_epi32(out_value_packed_i, zeros); + out_value_packed_i = _mm_packus_epi16(out_value_packed_i, zeros); + *(DWORD *)(pix_out) = _mm_cvtsi128_si32(out_value_packed_i); + } else + *pix_out = buffer_in[ref_u + ref_v * wrap_in]; + } else + // if( outside_min_u_ <= out_u_ && out_u_ <= outside_max_u_ && + // outside_min_v_ <= out_v_ && out_v_ <= outside_max_v_ ) + if (outside_min_u <= ref_u && ref_u <= outside_max_u && + outside_min_v <= ref_v && ref_v <= outside_max_v) { + if ((UINT)ref_u >= (UINT)lu || (UINT)ref_v >= (UINT)lv) + must_calc = true; + else { + calc_value = calc[(ref_u >> 3) + ref_v * calc_bytewrap]; + must_calc = calc_value && ((calc_value >> (ref_u & 7)) & 1); + } + + if (must_calc) { + ref_out_u_ = ref_u - out_u_; + ref_out_v_ = ref_v - out_v_; + ref_out_f_ = aff0MV1(aff0_uv2fg, ref_out_u_, ref_out_v_); + ref_out_g_ = aff0MV2(aff0_uv2fg, ref_out_u_, ref_out_v_); + ref_out_f = tround(ref_out_f_); + ref_out_g = tround(ref_out_g_); + sum_weights = 0; + sum_contribs_packed = _mm_setzero_ps(); + + for (i = n_pix - 1; i >= 0; i--) { + pix_out_f = pix_ref_f[i] + ref_out_f; + pix_out_g = pix_ref_g[i] + ref_out_g; + weight = (float)((filter[pix_out_f] * filter[pix_out_g]) >> 16); + pix_u = pix_ref_u[i] + ref_u; + pix_v = pix_ref_v[i] + ref_v; + + if (pix_u < 0 || pix_u > mu || pix_v < 0 || pix_v > mv) { + sum_weights += weight; + continue; + } + + notLessThan(0, pix_u); + notLessThan(0, pix_v); + notMoreThan(mu, pix_u); + notMoreThan(mv, pix_v); + + pix_value = buffer_in[pix_u + pix_v * wrap_in]; + pix_value_packed_i = _mm_unpacklo_epi8( + _mm_cvtsi32_si128(*(DWORD *)&pix_value), zeros); + pix_value_packed = + _mm_cvtepi32_ps(_mm_unpacklo_epi16(pix_value_packed_i, zeros)); + + weight_packed = _mm_load1_ps(&weight); + sum_contribs_packed = + _mm_add_ps(sum_contribs_packed, + _mm_mul_ps(pix_value_packed, weight_packed)); + + sum_weights += weight; + } + inv_sum_weights = 1.0f / sum_weights; + + __m128 inv_sum_weights_packed = _mm_load1_ps(&inv_sum_weights); + __m128 out_fval_packed = + _mm_mul_ps(sum_contribs_packed, inv_sum_weights_packed); + out_fval_packed = _mm_max_ps(out_fval_packed, zeros2); + out_fval_packed = _mm_min_ps(out_fval_packed, maxChanneValue_packed); + + __m128i out_value_packed_i = _mm_cvtps_epi32(out_fval_packed); + out_value_packed_i = _mm_packs_epi32(out_value_packed_i, zeros); + out_value_packed_i = _mm_packus_epi16(out_value_packed_i, zeros); + *(DWORD *)(pix_out) = _mm_cvtsi128_si32(out_value_packed_i); + } else + *pix_out = buffer_in[ref_u + ref_v * wrap_in]; + } else { + *pix_out = default_value; + } + } + } + if (calc) delete[] calc; } -namespace -{ +namespace { //--------------------------------------------------------------------------- -void inline blendBySSE2(TPixel32 *pix_out, - float *ink, float *paint, float *tone, - const __m128 &maxtone_packed, - const __m128i &zeros) -{ - __m128 a_packed = _mm_load_ps(ink); - __m128 b_packed = _mm_load_ps(paint); +void inline blendBySSE2(TPixel32 *pix_out, float *ink, float *paint, + float *tone, const __m128 &maxtone_packed, + const __m128i &zeros) { + __m128 a_packed = _mm_load_ps(ink); + __m128 b_packed = _mm_load_ps(paint); - __m128 num_packed = _mm_load1_ps(tone); - __m128 diff_packed = _mm_sub_ps(maxtone_packed, num_packed); + __m128 num_packed = _mm_load1_ps(tone); + __m128 diff_packed = _mm_sub_ps(maxtone_packed, num_packed); - // calcola in modo vettoriale out = ((den-num)*a + num*b)/den - __m128 pix_value_packed = _mm_mul_ps(diff_packed, a_packed); - __m128 tmpPix_packed = _mm_mul_ps(num_packed, b_packed); + // calcola in modo vettoriale out = ((den-num)*a + num*b)/den + __m128 pix_value_packed = _mm_mul_ps(diff_packed, a_packed); + __m128 tmpPix_packed = _mm_mul_ps(num_packed, b_packed); - pix_value_packed = _mm_add_ps(pix_value_packed, tmpPix_packed); - pix_value_packed = _mm_div_ps(pix_value_packed, maxtone_packed); + pix_value_packed = _mm_add_ps(pix_value_packed, tmpPix_packed); + pix_value_packed = _mm_div_ps(pix_value_packed, maxtone_packed); - // converte i canali da float a char - __m128i pix_value_packed_i = _mm_cvtps_epi32(pix_value_packed); - pix_value_packed_i = _mm_packs_epi32(pix_value_packed_i, zeros); - pix_value_packed_i = _mm_packus_epi16(pix_value_packed_i, zeros); + // converte i canali da float a char + __m128i pix_value_packed_i = _mm_cvtps_epi32(pix_value_packed); + pix_value_packed_i = _mm_packs_epi32(pix_value_packed_i, zeros); + pix_value_packed_i = _mm_packus_epi16(pix_value_packed_i, zeros); - *(DWORD *)(pix_out) = _mm_cvtsi128_si32(pix_value_packed_i); + *(DWORD *)(pix_out) = _mm_cvtsi128_si32(pix_value_packed_i); } //--------------------------------------------------------------------------- -void inline blendBySSE2(__m128 &pix_out_packed, - float *ink, float *paint, float *tone, - const __m128 &maxtone_packed, - const __m128i &zeros) -{ - __m128 a_packed = _mm_load_ps(ink); - __m128 b_packed = _mm_load_ps(paint); +void inline blendBySSE2(__m128 &pix_out_packed, float *ink, float *paint, + float *tone, const __m128 &maxtone_packed, + const __m128i &zeros) { + __m128 a_packed = _mm_load_ps(ink); + __m128 b_packed = _mm_load_ps(paint); - __m128 num_packed = _mm_load1_ps(tone); - __m128 diff_packed = _mm_sub_ps(maxtone_packed, num_packed); + __m128 num_packed = _mm_load1_ps(tone); + __m128 diff_packed = _mm_sub_ps(maxtone_packed, num_packed); - // calcola in modo vettoriale out = ((den-num)*a + num*b)/den - pix_out_packed = _mm_mul_ps(diff_packed, a_packed); - __m128 tmpPix_packed = _mm_mul_ps(num_packed, b_packed); + // calcola in modo vettoriale out = ((den-num)*a + num*b)/den + pix_out_packed = _mm_mul_ps(diff_packed, a_packed); + __m128 tmpPix_packed = _mm_mul_ps(num_packed, b_packed); - pix_out_packed = _mm_add_ps(pix_out_packed, tmpPix_packed); - pix_out_packed = _mm_div_ps(pix_out_packed, maxtone_packed); + pix_out_packed = _mm_add_ps(pix_out_packed, tmpPix_packed); + pix_out_packed = _mm_div_ps(pix_out_packed, maxtone_packed); } -} // namespace +} // namespace -#endif // _WIN32 +#endif // _WIN32 //--------------------------------------------------------------------------- -static void get_prow_gr8(const TRasterGR8P &rin, - double a11, double a12, double a21, double a22, - int pmin, int pmax, int q, float *prow) -{ - UCHAR *bufin_gr8, *in_gr8; - int u, v; - int p, p1, p2; - UINT lu, lv; - UINT mu, mv; - int du, dv; - double u_0, v_0; - double u_, v_; - double fu, fv; - double gu, gv; +static void get_prow_gr8(const TRasterGR8P &rin, double a11, double a12, + double a21, double a22, int pmin, int pmax, int q, + float *prow) { + UCHAR *bufin_gr8, *in_gr8; + int u, v; + int p, p1, p2; + UINT lu, lv; + UINT mu, mv; + int du, dv; + double u_0, v_0; + double u_, v_; + double fu, fv; + double gu, gv; #ifdef USE_DOUBLE_TO_INT - double d2iaux; + double d2iaux; #endif #ifdef BORDER @@ -1730,91 +1662,99 @@ static void get_prow_gr8(const TRasterGR8P &rin, #endif #define BORDER BORDER_GR8 - bufin_gr8 = (UCHAR *)rin->pixels(); - lu = rin->getLx(); - mu = lu - 1; - lv = rin->getLy(); - mv = lv - 1; - du = 1; - dv = rin->getWrap(); - u_0 = a12 * q; - v_0 = a22 * q; - - for (p = pmin; p <= pmax; p++) - if (!prow[p]) { - u_ = u_0 + a11 * p; - u = tfloor(u_); - v_ = v_0 + a21 * p; - v = tfloor(v_); - if ((UINT)u < mu && (UINT)v < mv) - break; - fu = u_ - u; - gu = 1. - fu; - fv = v_ - v; - gv = 1. - fv; - in_gr8 = bufin_gr8 + (u * du + v * dv); - prow[p] = (float)troundp(fu * gv * (((UINT)(u + 1) < lu && (UINT)v < lv) ? in_gr8[du] : BORDER) + - fu * fv * (((UINT)(u + 1) < lu && (UINT)(v + 1) < lv) ? in_gr8[du + dv] : BORDER) + - gu * gv * (((UINT)u < lu && (UINT)v < lv) ? in_gr8[0] : BORDER) + - gu * fv * (((UINT)u < lu && (UINT)(v + 1) < lv) ? in_gr8[dv] : BORDER)); - } - p1 = p; - for (p = pmax; p > p1; p--) - if (!prow[p]) { - u_ = u_0 + a11 * p; - u = tfloor(u_); - v_ = v_0 + a21 * p; - v = tfloor(v_); - if ((UINT)u < mu && (UINT)v < mv) - break; - fu = u_ - u; - gu = 1. - fu; - fv = v_ - v; - gv = 1. - fv; - in_gr8 = bufin_gr8 + (u * du + v * dv); - prow[p] = (float)troundp(fu * gv * (((UINT)(u + 1) < lu && (UINT)v < lv) ? in_gr8[du] : BORDER) + - fu * fv * (((UINT)(u + 1) < lu && (UINT)(v + 1) < lv) ? in_gr8[du + dv] : BORDER) + - gu * gv * (((UINT)u < lu && (UINT)v < lv) ? in_gr8[0] : BORDER) + - gu * fv * (((UINT)u < lu && (UINT)(v + 1) < lv) ? in_gr8[dv] : BORDER)); - } - p2 = p; - for (p = p1; p <= p2; p++) - if (!prow[p]) { - u_ = u_0 + a11 * p; - u = (int)(u_); - v_ = v_0 + a21 * p; - v = (int)(v_); - fu = u_ - u; - gu = 1. - fu; - fv = v_ - v; - gv = 1. - fv; - in_gr8 = bufin_gr8 + (u * du + v * dv); - prow[p] = (float)troundp(fu * gv * in_gr8[du] + fu * fv * in_gr8[du + dv] + - gu * gv * in_gr8[0] + gu * fv * in_gr8[dv]); - } + bufin_gr8 = (UCHAR *)rin->pixels(); + lu = rin->getLx(); + mu = lu - 1; + lv = rin->getLy(); + mv = lv - 1; + du = 1; + dv = rin->getWrap(); + u_0 = a12 * q; + v_0 = a22 * q; + + for (p = pmin; p <= pmax; p++) + if (!prow[p]) { + u_ = u_0 + a11 * p; + u = tfloor(u_); + v_ = v_0 + a21 * p; + v = tfloor(v_); + if ((UINT)u < mu && (UINT)v < mv) break; + fu = u_ - u; + gu = 1. - fu; + fv = v_ - v; + gv = 1. - fv; + in_gr8 = bufin_gr8 + (u * du + v * dv); + prow[p] = (float)troundp( + fu * gv * + (((UINT)(u + 1) < lu && (UINT)v < lv) ? in_gr8[du] : BORDER) + + fu * fv * (((UINT)(u + 1) < lu && (UINT)(v + 1) < lv) + ? in_gr8[du + dv] + : BORDER) + + gu * gv * (((UINT)u < lu && (UINT)v < lv) ? in_gr8[0] : BORDER) + + gu * fv * + (((UINT)u < lu && (UINT)(v + 1) < lv) ? in_gr8[dv] : BORDER)); + } + p1 = p; + for (p = pmax; p > p1; p--) + if (!prow[p]) { + u_ = u_0 + a11 * p; + u = tfloor(u_); + v_ = v_0 + a21 * p; + v = tfloor(v_); + if ((UINT)u < mu && (UINT)v < mv) break; + fu = u_ - u; + gu = 1. - fu; + fv = v_ - v; + gv = 1. - fv; + in_gr8 = bufin_gr8 + (u * du + v * dv); + prow[p] = (float)troundp( + fu * gv * + (((UINT)(u + 1) < lu && (UINT)v < lv) ? in_gr8[du] : BORDER) + + fu * fv * (((UINT)(u + 1) < lu && (UINT)(v + 1) < lv) + ? in_gr8[du + dv] + : BORDER) + + gu * gv * (((UINT)u < lu && (UINT)v < lv) ? in_gr8[0] : BORDER) + + gu * fv * + (((UINT)u < lu && (UINT)(v + 1) < lv) ? in_gr8[dv] : BORDER)); + } + p2 = p; + for (p = p1; p <= p2; p++) + if (!prow[p]) { + u_ = u_0 + a11 * p; + u = (int)(u_); + v_ = v_0 + a21 * p; + v = (int)(v_); + fu = u_ - u; + gu = 1. - fu; + fv = v_ - v; + gv = 1. - fv; + in_gr8 = bufin_gr8 + (u * du + v * dv); + prow[p] = + (float)troundp(fu * gv * in_gr8[du] + fu * fv * in_gr8[du + dv] + + gu * gv * in_gr8[0] + gu * fv * in_gr8[dv]); + } } //--------------------------------------------------------------------------- #define grey(PIXEL) (TPixelGR8::from(PIXEL).value) -static void get_prow_gr8(const TRaster32P &rin, - double a11, double a12, double a21, double a22, - int pmin, int pmax, int q, float *prow) -{ - TPixel *bufin_32, *in_32; - int u, v; - int p, p1, p2; - UINT lu, lv; - UINT mu, mv; - int du, dv; - double u_0, v_0; - double u_, v_; - double fu, fv; - double gu, gv; +static void get_prow_gr8(const TRaster32P &rin, double a11, double a12, + double a21, double a22, int pmin, int pmax, int q, + float *prow) { + TPixel *bufin_32, *in_32; + int u, v; + int p, p1, p2; + UINT lu, lv; + UINT mu, mv; + int du, dv; + double u_0, v_0; + double u_, v_; + double fu, fv; + double gu, gv; #ifdef USE_DOUBLE_TO_INT - double d2iaux; + double d2iaux; #endif #ifdef BORDER @@ -1822,496 +1762,494 @@ static void get_prow_gr8(const TRaster32P &rin, #endif #define BORDER BORDER_GR8 - bufin_32 = (TPixel *)rin->pixels(); - lu = rin->getLx(); - mu = lu - 1; - lv = rin->getLy(); - mv = lv - 1; - du = 1; - dv = rin->getWrap(); - u_0 = a12 * q; - v_0 = a22 * q; - - for (p = pmin; p <= pmax; p++) - if (!prow[p]) { - u_ = u_0 + a11 * p; - u = tfloor(u_); - v_ = v_0 + a21 * p; - v = tfloor(v_); - if ((UINT)u < mu && (UINT)v < mv) - break; - fu = u_ - u; - gu = 1. - fu; - fv = v_ - v; - gv = 1. - fv; - in_32 = bufin_32 + (u * du + v * dv); - prow[p] = (float)troundp(fu * gv * (((UINT)(u + 1) < lu && (UINT)v < lv) ? grey(in_32[du]) : BORDER) + - fu * fv * (((UINT)(u + 1) < lu && (UINT)(v + 1) < lv) ? grey(in_32[du + dv]) : BORDER) + - gu * gv * (((UINT)u < lu && (UINT)v < lv) ? grey(in_32[0]) : BORDER) + - gu * fv * (((UINT)u < lu && (UINT)(v + 1) < lv) ? grey(in_32[dv]) : BORDER)); - } - p1 = p; - for (p = pmax; p > p1; p--) - if (!prow[p]) { - u_ = u_0 + a11 * p; - u = tfloor(u_); - v_ = v_0 + a21 * p; - v = tfloor(v_); - if ((UINT)u < mu && (UINT)v < mv) - break; - fu = u_ - u; - gu = 1. - fu; - fv = v_ - v; - gv = 1. - fv; - in_32 = bufin_32 + (u * du + v * dv); - prow[p] = (float)troundp(fu * gv * (((UINT)(u + 1) < lu && (UINT)v < lv) ? grey(in_32[du]) : BORDER) + - fu * fv * (((UINT)(u + 1) < lu && (UINT)(v + 1) < lv) ? grey(in_32[du + dv]) : BORDER) + - gu * gv * (((UINT)u < lu && (UINT)v < lv) ? grey(in_32[0]) : BORDER) + - gu * fv * (((UINT)u < lu && (UINT)(v + 1) < lv) ? grey(in_32[dv]) : BORDER)); - } - p2 = p; - for (p = p1; p <= p2; p++) - if (!prow[p]) { - u_ = u_0 + a11 * p; - u = (int)(u_); - v_ = v_0 + a21 * p; - v = (int)(v_); - fu = u_ - u; - gu = 1. - fu; - fv = v_ - v; - gv = 1. - fv; - in_32 = bufin_32 + (u * du + v * dv); - prow[p] = (float)troundp(fu * gv * grey(in_32[du]) + fu * fv * grey(in_32[du + dv]) + - gu * gv * grey(in_32[0]) + gu * fv * grey(in_32[dv])); - } + bufin_32 = (TPixel *)rin->pixels(); + lu = rin->getLx(); + mu = lu - 1; + lv = rin->getLy(); + mv = lv - 1; + du = 1; + dv = rin->getWrap(); + u_0 = a12 * q; + v_0 = a22 * q; + + for (p = pmin; p <= pmax; p++) + if (!prow[p]) { + u_ = u_0 + a11 * p; + u = tfloor(u_); + v_ = v_0 + a21 * p; + v = tfloor(v_); + if ((UINT)u < mu && (UINT)v < mv) break; + fu = u_ - u; + gu = 1. - fu; + fv = v_ - v; + gv = 1. - fv; + in_32 = bufin_32 + (u * du + v * dv); + prow[p] = (float)troundp( + fu * gv * (((UINT)(u + 1) < lu && (UINT)v < lv) ? grey(in_32[du]) + : BORDER) + + fu * fv * (((UINT)(u + 1) < lu && (UINT)(v + 1) < lv) + ? grey(in_32[du + dv]) + : BORDER) + + gu * gv * (((UINT)u < lu && (UINT)v < lv) ? grey(in_32[0]) : BORDER) + + gu * fv * (((UINT)u < lu && (UINT)(v + 1) < lv) ? grey(in_32[dv]) + : BORDER)); + } + p1 = p; + for (p = pmax; p > p1; p--) + if (!prow[p]) { + u_ = u_0 + a11 * p; + u = tfloor(u_); + v_ = v_0 + a21 * p; + v = tfloor(v_); + if ((UINT)u < mu && (UINT)v < mv) break; + fu = u_ - u; + gu = 1. - fu; + fv = v_ - v; + gv = 1. - fv; + in_32 = bufin_32 + (u * du + v * dv); + prow[p] = (float)troundp( + fu * gv * (((UINT)(u + 1) < lu && (UINT)v < lv) ? grey(in_32[du]) + : BORDER) + + fu * fv * (((UINT)(u + 1) < lu && (UINT)(v + 1) < lv) + ? grey(in_32[du + dv]) + : BORDER) + + gu * gv * (((UINT)u < lu && (UINT)v < lv) ? grey(in_32[0]) : BORDER) + + gu * fv * (((UINT)u < lu && (UINT)(v + 1) < lv) ? grey(in_32[dv]) + : BORDER)); + } + p2 = p; + for (p = p1; p <= p2; p++) + if (!prow[p]) { + u_ = u_0 + a11 * p; + u = (int)(u_); + v_ = v_0 + a21 * p; + v = (int)(v_); + fu = u_ - u; + gu = 1. - fu; + fv = v_ - v; + gv = 1. - fv; + in_32 = bufin_32 + (u * du + v * dv); + prow[p] = (float)troundp( + fu * gv * grey(in_32[du]) + fu * fv * grey(in_32[du + dv]) + + gu * gv * grey(in_32[0]) + gu * fv * grey(in_32[dv])); + } } //--------------------------------------------------------------------------- typedef float *MyFloatPtr; static void rop_resample_gr8(const TRasterGR8P &rin, TRasterGR8P rout, - const TAffine &aff, const TAffine &invrot, - FILTER *rowflt, int pmin, int pmax, - FILTER *colflt, int qmin, int qmax, int nrows, - int flatradu, int flatradv, - double flatradx_, double flatrady_, - NOCALC *rownoc, int nocdiamx, - NOCALC *colnoc, int nocdiamy) -{ - - FILTER *xflt, *yflt; - UCHAR *bufin_gr8, *bufout_gr8, *in_gr8, *out_gr8; - float *prow_base, *prow, **xrow_base, **xrow, *xxx, tmp; - double x_, y_; - int u, v; //, vw; - int p, q; - int x, y; - int lu, lv, mu, mv; - int lx, ly, mx, my; - //int dudp, dudq, dvdp, dvdq; - int topq, topy; - int wrapin, wrapout; - int flatdiamu, flatdiamv; - int xlo, xhi, ylo, yhi; - int *nocheight; - int nocwidth; - int i, j; + const TAffine &aff, const TAffine &invrot, + FILTER *rowflt, int pmin, int pmax, FILTER *colflt, + int qmin, int qmax, int nrows, int flatradu, + int flatradv, double flatradx_, double flatrady_, + NOCALC *rownoc, int nocdiamx, NOCALC *colnoc, + int nocdiamy) { + FILTER *xflt, *yflt; + UCHAR *bufin_gr8, *bufout_gr8, *in_gr8, *out_gr8; + float *prow_base, *prow, **xrow_base, **xrow, *xxx, tmp; + double x_, y_; + int u, v; //, vw; + int p, q; + int x, y; + int lu, lv, mu, mv; + int lx, ly, mx, my; + // int dudp, dudq, dvdp, dvdq; + int topq, topy; + int wrapin, wrapout; + int flatdiamu, flatdiamv; + int xlo, xhi, ylo, yhi; + int *nocheight; + int nocwidth; + int i, j; #ifdef USE_DOUBLE_TO_INT - double d2iaux; + double d2iaux; #endif - bufin_gr8 = (UCHAR *)rin->pixels(); - bufout_gr8 = (UCHAR *)rout->pixels(); - wrapin = rin->getWrap(); - wrapout = rout->getWrap(); - - lu = rin->getLx(); - mu = lu - 1; - lv = rin->getLy(); - mv = lv - 1; - lx = rout->getLx(); - mx = lx - 1; - ly = rout->getLy(); - my = ly - 1; - prow_base = new float[pmax - pmin + 1]; - prow = prow_base - pmin; - xrow_base = new MyFloatPtr[qmax - (qmin - nrows) + 1]; - xrow = xrow_base - (qmin - nrows); - topq = qmin; - - //app = xrow+topq-nrows; - i = 0; - j = 3; - - for (i = 0; i < nrows; i++) - *(xrow + topq - nrows + i) = new float[lx]; - - //while(app= flatdiamv) - if (colval[u] == flatval) - flatcols++; - else - flatcols = 1; - else - flatcols = 0; - flatval = colval[u]; - if (flatcols >= flatdiamu) { + bufin_gr8 = (UCHAR *)rin->pixels(); + bufout_gr8 = (UCHAR *)rout->pixels(); + wrapin = rin->getWrap(); + wrapout = rout->getWrap(); + + lu = rin->getLx(); + mu = lu - 1; + lv = rin->getLy(); + mv = lv - 1; + lx = rout->getLx(); + mx = lx - 1; + ly = rout->getLy(); + my = ly - 1; + prow_base = new float[pmax - pmin + 1]; + prow = prow_base - pmin; + xrow_base = new MyFloatPtr[qmax - (qmin - nrows) + 1]; + xrow = xrow_base - (qmin - nrows); + topq = qmin; + + // app = xrow+topq-nrows; + i = 0; + j = 3; + + for (i = 0; i < nrows; i++) *(xrow + topq - nrows + i) = new float[lx]; + + // while(app= flatdiamv) + if (colval[u] == flatval) + flatcols++; + else + flatcols = 1; + else + flatcols = 0; + flatval = colval[u]; + if (flatcols >= flatdiamu) { #ifdef VECCHIA_MANIERA - x_ = AFF_M_V_1(aff, u - flatradu, v - flatradv); - y_ = AFF_M_V_2(aff, u - flatradu, v - flatradv); - xlo = CEIL(x_ - flatradx_); - xhi = FLOOR(x_ + flatradx_); - ylo = CEIL(y_ - flatrady_); - yhi = FLOOR(y_ + flatrady_); - NOT_LESS_THAN(0, xlo); - NOT_MORE_THAN(mx, xhi); - NOT_LESS_THAN(0, ylo); - NOT_MORE_THAN(my, yhi); + x_ = AFF_M_V_1(aff, u - flatradu, v - flatradv); + y_ = AFF_M_V_2(aff, u - flatradu, v - flatradv); + xlo = CEIL(x_ - flatradx_); + xhi = FLOOR(x_ + flatradx_); + ylo = CEIL(y_ - flatrady_); + yhi = FLOOR(y_ + flatrady_); + NOT_LESS_THAN(0, xlo); + NOT_MORE_THAN(mx, xhi); + NOT_LESS_THAN(0, ylo); + NOT_MORE_THAN(my, yhi); #endif - xlo = std::max(0, (int)xlo_); - xhi = std::min(mx, (int)xhi_); - ylo = std::max(0, (int)ylo_); - yhi = std::min(my, (int)yhi_); - for (y = ylo; y <= yhi; y++) - for (x = xlo; x <= xhi; x++) - bufout_gr8[x + y * wrapout] = flatval, count++; - } - xlo_ += aff.a11; - xhi_ += aff.a11; - ylo_ += aff.a21; - yhi_ += aff.a21; - } - } - delete colval; - delete colheight; - - topy = 0; - /*TCALLOC (nocheight, lx);*/ - nocheight = new int[lx]; - memset(nocheight, 0, lx * sizeof(int)); - out_gr8 = bufout_gr8; - for (x = 0; x < lx; x++) - if (out_gr8[x] != GREY_GR8) - nocheight[x]++; - else - nocheight[x] = 0; - - for (y = 0, yflt = colflt; y < ly; y++, yflt++) { - for (; topq <= yflt->last; topq++) { - xrow[topq] = xrow[topq - nrows]; - xxx = xrow[topq]; - memset(xxx, 0, sizeof(*xxx) * lx); /* 0.0 == nocalc */ - while (topy < ly - 1 && colnoc[topy].last < topq) { - topy++; - out_gr8 = bufout_gr8 + topy * wrapout; - for (x = 0; x < lx; x++) - if (out_gr8[x] != GREY_GR8) - nocheight[x]++; - else - nocheight[x] = 0; - } - if (topy < ly && colnoc[topy].first <= topq) { - for (x = 0; x < lx; x++) - if (nocheight[x] < nocdiamy) - xxx[x] = 1.0; /* 1.0 == calc */ - } else { - for (x = 0; x < lx; x++) - xxx[x] = 1.0; /* 1.0 == calc */ - } - - memset(prow + pmin, 0, sizeof(*prow) * (pmax - pmin + 1)); /* 0.0 == calc */ - nocwidth = 0; - for (x = 0; x < lx; x++) - if (xxx[x]) - nocwidth = 0; - else { - nocwidth++; - if (nocwidth >= nocdiamx) - for (p = rownoc[x].first; p <= rownoc[x].last; p++) - prow[p] = 1.0; /* 1.0 == nocalc */ - } - get_prow_gr8(rin, invrot.a11, invrot.a12, invrot.a21, invrot.a22, - pmin, pmax, topq, prow); - for (x = 0, xflt = rowflt; x < lx; x++, xflt++) - if (xxx[x]) { - for (tmp = 0.0, p = xflt->first; p <= xflt->last; p++) - tmp += xflt->w[p] * prow[p]; - xxx[x] = tmp; - } - } - out_gr8 = bufout_gr8 + wrapout * y; - for (x = 0; x < lx; x++) - if (out_gr8[x] == GREY_GR8) { - for (tmp = 0.0, q = yflt->first; q <= yflt->last; q++) - tmp += yflt->w[q] * xrow[q][x]; - out_gr8[x] = TO8BIT(tmp); - } - } - //cest_plus_facile (xrow); - - for (q = 0; q < nrows; q++) - delete xrow_base[q]; - delete xrow_base; - delete prow_base; + xlo = std::max(0, (int)xlo_); + xhi = std::min(mx, (int)xhi_); + ylo = std::max(0, (int)ylo_); + yhi = std::min(my, (int)yhi_); + for (y = ylo; y <= yhi; y++) + for (x = xlo; x <= xhi; x++) + bufout_gr8[x + y * wrapout] = flatval, count++; + } + xlo_ += aff.a11; + xhi_ += aff.a11; + ylo_ += aff.a21; + yhi_ += aff.a21; + } + } + delete colval; + delete colheight; + + topy = 0; + /*TCALLOC (nocheight, lx);*/ + nocheight = new int[lx]; + memset(nocheight, 0, lx * sizeof(int)); + out_gr8 = bufout_gr8; + for (x = 0; x < lx; x++) + if (out_gr8[x] != GREY_GR8) + nocheight[x]++; + else + nocheight[x] = 0; + + for (y = 0, yflt = colflt; y < ly; y++, yflt++) { + for (; topq <= yflt->last; topq++) { + xrow[topq] = xrow[topq - nrows]; + xxx = xrow[topq]; + memset(xxx, 0, sizeof(*xxx) * lx); /* 0.0 == nocalc */ + while (topy < ly - 1 && colnoc[topy].last < topq) { + topy++; + out_gr8 = bufout_gr8 + topy * wrapout; + for (x = 0; x < lx; x++) + if (out_gr8[x] != GREY_GR8) + nocheight[x]++; + else + nocheight[x] = 0; + } + if (topy < ly && colnoc[topy].first <= topq) { + for (x = 0; x < lx; x++) + if (nocheight[x] < nocdiamy) xxx[x] = 1.0; /* 1.0 == calc */ + } else { + for (x = 0; x < lx; x++) xxx[x] = 1.0; /* 1.0 == calc */ + } + + memset(prow + pmin, 0, + sizeof(*prow) * (pmax - pmin + 1)); /* 0.0 == calc */ + nocwidth = 0; + for (x = 0; x < lx; x++) + if (xxx[x]) + nocwidth = 0; + else { + nocwidth++; + if (nocwidth >= nocdiamx) + for (p = rownoc[x].first; p <= rownoc[x].last; p++) + prow[p] = 1.0; /* 1.0 == nocalc */ + } + get_prow_gr8(rin, invrot.a11, invrot.a12, invrot.a21, invrot.a22, pmin, + pmax, topq, prow); + for (x = 0, xflt = rowflt; x < lx; x++, xflt++) + if (xxx[x]) { + for (tmp = 0.0, p = xflt->first; p <= xflt->last; p++) + tmp += xflt->w[p] * prow[p]; + xxx[x] = tmp; + } + } + out_gr8 = bufout_gr8 + wrapout * y; + for (x = 0; x < lx; x++) + if (out_gr8[x] == GREY_GR8) { + for (tmp = 0.0, q = yflt->first; q <= yflt->last; q++) + tmp += yflt->w[q] * xrow[q][x]; + out_gr8[x] = TO8BIT(tmp); + } + } + // cest_plus_facile (xrow); + + for (q = 0; q < nrows; q++) delete xrow_base[q]; + delete xrow_base; + delete prow_base; } //--------------------------------------------------------------------------- static void rop_resample_rgbm32_gr8(const TRaster32P &rin, TRasterGR8P rout, - const TAffine &aff, const TAffine &invrot, - FILTER *rowflt, int pmin, int pmax, - FILTER *colflt, int qmin, int qmax, int nrows, - int flatradu, int flatradv, - double flatradx_, double flatrady_, - NOCALC *rownoc, int nocdiamx, - NOCALC *colnoc, int nocdiamy) -{ - - FILTER *xflt, *yflt; - UCHAR *bufout_gr8, *out_gr8; - TPixel *bufin_32, *in_32; - float *prow_base, *prow, **xrow_base, **xrow, *xxx, tmp; - double x_, y_; - int u, v; //, vw; - int p, q; - int x, y; - int lu, lv, mu, mv; - int lx, ly, mx, my; - //int dudp, dudq, dvdp, dvdq; - int topq, topy; - int wrapin, wrapout; - int flatdiamu, flatdiamv; - int xlo, xhi, ylo, yhi; - int *nocheight; - int nocwidth; - int i, j; + const TAffine &aff, const TAffine &invrot, + FILTER *rowflt, int pmin, int pmax, + FILTER *colflt, int qmin, int qmax, + int nrows, int flatradu, int flatradv, + double flatradx_, double flatrady_, + NOCALC *rownoc, int nocdiamx, + NOCALC *colnoc, int nocdiamy) { + FILTER *xflt, *yflt; + UCHAR *bufout_gr8, *out_gr8; + TPixel *bufin_32, *in_32; + float *prow_base, *prow, **xrow_base, **xrow, *xxx, tmp; + double x_, y_; + int u, v; //, vw; + int p, q; + int x, y; + int lu, lv, mu, mv; + int lx, ly, mx, my; + // int dudp, dudq, dvdp, dvdq; + int topq, topy; + int wrapin, wrapout; + int flatdiamu, flatdiamv; + int xlo, xhi, ylo, yhi; + int *nocheight; + int nocwidth; + int i, j; #ifdef USE_DOUBLE_TO_INT - double d2iaux; + double d2iaux; #endif - bufin_32 = (TPixel *)rin->pixels(); - bufout_gr8 = (UCHAR *)rout->pixels(); - wrapin = rin->getWrap(); - wrapout = rout->getWrap(); - - lu = rin->getLx(); - mu = lu - 1; - lv = rin->getLy(); - mv = lv - 1; - lx = rout->getLx(); - mx = lx - 1; - ly = rout->getLy(); - my = ly - 1; - prow_base = new float[pmax - pmin + 1]; - prow = prow_base - pmin; - xrow_base = new MyFloatPtr[qmax - (qmin - nrows) + 1]; - xrow = xrow_base - (qmin - nrows); - topq = qmin; - - //app = xrow+topq-nrows; - i = 0; - j = 3; - - for (i = 0; i < nrows; i++) - *(xrow + topq - nrows + i) = new float[lx]; - - //while(app= flatdiamv) - if (colval[u] == flatval) - flatcols++; - else - flatcols = 1; - else - flatcols = 0; - flatval = colval[u]; - if (flatcols >= flatdiamu) { + bufin_32 = (TPixel *)rin->pixels(); + bufout_gr8 = (UCHAR *)rout->pixels(); + wrapin = rin->getWrap(); + wrapout = rout->getWrap(); + + lu = rin->getLx(); + mu = lu - 1; + lv = rin->getLy(); + mv = lv - 1; + lx = rout->getLx(); + mx = lx - 1; + ly = rout->getLy(); + my = ly - 1; + prow_base = new float[pmax - pmin + 1]; + prow = prow_base - pmin; + xrow_base = new MyFloatPtr[qmax - (qmin - nrows) + 1]; + xrow = xrow_base - (qmin - nrows); + topq = qmin; + + // app = xrow+topq-nrows; + i = 0; + j = 3; + + for (i = 0; i < nrows; i++) *(xrow + topq - nrows + i) = new float[lx]; + + // while(app= flatdiamv) + if (colval[u] == flatval) + flatcols++; + else + flatcols = 1; + else + flatcols = 0; + flatval = colval[u]; + if (flatcols >= flatdiamu) { #ifdef VECCHIA_MANIERA - x_ = AFF_M_V_1(aff, u - flatradu, v - flatradv); - y_ = AFF_M_V_2(aff, u - flatradu, v - flatradv); - xlo = CEIL(x_ - flatradx_); - xhi = FLOOR(x_ + flatradx_); - ylo = CEIL(y_ - flatrady_); - yhi = FLOOR(y_ + flatrady_); - NOT_LESS_THAN(0, xlo); - NOT_MORE_THAN(mx, xhi); - NOT_LESS_THAN(0, ylo); - NOT_MORE_THAN(my, yhi); + x_ = AFF_M_V_1(aff, u - flatradu, v - flatradv); + y_ = AFF_M_V_2(aff, u - flatradu, v - flatradv); + xlo = CEIL(x_ - flatradx_); + xhi = FLOOR(x_ + flatradx_); + ylo = CEIL(y_ - flatrady_); + yhi = FLOOR(y_ + flatrady_); + NOT_LESS_THAN(0, xlo); + NOT_MORE_THAN(mx, xhi); + NOT_LESS_THAN(0, ylo); + NOT_MORE_THAN(my, yhi); #endif - xlo = std::max(0, (int)xlo_); - xhi = std::min(mx, (int)xhi_); - ylo = std::max(0, (int)ylo_); - yhi = std::min(my, (int)yhi_); - for (y = ylo; y <= yhi; y++) - for (x = xlo; x <= xhi; x++) - bufout_gr8[x + y * wrapout] = flatval, count++; - } - xlo_ += aff.a11; - xhi_ += aff.a11; - ylo_ += aff.a21; - yhi_ += aff.a21; - } - } - delete colval; - delete colheight; - - topy = 0; - /*TCALLOC (nocheight, lx);*/ - nocheight = new int[lx]; - memset(nocheight, 0, lx * sizeof(int)); - out_gr8 = bufout_gr8; - for (x = 0; x < lx; x++) - if (out_gr8[x] != GREY_GR8) - nocheight[x]++; - else - nocheight[x] = 0; - - for (y = 0, yflt = colflt; y < ly; y++, yflt++) { - for (; topq <= yflt->last; topq++) { - xrow[topq] = xrow[topq - nrows]; - xxx = xrow[topq]; - memset(xxx, 0, sizeof(*xxx) * lx); /* 0.0 == nocalc */ - while (topy < ly - 1 && colnoc[topy].last < topq) { - topy++; - out_gr8 = bufout_gr8 + topy * wrapout; - for (x = 0; x < lx; x++) - if (out_gr8[x] != GREY_GR8) - nocheight[x]++; - else - nocheight[x] = 0; - } - if (topy < ly && colnoc[topy].first <= topq) { - for (x = 0; x < lx; x++) - if (nocheight[x] < nocdiamy) - xxx[x] = 1.0; /* 1.0 == calc */ - } else { - for (x = 0; x < lx; x++) - xxx[x] = 1.0; /* 1.0 == calc */ - } - - memset(prow + pmin, 0, sizeof(*prow) * (pmax - pmin + 1)); /* 0.0 == calc */ - nocwidth = 0; - for (x = 0; x < lx; x++) - if (xxx[x]) - nocwidth = 0; - else { - nocwidth++; - if (nocwidth >= nocdiamx) - for (p = rownoc[x].first; p <= rownoc[x].last; p++) - prow[p] = 1.0; /* 1.0 == nocalc */ - } - get_prow_gr8(rin, invrot.a11, invrot.a12, invrot.a21, invrot.a22, - pmin, pmax, topq, prow); - for (x = 0, xflt = rowflt; x < lx; x++, xflt++) - if (xxx[x]) { - for (tmp = 0.0, p = xflt->first; p <= xflt->last; p++) - tmp += xflt->w[p] * prow[p]; - xxx[x] = tmp; - } - } - out_gr8 = bufout_gr8 + wrapout * y; - for (x = 0; x < lx; x++) - if (out_gr8[x] == GREY_GR8) { - for (tmp = 0.0, q = yflt->first; q <= yflt->last; q++) - tmp += yflt->w[q] * xrow[q][x]; - out_gr8[x] = TO8BIT(tmp); - } - } - //cest_plus_facile (xrow); - - for (q = 0; q < nrows; q++) - delete xrow_base[q]; - delete xrow_base; - delete prow_base; + xlo = std::max(0, (int)xlo_); + xhi = std::min(mx, (int)xhi_); + ylo = std::max(0, (int)ylo_); + yhi = std::min(my, (int)yhi_); + for (y = ylo; y <= yhi; y++) + for (x = xlo; x <= xhi; x++) + bufout_gr8[x + y * wrapout] = flatval, count++; + } + xlo_ += aff.a11; + xhi_ += aff.a11; + ylo_ += aff.a21; + yhi_ += aff.a21; + } + } + delete colval; + delete colheight; + + topy = 0; + /*TCALLOC (nocheight, lx);*/ + nocheight = new int[lx]; + memset(nocheight, 0, lx * sizeof(int)); + out_gr8 = bufout_gr8; + for (x = 0; x < lx; x++) + if (out_gr8[x] != GREY_GR8) + nocheight[x]++; + else + nocheight[x] = 0; + + for (y = 0, yflt = colflt; y < ly; y++, yflt++) { + for (; topq <= yflt->last; topq++) { + xrow[topq] = xrow[topq - nrows]; + xxx = xrow[topq]; + memset(xxx, 0, sizeof(*xxx) * lx); /* 0.0 == nocalc */ + while (topy < ly - 1 && colnoc[topy].last < topq) { + topy++; + out_gr8 = bufout_gr8 + topy * wrapout; + for (x = 0; x < lx; x++) + if (out_gr8[x] != GREY_GR8) + nocheight[x]++; + else + nocheight[x] = 0; + } + if (topy < ly && colnoc[topy].first <= topq) { + for (x = 0; x < lx; x++) + if (nocheight[x] < nocdiamy) xxx[x] = 1.0; /* 1.0 == calc */ + } else { + for (x = 0; x < lx; x++) xxx[x] = 1.0; /* 1.0 == calc */ + } + + memset(prow + pmin, 0, + sizeof(*prow) * (pmax - pmin + 1)); /* 0.0 == calc */ + nocwidth = 0; + for (x = 0; x < lx; x++) + if (xxx[x]) + nocwidth = 0; + else { + nocwidth++; + if (nocwidth >= nocdiamx) + for (p = rownoc[x].first; p <= rownoc[x].last; p++) + prow[p] = 1.0; /* 1.0 == nocalc */ + } + get_prow_gr8(rin, invrot.a11, invrot.a12, invrot.a21, invrot.a22, pmin, + pmax, topq, prow); + for (x = 0, xflt = rowflt; x < lx; x++, xflt++) + if (xxx[x]) { + for (tmp = 0.0, p = xflt->first; p <= xflt->last; p++) + tmp += xflt->w[p] * prow[p]; + xxx[x] = tmp; + } + } + out_gr8 = bufout_gr8 + wrapout * y; + for (x = 0; x < lx; x++) + if (out_gr8[x] == GREY_GR8) { + for (tmp = 0.0, q = yflt->first; q <= yflt->last; q++) + tmp += yflt->w[q] * xrow[q][x]; + out_gr8[x] = TO8BIT(tmp); + } + } + // cest_plus_facile (xrow); + + for (q = 0; q < nrows; q++) delete xrow_base[q]; + delete xrow_base; + delete prow_base; } //--------------------------------------------------------------------------- @@ -2322,638 +2260,620 @@ static void rop_resample_rgbm32_gr8(const TRaster32P &rin, TRasterGR8P rout, template void rop_resample_rgbm(TRasterPT rout, const TRasterPT &rin, - const TAffine &aff, TRop::ResampleFilterType flt_type, double blur) -{ + const TAffine &aff, TRop::ResampleFilterType flt_type, + double blur) { #define FILTER_RESOLUTION 1024 #define MAX_FILTER_VAL 32767 #ifdef USE_STATIC_VARS - static TRop::ResampleFilterType current_flt_type = TRop::None; - static std::unique_ptr filter_array; - static short *filter = 0; - static int min_filter_fg, max_filter_fg; - static int filter_array_size = 0; - static int n_pix = 0; - static std::unique_ptr pix_ref_u; - static std::unique_ptr pix_ref_v; - static std::unique_ptr pix_ref_f; - static std::unique_ptr pix_ref_g; - static int current_max_n_pix = 0; + static TRop::ResampleFilterType current_flt_type = TRop::None; + static std::unique_ptr filter_array; + static short *filter = 0; + static int min_filter_fg, max_filter_fg; + static int filter_array_size = 0; + static int n_pix = 0; + static std::unique_ptr pix_ref_u; + static std::unique_ptr pix_ref_v; + static std::unique_ptr pix_ref_f; + static std::unique_ptr pix_ref_g; + static int current_max_n_pix = 0; #else - std::unique_ptr filter_array; - short *filter = 0; - int min_filter_fg, max_filter_fg; - int filter_array_size = 0; - int n_pix = 0; - std::unique_ptr pix_ref_u; - std::unique_ptr pix_ref_v; - std::unique_ptr pix_ref_f; - std::unique_ptr pix_ref_g; - int current_max_n_pix = 0; + std::unique_ptr filter_array; + short *filter = 0; + int min_filter_fg, max_filter_fg; + int filter_array_size = 0; + int n_pix = 0; + std::unique_ptr pix_ref_u; + std::unique_ptr pix_ref_v; + std::unique_ptr pix_ref_f; + std::unique_ptr pix_ref_g; + int current_max_n_pix = 0; #endif - int filter_st_radius; - int filter_fg_radius; - int filter_size; - int f; - double s_; - double weight_; - int weight; - TAffine aff_uv2xy; - TAffine aff_xy2uv; - TAffine aff0_uv2xy; - TAffine aff0_xy2st; - TAffine aff0_uv2st; - TAffine aff0_st2fg; - TAffine aff0_uv2fg; - TAffine aff0_fg2uv; - double scale_x, scale_y; - double inv_blur; - int max_n_pix; - double min_pix_out_u_, min_pix_out_v_; - double max_pix_out_u_, max_pix_out_v_; - int min_pix_ref_u, min_pix_ref_v; - int max_pix_ref_u, max_pix_ref_v; - int cur_pix_ref_u, cur_pix_ref_v; - double cur_pix_ref_f_, cur_pix_ref_g_; - int cur_pix_ref_f, cur_pix_ref_g; - double min_ref_out_f_, min_ref_out_g_; - double max_ref_out_f_, max_ref_out_g_; - int min_ref_out_f, min_ref_out_g; - int max_ref_out_f, max_ref_out_g; - int min_pix_ref_f, min_pix_ref_g; - int max_pix_ref_f, max_pix_ref_g; - int min_pix_out_f, min_pix_out_g; - int max_pix_out_f, max_pix_out_g; - int min_pix_out_fg; - int max_pix_out_fg; + int filter_st_radius; + int filter_fg_radius; + int filter_size; + int f; + double s_; + double weight_; + int weight; + TAffine aff_uv2xy; + TAffine aff_xy2uv; + TAffine aff0_uv2xy; + TAffine aff0_xy2st; + TAffine aff0_uv2st; + TAffine aff0_st2fg; + TAffine aff0_uv2fg; + TAffine aff0_fg2uv; + double scale_x, scale_y; + double inv_blur; + int max_n_pix; + double min_pix_out_u_, min_pix_out_v_; + double max_pix_out_u_, max_pix_out_v_; + int min_pix_ref_u, min_pix_ref_v; + int max_pix_ref_u, max_pix_ref_v; + int cur_pix_ref_u, cur_pix_ref_v; + double cur_pix_ref_f_, cur_pix_ref_g_; + int cur_pix_ref_f, cur_pix_ref_g; + double min_ref_out_f_, min_ref_out_g_; + double max_ref_out_f_, max_ref_out_g_; + int min_ref_out_f, min_ref_out_g; + int max_ref_out_f, max_ref_out_g; + int min_pix_ref_f, min_pix_ref_g; + int max_pix_ref_f, max_pix_ref_g; + int min_pix_out_f, min_pix_out_g; + int max_pix_out_f, max_pix_out_g; + int min_pix_out_fg; + int max_pix_out_fg; #ifdef USE_DOUBLE_TO_INT - double d2iaux; + double d2iaux; #endif - assert(flt_type != TRop::None); - - //Retrieve the filter radius in the st and fx references - filter_st_radius = get_filter_radius(flt_type); - filter_fg_radius = filter_st_radius * FILTER_RESOLUTION; - - //Retrieve the transformation affines among the involved references - //NOTE: The 0.5 translation is needed in order to make the later - //resample_main procedures work with pixel centers. - aff_uv2xy = aff * TTranslation(0.5, 0.5); - aff0_uv2xy = aff_uv2xy.place(0.0, 0.0, 0.0, 0.0); - aff_xy2uv = aff_uv2xy.inv(); - - //Consider the norm of (1,0) and (0,1) images. - scale_x = sqrt(sq(aff_uv2xy.a11) + sq(aff_uv2xy.a12)); - scale_y = sqrt(sq(aff_uv2xy.a21) + sq(aff_uv2xy.a22)); - - //Inserting the following scale will make shrinks look smooth. - aff0_xy2st = TScale((scale_x > 1.0) ? 1.0 / scale_x : 1.0, - (scale_y > 1.0) ? 1.0 / scale_y : 1.0); - - if (blur > 1.0) //Consider the blur as a scale in the filter reference - { - inv_blur = 1.0 / blur; - aff0_xy2st = TScale(inv_blur, inv_blur) * aff0_xy2st; - } - - aff0_uv2st = aff0_xy2st * aff0_uv2xy; - aff0_st2fg = TScale(FILTER_RESOLUTION, FILTER_RESOLUTION); - aff0_uv2fg = aff0_st2fg * aff0_uv2st; - aff0_fg2uv = aff0_uv2fg.inv(); - - //Take the pre-image of the filter mask in uv coordinates. This is where - //input pixels will be taken to find an output one. - minmax(-filter_fg_radius, -filter_fg_radius, - filter_fg_radius, filter_fg_radius, - aff0_fg2uv, - min_pix_out_u_, min_pix_out_v_, - max_pix_out_u_, max_pix_out_v_); - - //Adjust them to integer coordinates. The intent here is that - //of isolating their fractionary part - furthermore, we'll take - //the *opposites* of fractionary parts (explained later). - //NOTE: We'll assume we want to include in the filter mask all - //*integer positions around a fractionary displacement of the origin*; - //so the approximations below are stricly necessary. - - min_pix_ref_u = intLE(min_pix_out_u_); - min_pix_ref_v = intLE(min_pix_out_v_); - max_pix_ref_u = intGE(max_pix_out_u_); - max_pix_ref_v = intGE(max_pix_out_v_); - - if (blur <= 1.0) { - //If the blur radius has sub-pixel width - if (aff_uv2xy.a12 == 0.0 && aff_uv2xy.a21 == 0.0) { - //And it's the sole scales case - if (aff_uv2xy.a11 == 1.0 && isInt(aff_uv2xy.a13 - 0.5)) { - //And the x mapping is bijective, then prevent any filtering. - min_pix_ref_u = 0; - max_pix_ref_u = 0; - } - if (aff_uv2xy.a22 == 1.0 && isInt(aff_uv2xy.a23 - 0.5)) { - //And the y mapping is bijective ... - min_pix_ref_v = 0; - max_pix_ref_v = 0; - } - } else if (aff_uv2xy.a11 == 0.0 && aff_uv2xy.a22 == 0.0) { - //The mirrored version of the one above - if (aff_uv2xy.a12 == 1.0 && isInt(aff_uv2xy.a13 - 0.5)) { - min_pix_ref_v = 0; - max_pix_ref_v = 0; - } - if (aff_uv2xy.a21 == 1.0 && isInt(aff_uv2xy.a23 - 0.5)) { - min_pix_ref_u = 0; - max_pix_ref_u = 0; - } - } - } - - //Take the number of pixels involved in the filter (uv reference) - max_n_pix = (max_pix_ref_u - min_pix_ref_u + 1) * - (max_pix_ref_v - min_pix_ref_v + 1); - - if (max_n_pix > current_max_n_pix) { - current_max_n_pix = max_n_pix; - pix_ref_u.reset(new int[current_max_n_pix]); - pix_ref_v.reset(new int[current_max_n_pix]); - pix_ref_f.reset(new int[current_max_n_pix]); - pix_ref_g.reset(new int[current_max_n_pix]); - assert(pix_ref_u && pix_ref_v && pix_ref_f && pix_ref_g); - } - - //Build the image of fractionary domain from the uv to fg reference - minmax(-1, -1, 0, 0, - aff0_uv2fg, - min_ref_out_f_, min_ref_out_g_, - max_ref_out_f_, max_ref_out_g_); - - min_ref_out_f = tround(min_ref_out_f_); - min_ref_out_g = tround(min_ref_out_g_); - max_ref_out_f = tround(max_ref_out_f_); - max_ref_out_g = tround(max_ref_out_g_); - - //Remember that negative fractionary parts must be subtracted from their integer counterparts - min_pix_ref_f = -filter_fg_radius - max_ref_out_f; - min_pix_ref_g = -filter_fg_radius - max_ref_out_g; - max_pix_ref_f = filter_fg_radius - min_ref_out_f; - max_pix_ref_g = filter_fg_radius - min_ref_out_g; - - min_pix_out_f = c_maxint; - min_pix_out_g = c_maxint; - max_pix_out_f = c_minint; - max_pix_out_g = c_minint; - n_pix = 0; - - if (!pix_ref_u || !pix_ref_v || !pix_ref_f || !pix_ref_g) { - throw TRopException("tresample.cpp line2640 function rop_resample_rgbm() : alloc pix_ref failed"); - } - - //Build the *integer* part of the fg images of those coordinates inside the uv filter bounds. - - //NOTE: Doing so reduces the execution time for the later resample_main procedure - - //the idea is the following: - // We want to build the output pixel (x,y) obtained from the source image through A. - // Then, we find (u,v) = (A^-1) * (x,y) = ([u],[v]) + ({u},{v}), where [] and {} - // denote integer and fractionary parts. - // Now, the convolution positions on fg for (u,v) can be thought of being calculated by taking - // images of integer displacements of (u,v). So, their calculation is definitely *not* directly - // dependent on the fractionary part of (u,v) - that is, the (i,j)th displacement position of FG(u,v) - // is: - // FG([u]+i,[v]+j) = FG(u+i,v+j) - FG({u},{v}) = FG(i,j) - FG({u},{v}); - // - // where it is assumed that FG(u,v) = (0,0), since the filter is to be considered centered on (u,v). - - for (cur_pix_ref_v = min_pix_ref_v; - cur_pix_ref_v <= max_pix_ref_v; - cur_pix_ref_v++) - for (cur_pix_ref_u = min_pix_ref_u; - cur_pix_ref_u <= max_pix_ref_u; - cur_pix_ref_u++) { - //Get the image of current uv position - cur_pix_ref_f_ = affMV1(aff0_uv2fg, cur_pix_ref_u, cur_pix_ref_v); - cur_pix_ref_g_ = affMV2(aff0_uv2fg, cur_pix_ref_u, cur_pix_ref_v); - - //And round it to the closest integer in fg - cur_pix_ref_f = tround(cur_pix_ref_f_); - cur_pix_ref_g = tround(cur_pix_ref_g_); - if (min_pix_ref_f <= cur_pix_ref_f && cur_pix_ref_f <= max_pix_ref_f && - min_pix_ref_g <= cur_pix_ref_g && cur_pix_ref_g <= max_pix_ref_g) { - pix_ref_u[n_pix] = cur_pix_ref_u; - pix_ref_v[n_pix] = cur_pix_ref_v; - pix_ref_f[n_pix] = cur_pix_ref_f; - pix_ref_g[n_pix] = cur_pix_ref_g; - notMoreThan(cur_pix_ref_f + min_ref_out_f, min_pix_out_f); //cur_pix_ref > min_pix_out - min_ref_out - notMoreThan(cur_pix_ref_g + min_ref_out_g, min_pix_out_g); - notLessThan(cur_pix_ref_f + max_ref_out_f, max_pix_out_f); //cur_pix_ref < max_pix_out - max_ref_out - notLessThan(cur_pix_ref_g + max_ref_out_g, max_pix_out_g); - n_pix++; - } - } - assert(n_pix > 0); + assert(flt_type != TRop::None); + + // Retrieve the filter radius in the st and fx references + filter_st_radius = get_filter_radius(flt_type); + filter_fg_radius = filter_st_radius * FILTER_RESOLUTION; + + // Retrieve the transformation affines among the involved references + // NOTE: The 0.5 translation is needed in order to make the later + // resample_main procedures work with pixel centers. + aff_uv2xy = aff * TTranslation(0.5, 0.5); + aff0_uv2xy = aff_uv2xy.place(0.0, 0.0, 0.0, 0.0); + aff_xy2uv = aff_uv2xy.inv(); + + // Consider the norm of (1,0) and (0,1) images. + scale_x = sqrt(sq(aff_uv2xy.a11) + sq(aff_uv2xy.a12)); + scale_y = sqrt(sq(aff_uv2xy.a21) + sq(aff_uv2xy.a22)); + + // Inserting the following scale will make shrinks look smooth. + aff0_xy2st = TScale((scale_x > 1.0) ? 1.0 / scale_x : 1.0, + (scale_y > 1.0) ? 1.0 / scale_y : 1.0); + + if (blur > 1.0) // Consider the blur as a scale in the filter reference + { + inv_blur = 1.0 / blur; + aff0_xy2st = TScale(inv_blur, inv_blur) * aff0_xy2st; + } + + aff0_uv2st = aff0_xy2st * aff0_uv2xy; + aff0_st2fg = TScale(FILTER_RESOLUTION, FILTER_RESOLUTION); + aff0_uv2fg = aff0_st2fg * aff0_uv2st; + aff0_fg2uv = aff0_uv2fg.inv(); + + // Take the pre-image of the filter mask in uv coordinates. This is where + // input pixels will be taken to find an output one. + minmax(-filter_fg_radius, -filter_fg_radius, filter_fg_radius, + filter_fg_radius, aff0_fg2uv, min_pix_out_u_, min_pix_out_v_, + max_pix_out_u_, max_pix_out_v_); + + // Adjust them to integer coordinates. The intent here is that + // of isolating their fractionary part - furthermore, we'll take + // the *opposites* of fractionary parts (explained later). + // NOTE: We'll assume we want to include in the filter mask all + //*integer positions around a fractionary displacement of the origin*; + // so the approximations below are stricly necessary. + + min_pix_ref_u = intLE(min_pix_out_u_); + min_pix_ref_v = intLE(min_pix_out_v_); + max_pix_ref_u = intGE(max_pix_out_u_); + max_pix_ref_v = intGE(max_pix_out_v_); + + if (blur <= 1.0) { + // If the blur radius has sub-pixel width + if (aff_uv2xy.a12 == 0.0 && aff_uv2xy.a21 == 0.0) { + // And it's the sole scales case + if (aff_uv2xy.a11 == 1.0 && isInt(aff_uv2xy.a13 - 0.5)) { + // And the x mapping is bijective, then prevent any filtering. + min_pix_ref_u = 0; + max_pix_ref_u = 0; + } + if (aff_uv2xy.a22 == 1.0 && isInt(aff_uv2xy.a23 - 0.5)) { + // And the y mapping is bijective ... + min_pix_ref_v = 0; + max_pix_ref_v = 0; + } + } else if (aff_uv2xy.a11 == 0.0 && aff_uv2xy.a22 == 0.0) { + // The mirrored version of the one above + if (aff_uv2xy.a12 == 1.0 && isInt(aff_uv2xy.a13 - 0.5)) { + min_pix_ref_v = 0; + max_pix_ref_v = 0; + } + if (aff_uv2xy.a21 == 1.0 && isInt(aff_uv2xy.a23 - 0.5)) { + min_pix_ref_u = 0; + max_pix_ref_u = 0; + } + } + } + + // Take the number of pixels involved in the filter (uv reference) + max_n_pix = + (max_pix_ref_u - min_pix_ref_u + 1) * (max_pix_ref_v - min_pix_ref_v + 1); + + if (max_n_pix > current_max_n_pix) { + current_max_n_pix = max_n_pix; + pix_ref_u.reset(new int[current_max_n_pix]); + pix_ref_v.reset(new int[current_max_n_pix]); + pix_ref_f.reset(new int[current_max_n_pix]); + pix_ref_g.reset(new int[current_max_n_pix]); + assert(pix_ref_u && pix_ref_v && pix_ref_f && pix_ref_g); + } + + // Build the image of fractionary domain from the uv to fg reference + minmax(-1, -1, 0, 0, aff0_uv2fg, min_ref_out_f_, min_ref_out_g_, + max_ref_out_f_, max_ref_out_g_); + + min_ref_out_f = tround(min_ref_out_f_); + min_ref_out_g = tround(min_ref_out_g_); + max_ref_out_f = tround(max_ref_out_f_); + max_ref_out_g = tround(max_ref_out_g_); + + // Remember that negative fractionary parts must be subtracted from their + // integer counterparts + min_pix_ref_f = -filter_fg_radius - max_ref_out_f; + min_pix_ref_g = -filter_fg_radius - max_ref_out_g; + max_pix_ref_f = filter_fg_radius - min_ref_out_f; + max_pix_ref_g = filter_fg_radius - min_ref_out_g; + + min_pix_out_f = c_maxint; + min_pix_out_g = c_maxint; + max_pix_out_f = c_minint; + max_pix_out_g = c_minint; + n_pix = 0; + + if (!pix_ref_u || !pix_ref_v || !pix_ref_f || !pix_ref_g) { + throw TRopException( + "tresample.cpp line2640 function rop_resample_rgbm() : alloc pix_ref " + "failed"); + } + + // Build the *integer* part of the fg images of those coordinates inside the + // uv filter bounds. + + // NOTE: Doing so reduces the execution time for the later resample_main + // procedure - + // the idea is the following: + // We want to build the output pixel (x,y) obtained from the source image + // through A. + // Then, we find (u,v) = (A^-1) * (x,y) = ([u],[v]) + ({u},{v}), where [] and + // {} + // denote integer and fractionary parts. + // Now, the convolution positions on fg for (u,v) can be thought of being + // calculated by taking + // images of integer displacements of (u,v). So, their calculation is + // definitely *not* directly + // dependent on the fractionary part of (u,v) - that is, the (i,j)th + // displacement position of FG(u,v) + // is: + // FG([u]+i,[v]+j) = FG(u+i,v+j) - FG({u},{v}) = FG(i,j) - + // FG({u},{v}); + // + // where it is assumed that FG(u,v) = (0,0), since the filter is to be + // considered centered on (u,v). + + for (cur_pix_ref_v = min_pix_ref_v; cur_pix_ref_v <= max_pix_ref_v; + cur_pix_ref_v++) + for (cur_pix_ref_u = min_pix_ref_u; cur_pix_ref_u <= max_pix_ref_u; + cur_pix_ref_u++) { + // Get the image of current uv position + cur_pix_ref_f_ = affMV1(aff0_uv2fg, cur_pix_ref_u, cur_pix_ref_v); + cur_pix_ref_g_ = affMV2(aff0_uv2fg, cur_pix_ref_u, cur_pix_ref_v); + + // And round it to the closest integer in fg + cur_pix_ref_f = tround(cur_pix_ref_f_); + cur_pix_ref_g = tround(cur_pix_ref_g_); + if (min_pix_ref_f <= cur_pix_ref_f && cur_pix_ref_f <= max_pix_ref_f && + min_pix_ref_g <= cur_pix_ref_g && cur_pix_ref_g <= max_pix_ref_g) { + pix_ref_u[n_pix] = cur_pix_ref_u; + pix_ref_v[n_pix] = cur_pix_ref_v; + pix_ref_f[n_pix] = cur_pix_ref_f; + pix_ref_g[n_pix] = cur_pix_ref_g; + notMoreThan(cur_pix_ref_f + min_ref_out_f, + min_pix_out_f); // cur_pix_ref > min_pix_out - min_ref_out + notMoreThan(cur_pix_ref_g + min_ref_out_g, min_pix_out_g); + notLessThan(cur_pix_ref_f + max_ref_out_f, + max_pix_out_f); // cur_pix_ref < max_pix_out - max_ref_out + notLessThan(cur_pix_ref_g + max_ref_out_g, max_pix_out_g); + n_pix++; + } + } + assert(n_pix > 0); #ifdef USE_STATIC_VARS - if (flt_type != current_flt_type) { - current_flt_type = flt_type; + if (flt_type != current_flt_type) { + current_flt_type = flt_type; #endif - //Build a sufficient filter weights array - min_filter_fg = -filter_fg_radius - FILTER_RESOLUTION * 3 / 2; //??? - max_filter_fg = filter_fg_radius + FILTER_RESOLUTION * 3 / 2; - filter_size = max_filter_fg - min_filter_fg + 1; - if (filter_size > filter_array_size) //For the static vars case... - { - filter_array.reset(new short[filter_size]); - assert(filter_array); - filter_array_size = filter_size; - } - filter = filter_array.get() - min_filter_fg; //Take the position corresponding to fg's (0,0) in the array - filter[0] = MAX_FILTER_VAL; - for (f = 1, s_ = 1.0 / FILTER_RESOLUTION; - f < filter_fg_radius; - f++, s_ += 1.0 / FILTER_RESOLUTION) { - //Symmetrically build the array - weight_ = get_filter_value(flt_type, s_) * (double)MAX_FILTER_VAL; - weight = tround(weight_); - filter[f] = weight; - filter[-f] = weight; - } - for (f = filter_fg_radius; f <= max_filter_fg; f++) - filter[f] = 0; - for (f = -filter_fg_radius; f >= min_filter_fg; f--) - filter[f] = 0; + // Build a sufficient filter weights array + min_filter_fg = -filter_fg_radius - FILTER_RESOLUTION * 3 / 2; //??? + max_filter_fg = filter_fg_radius + FILTER_RESOLUTION * 3 / 2; + filter_size = max_filter_fg - min_filter_fg + 1; + if (filter_size > filter_array_size) // For the static vars case... + { + filter_array.reset(new short[filter_size]); + assert(filter_array); + filter_array_size = filter_size; + } + filter = filter_array.get() - min_filter_fg; // Take the position + // corresponding to fg's (0,0) + // in the array + filter[0] = MAX_FILTER_VAL; + for (f = 1, s_ = 1.0 / FILTER_RESOLUTION; f < filter_fg_radius; + f++, s_ += 1.0 / FILTER_RESOLUTION) { + // Symmetrically build the array + weight_ = get_filter_value(flt_type, s_) * (double)MAX_FILTER_VAL; + weight = tround(weight_); + filter[f] = weight; + filter[-f] = weight; + } + for (f = filter_fg_radius; f <= max_filter_fg; f++) filter[f] = 0; + for (f = -filter_fg_radius; f >= min_filter_fg; f--) filter[f] = 0; #ifdef USE_STATIC_VARS - } + } #endif - //Considering the bounding square in fg - min_pix_out_fg = std::min(min_pix_out_f, min_pix_out_g); - max_pix_out_fg = std::max(max_pix_out_f, max_pix_out_g); - if (min_pix_out_fg < min_filter_fg || max_pix_out_fg > max_filter_fg) { - //Reallocate the filter... and so on... - filter_size = max_pix_out_fg - min_pix_out_fg + 1; - if (filter_size > filter_array_size) { - //controllare!! - //TREALLOC (filter_array, filter_size) - filter_array.reset(new short[filter_size]); - - assert(filter_array); - filter_array_size = filter_size; - } - filter = filter_array.get() - min_filter_fg; - if (min_pix_out_fg < min_filter_fg) { - int delta = min_filter_fg - min_pix_out_fg; - - for (f = max_filter_fg; f >= min_filter_fg; f--) - filter[f + delta] = filter[f]; - filter += delta; - for (f = min_filter_fg - 1; f >= min_pix_out_fg; f--) - filter[f] = 0; - min_filter_fg = min_pix_out_fg; - } - if (max_pix_out_fg > max_filter_fg) { - for (f = max_filter_fg + 1; f <= max_pix_out_fg; f++) - filter[f] = 0; - max_filter_fg = max_pix_out_fg; - } - } + // Considering the bounding square in fg + min_pix_out_fg = std::min(min_pix_out_f, min_pix_out_g); + max_pix_out_fg = std::max(max_pix_out_f, max_pix_out_g); + if (min_pix_out_fg < min_filter_fg || max_pix_out_fg > max_filter_fg) { + // Reallocate the filter... and so on... + filter_size = max_pix_out_fg - min_pix_out_fg + 1; + if (filter_size > filter_array_size) { + // controllare!! + // TREALLOC (filter_array, filter_size) + filter_array.reset(new short[filter_size]); + + assert(filter_array); + filter_array_size = filter_size; + } + filter = filter_array.get() - min_filter_fg; + if (min_pix_out_fg < min_filter_fg) { + int delta = min_filter_fg - min_pix_out_fg; + + for (f = max_filter_fg; f >= min_filter_fg; f--) + filter[f + delta] = filter[f]; + filter += delta; + for (f = min_filter_fg - 1; f >= min_pix_out_fg; f--) filter[f] = 0; + min_filter_fg = min_pix_out_fg; + } + if (max_pix_out_fg > max_filter_fg) { + for (f = max_filter_fg + 1; f <= max_pix_out_fg; f++) filter[f] = 0; + max_filter_fg = max_pix_out_fg; + } + } #ifdef _WIN32 - if ((TSystem::getCPUExtensions() & TSystem::CpuSupportsSse2) && T::maxChannelValue == 255) - resample_main_rgbm_SSE2(rout, rin, aff_xy2uv, aff0_uv2fg, - min_pix_ref_u, min_pix_ref_v, - max_pix_ref_u, max_pix_ref_v, - n_pix, - pix_ref_u.get(), pix_ref_v.get(), - pix_ref_f.get(), pix_ref_g.get(), - filter); - else + if ((TSystem::getCPUExtensions() & TSystem::CpuSupportsSse2) && + T::maxChannelValue == 255) + resample_main_rgbm_SSE2(rout, rin, aff_xy2uv, aff0_uv2fg, min_pix_ref_u, + min_pix_ref_v, max_pix_ref_u, max_pix_ref_v, + n_pix, pix_ref_u.get(), pix_ref_v.get(), + pix_ref_f.get(), pix_ref_g.get(), filter); + else #endif - if (n_pix >= 512 || T::maxChannelValue > 255) - resample_main_rgbm( - rout, rin, aff_xy2uv, aff0_uv2fg, - min_pix_ref_u, min_pix_ref_v, - max_pix_ref_u, max_pix_ref_v, - n_pix, - pix_ref_u.get(), pix_ref_v.get(), - pix_ref_f.get(), pix_ref_g.get(), - filter); - else - resample_main_rgbm( - rout, rin, aff_xy2uv, aff0_uv2fg, - min_pix_ref_u, min_pix_ref_v, - max_pix_ref_u, max_pix_ref_v, - n_pix, - pix_ref_u.get(), pix_ref_v.get(), - pix_ref_f.get(), pix_ref_g.get(), - filter); + if (n_pix >= 512 || T::maxChannelValue > 255) + resample_main_rgbm( + rout, rin, aff_xy2uv, aff0_uv2fg, min_pix_ref_u, min_pix_ref_v, + max_pix_ref_u, max_pix_ref_v, n_pix, pix_ref_u.get(), pix_ref_v.get(), + pix_ref_f.get(), pix_ref_g.get(), filter); + else + resample_main_rgbm( + rout, rin, aff_xy2uv, aff0_uv2fg, min_pix_ref_u, min_pix_ref_v, + max_pix_ref_u, max_pix_ref_v, n_pix, pix_ref_u.get(), pix_ref_v.get(), + pix_ref_f.get(), pix_ref_g.get(), filter); } //--------------------------------------------------------------------------- -static void free_filter(FILTER *filter, int lx) -{ - for (--lx; lx >= 0; lx--) - if (filter[lx].w_base) - delete (filter[lx].w_base); - delete (filter); +static void free_filter(FILTER *filter, int lx) { + for (--lx; lx >= 0; lx--) + if (filter[lx].w_base) delete (filter[lx].w_base); + delete (filter); } //----------------------------------------------------------------------------- -void do_resample(TRasterGR8P rout, const TRasterGR8P &rin, - const TAffine &aff, TRop::ResampleFilterType flt_type, double blur) -{ - double jacob; - double s11, s22, s13, s23; - FILTER *rowf, *colf; - NOCALC *rown, *coln; - int pmin, pmax, qmin, qmax; - int nrows, dummy; - double negradu_, negradv_, posradu_, posradv_; - double negradx_, negrady_, posradx_, posrady_; - int nocdiamx, nocdiamy; - double rad_x, rad_y; - TAffine rot, scale, invrot; +void do_resample(TRasterGR8P rout, const TRasterGR8P &rin, const TAffine &aff, + TRop::ResampleFilterType flt_type, double blur) { + double jacob; + double s11, s22, s13, s23; + FILTER *rowf, *colf; + NOCALC *rown, *coln; + int pmin, pmax, qmin, qmax; + int nrows, dummy; + double negradu_, negradv_, posradu_, posradv_; + double negradx_, negrady_, posradx_, posrady_; + int nocdiamx, nocdiamy; + double rad_x, rad_y; + TAffine rot, scale, invrot; #ifdef USE_DOUBLE_TO_INT - double d2iaux; + double d2iaux; #endif - if (!(rout->getLx() > 0 && rout->getLy() > 0)) /* immagine out vuota */ - { - return; - } - if (!(rin->getLx() > 0 && rin->getLy() > 0)) /* immagine in vuota */ - { - rout->fill(TPixelGR8::Black); //Black_rgbm - return; - } - - TRasterGR8P routGR8 = rout, rinGR8 = rin; - if (routGR8 && rinGR8) { - jacob = fabs(aff.det()); - if (jacob == 0.0) - throw TRopException("AFFINE transformation has zero determinant"); - if (jacob < 1E-30) - throw TRopException("AFFINE transformation has (nearly) zero determinant"); - s11 = sqrt(jacob); /* provvisorio */ - s22 = s11; - s13 = aff.a13; - s23 = aff.a23; - - //rot = aff_place (0.0, 0.0, 0.0, 0.0, TScale(1/s11, 1/s22)*aff);//eventualmente invertire ordine - - rot = (TScale(1 / s11, 1 / s22) * aff).place(0.0, 0.0, 0.0, 0.0); - - //scale = aff_place (0.0, 0.0, s13, s23, TScale(s11, s22)); - scale = TScale(s11, s22).place(0.0, 0.0, s13, s23); - invrot = rot.inv(); - - rowf = create_filter(flt_type, blur, scale.a11, scale.a13, rout->getLx(), - rad_x, pmin, pmax, dummy); - colf = create_filter(flt_type, blur, scale.a22, scale.a23, rout->getLy(), - rad_y, qmin, qmax, nrows); - rown = create_nocalc(flt_type, blur, scale.a11, scale.a13, rout->getLx(), - pmin, pmax, nocdiamx); - coln = create_nocalc(flt_type, blur, scale.a22, scale.a23, rout->getLy(), - qmin, qmax, nocdiamy); + if (!(rout->getLx() > 0 && rout->getLy() > 0)) /* immagine out vuota */ + { + return; + } + if (!(rin->getLx() > 0 && rin->getLy() > 0)) /* immagine in vuota */ + { + rout->fill(TPixelGR8::Black); // Black_rgbm + return; + } + + TRasterGR8P routGR8 = rout, rinGR8 = rin; + if (routGR8 && rinGR8) { + jacob = fabs(aff.det()); + if (jacob == 0.0) + throw TRopException("AFFINE transformation has zero determinant"); + if (jacob < 1E-30) + throw TRopException( + "AFFINE transformation has (nearly) zero determinant"); + s11 = sqrt(jacob); /* provvisorio */ + s22 = s11; + s13 = aff.a13; + s23 = aff.a23; + + // rot = aff_place (0.0, 0.0, 0.0, 0.0, TScale(1/s11, + // 1/s22)*aff);//eventualmente invertire ordine + + rot = (TScale(1 / s11, 1 / s22) * aff).place(0.0, 0.0, 0.0, 0.0); + + // scale = aff_place (0.0, 0.0, s13, s23, TScale(s11, s22)); + scale = TScale(s11, s22).place(0.0, 0.0, s13, s23); + invrot = rot.inv(); + + rowf = create_filter(flt_type, blur, scale.a11, scale.a13, rout->getLx(), + rad_x, pmin, pmax, dummy); + colf = create_filter(flt_type, blur, scale.a22, scale.a23, rout->getLy(), + rad_y, qmin, qmax, nrows); + rown = create_nocalc(flt_type, blur, scale.a11, scale.a13, rout->getLx(), + pmin, pmax, nocdiamx); + coln = create_nocalc(flt_type, blur, scale.a22, scale.a23, rout->getLy(), + qmin, qmax, nocdiamy); #ifdef DBMALLOC - malloc_chain_check(TRUE); + malloc_chain_check(TRUE); #endif #ifdef MEMLEAK - CheckMemory(); + CheckMemory(); #endif - TAffine aff_0 = aff.place(0.0, 0.0, 0.0, 0.0); - TAffine inv_0 = aff_0.inv(); - - minmax(-0.5, -0.5, 0.5, 0.5, aff_0, - negradx_, negrady_, posradx_, posrady_); - double flatradx_ = posradx_; - double flatrady_ = posrady_; - minmax(negradx_ - rad_x, negrady_ - rad_y, posradx_ + rad_x, posrady_ + rad_y, inv_0, - negradu_, negradv_, posradu_, posradv_); - - int flatradu = tceil(posradu_) - 1; - int flatradv = tceil(posradv_) - 1; - - rop_resample_gr8(rin, rout, aff, invrot, - rowf, pmin, pmax, colf, qmin, qmax, nrows, - flatradu, flatradv, flatradx_, flatrady_, - rown, nocdiamx, coln, nocdiamy); - - //free_nocalc (coln); - if (coln) - delete (coln); - //free_nocalc (rown); - if (rown) - delete (rown); - free_filter(colf, rout->getLy()); - free_filter(rowf, rout->getLx()); - //----NON GESTIAMO ANCORA EXTRA BUFFER - //rop_resample_extra (rin, rout, aff); - - return; - } else - throw TRopException("unsupported pixel type"); + TAffine aff_0 = aff.place(0.0, 0.0, 0.0, 0.0); + TAffine inv_0 = aff_0.inv(); + + minmax(-0.5, -0.5, 0.5, 0.5, aff_0, negradx_, negrady_, posradx_, posrady_); + double flatradx_ = posradx_; + double flatrady_ = posrady_; + minmax(negradx_ - rad_x, negrady_ - rad_y, posradx_ + rad_x, + posrady_ + rad_y, inv_0, negradu_, negradv_, posradu_, posradv_); + + int flatradu = tceil(posradu_) - 1; + int flatradv = tceil(posradv_) - 1; + + rop_resample_gr8(rin, rout, aff, invrot, rowf, pmin, pmax, colf, qmin, qmax, + nrows, flatradu, flatradv, flatradx_, flatrady_, rown, + nocdiamx, coln, nocdiamy); + + // free_nocalc (coln); + if (coln) delete (coln); + // free_nocalc (rown); + if (rown) delete (rown); + free_filter(colf, rout->getLy()); + free_filter(rowf, rout->getLx()); + //----NON GESTIAMO ANCORA EXTRA BUFFER + // rop_resample_extra (rin, rout, aff); + + return; + } else + throw TRopException("unsupported pixel type"); } //----------------------------------------------------------------------------- -void do_resample(TRasterGR8P rout, const TRaster32P &rin, - const TAffine &aff, TRop::ResampleFilterType flt_type, double blur) -{ - double jacob; - double s11, s22, s13, s23; - FILTER *rowf, *colf; - NOCALC *rown, *coln; - int pmin, pmax, qmin, qmax; - int nrows, dummy; - double negradu_, negradv_, posradu_, posradv_; - double negradx_, negrady_, posradx_, posrady_; - int nocdiamx, nocdiamy; - double rad_x, rad_y; - TAffine rot, scale, invrot; +void do_resample(TRasterGR8P rout, const TRaster32P &rin, const TAffine &aff, + TRop::ResampleFilterType flt_type, double blur) { + double jacob; + double s11, s22, s13, s23; + FILTER *rowf, *colf; + NOCALC *rown, *coln; + int pmin, pmax, qmin, qmax; + int nrows, dummy; + double negradu_, negradv_, posradu_, posradv_; + double negradx_, negrady_, posradx_, posrady_; + int nocdiamx, nocdiamy; + double rad_x, rad_y; + TAffine rot, scale, invrot; #ifdef USE_DOUBLE_TO_INT - double d2iaux; + double d2iaux; #endif - if (!(rout->getLx() > 0 && rout->getLy() > 0)) /* immagine out vuota */ - { - return; - } - if (!(rin->getLx() > 0 && rin->getLy() > 0)) /* immagine in vuota */ - { - rout->fill(TPixelGR8::Black); //Black_rgbm - return; - } - - jacob = fabs(aff.det()); - if (jacob == 0.0) - throw TRopException("AFFINE transformation has zero determinant"); - if (jacob < 1E-30) - throw TRopException("AFFINE transformation has (nearly) zero determinant"); - s11 = sqrt(jacob); /* provvisorio */ - s22 = s11; - s13 = aff.a13; - s23 = aff.a23; - - //rot = aff_place (0.0, 0.0, 0.0, 0.0, TScale(1/s11, 1/s22)*aff);//eventualmente invertire ordine - - rot = (TScale(1 / s11, 1 / s22) * aff).place(0.0, 0.0, 0.0, 0.0); - - //scale = aff_place (0.0, 0.0, s13, s23, TScale(s11, s22)); - scale = TScale(s11, s22).place(0.0, 0.0, s13, s23); - invrot = rot.inv(); - - rowf = create_filter(flt_type, blur, scale.a11, scale.a13, rout->getLx(), - rad_x, pmin, pmax, dummy); - colf = create_filter(flt_type, blur, scale.a22, scale.a23, rout->getLy(), - rad_y, qmin, qmax, nrows); - rown = create_nocalc(flt_type, blur, scale.a11, scale.a13, rout->getLx(), - pmin, pmax, nocdiamx); - coln = create_nocalc(flt_type, blur, scale.a22, scale.a23, rout->getLy(), - qmin, qmax, nocdiamy); + if (!(rout->getLx() > 0 && rout->getLy() > 0)) /* immagine out vuota */ + { + return; + } + if (!(rin->getLx() > 0 && rin->getLy() > 0)) /* immagine in vuota */ + { + rout->fill(TPixelGR8::Black); // Black_rgbm + return; + } + + jacob = fabs(aff.det()); + if (jacob == 0.0) + throw TRopException("AFFINE transformation has zero determinant"); + if (jacob < 1E-30) + throw TRopException("AFFINE transformation has (nearly) zero determinant"); + s11 = sqrt(jacob); /* provvisorio */ + s22 = s11; + s13 = aff.a13; + s23 = aff.a23; + + // rot = aff_place (0.0, 0.0, 0.0, 0.0, TScale(1/s11, + // 1/s22)*aff);//eventualmente invertire ordine + + rot = (TScale(1 / s11, 1 / s22) * aff).place(0.0, 0.0, 0.0, 0.0); + + // scale = aff_place (0.0, 0.0, s13, s23, TScale(s11, s22)); + scale = TScale(s11, s22).place(0.0, 0.0, s13, s23); + invrot = rot.inv(); + + rowf = create_filter(flt_type, blur, scale.a11, scale.a13, rout->getLx(), + rad_x, pmin, pmax, dummy); + colf = create_filter(flt_type, blur, scale.a22, scale.a23, rout->getLy(), + rad_y, qmin, qmax, nrows); + rown = create_nocalc(flt_type, blur, scale.a11, scale.a13, rout->getLx(), + pmin, pmax, nocdiamx); + coln = create_nocalc(flt_type, blur, scale.a22, scale.a23, rout->getLy(), + qmin, qmax, nocdiamy); #ifdef DBMALLOC - malloc_chain_check(TRUE); + malloc_chain_check(TRUE); #endif #ifdef MEMLEAK - CheckMemory(); + CheckMemory(); #endif - TAffine aff_0 = aff.place(0.0, 0.0, 0.0, 0.0); - TAffine inv_0 = aff_0.inv(); - - minmax(-0.5, -0.5, 0.5, 0.5, aff_0, - negradx_, negrady_, posradx_, posrady_); - double flatradx_ = posradx_; - double flatrady_ = posrady_; - minmax(negradx_ - rad_x, negrady_ - rad_y, posradx_ + rad_x, posrady_ + rad_y, inv_0, - negradu_, negradv_, posradu_, posradv_); - - int flatradu = tceil(posradu_) - 1; - int flatradv = tceil(posradv_) - 1; - - rop_resample_rgbm32_gr8(rin, rout, aff, invrot, - rowf, pmin, pmax, colf, qmin, qmax, nrows, - flatradu, flatradv, flatradx_, flatrady_, - rown, nocdiamx, coln, nocdiamy); - - //free_nocalc (coln); - if (coln) - delete (coln); - //free_nocalc (rown); - if (rown) - delete (rown); - free_filter(colf, rout->getLy()); - free_filter(rowf, rout->getLx()); - //----NON GESTIAMO ANCORA EXTRA BUFFER - //rop_resample_extra (rin, rout, aff); - - return; - - // else throw TRopException("unsupported pixel type"); + TAffine aff_0 = aff.place(0.0, 0.0, 0.0, 0.0); + TAffine inv_0 = aff_0.inv(); + + minmax(-0.5, -0.5, 0.5, 0.5, aff_0, negradx_, negrady_, posradx_, posrady_); + double flatradx_ = posradx_; + double flatrady_ = posrady_; + minmax(negradx_ - rad_x, negrady_ - rad_y, posradx_ + rad_x, posrady_ + rad_y, + inv_0, negradu_, negradv_, posradu_, posradv_); + + int flatradu = tceil(posradu_) - 1; + int flatradv = tceil(posradv_) - 1; + + rop_resample_rgbm32_gr8(rin, rout, aff, invrot, rowf, pmin, pmax, colf, qmin, + qmax, nrows, flatradu, flatradv, flatradx_, flatrady_, + rown, nocdiamx, coln, nocdiamy); + + // free_nocalc (coln); + if (coln) delete (coln); + // free_nocalc (rown); + if (rown) delete (rown); + free_filter(colf, rout->getLy()); + free_filter(rowf, rout->getLx()); + //----NON GESTIAMO ANCORA EXTRA BUFFER + // rop_resample_extra (rin, rout, aff); + + return; + + // else throw TRopException("unsupported pixel type"); } //----------------------------------------------------------------------------- template -void do_resample(TRasterPT rout, const TRasterPT &rin, - const TAffine &aff, TRop::ResampleFilterType flt_type, double blur) +void do_resample(TRasterPT rout, const TRasterPT &rin, const TAffine &aff, + TRop::ResampleFilterType flt_type, double blur) { #ifdef ALTRI_TIPI_DI_RASTER - double jacob; - double s11, s22, s13, s23; - FILTER *rowf, *colf; - NOCALC *rown, *coln; - int pmin, pmax, qmin, qmax; - int nrows, dummy; - double negradu_, negradv_, posradu_, posradv_; - double negradx_, negrady_, posradx_, posrady_; - int nocdiamx, nocdiamy; - double rad_x, rad_y; + double jacob; + double s11, s22, s13, s23; + FILTER *rowf, *colf; + NOCALC *rown, *coln; + int pmin, pmax, qmin, qmax; + int nrows, dummy; + double negradu_, negradv_, posradu_, posradv_; + double negradx_, negrady_, posradx_, posrady_; + int nocdiamx, nocdiamy; + double rad_x, rad_y; #endif - if (!(rout->getLx() > 0 && rout->getLy() > 0)) /* immagine out vuota */ - { - return; - } - if (!(rin->getLx() > 0 && rin->getLy() > 0)) /* immagine in vuota */ - { - rout->fill(T::Black); //Black_rgbm - return; - } - - TRasterPT rout_ = rout, rin_ = rin; - if (rout_ && rin_) { - rop_resample_rgbm(rout, rin, aff, flt_type, blur); - return; - } else - throw TRopException("unsupported pixel type"); + if (!(rout->getLx() > 0 && rout->getLy() > 0)) /* immagine out vuota */ + { + return; + } + if (!(rin->getLx() > 0 && rin->getLy() > 0)) /* immagine in vuota */ + { + rout->fill(T::Black); // Black_rgbm + return; + } + + TRasterPT rout_ = rout, rin_ = rin; + if (rout_ && rin_) { + rop_resample_rgbm(rout, rin, aff, flt_type, blur); + return; + } else + throw TRopException("unsupported pixel type"); #ifdef ALTRI_TIPI_DI_RASTER - jacob = fabs(aff.det()); - if (jacob == 0.0) - throw TRopException("AFFINE transformation has zero determinant"); - if (jacob < 1E-30) - throw TRopException("AFFINE transformation has (nearly) zero determinant"); - s11 = sqrt(jacob); /* provvisorio */ - s22 = s11; - s13 = aff.a13; - s23 = aff.a23; - - rot = (TScale(1 / s11, 1 / s22) * aff).place(0.0, 0.0, 0.0, 0.0); - - scale = TScale(s11, s22).place(0.0, 0.0, s13, s23); - invrot = rot.inv(); - - rowf = create_filter(flt_type, blur, scale.a11, scale.a13, rout->getLx(), - rad_x, pmin, pmax, dummy); - colf = create_filter(flt_type, blur, scale.a22, scale.a23, rout->getLy(), - rad_y, qmin, qmax, nrows); - rown = create_nocalc(flt_type, blur, scale.a11, scale.a13, rout->getLx(), - pmin, pmax, nocdiamx); - coln = create_nocalc(flt_type, blur, scale.a22, scale.a23, rout->getLy(), - qmin, qmax, nocdiamy); + jacob = fabs(aff.det()); + if (jacob == 0.0) + throw TRopException("AFFINE transformation has zero determinant"); + if (jacob < 1E-30) + throw TRopException("AFFINE transformation has (nearly) zero determinant"); + s11 = sqrt(jacob); /* provvisorio */ + s22 = s11; + s13 = aff.a13; + s23 = aff.a23; + + rot = (TScale(1 / s11, 1 / s22) * aff).place(0.0, 0.0, 0.0, 0.0); + + scale = TScale(s11, s22).place(0.0, 0.0, s13, s23); + invrot = rot.inv(); + + rowf = create_filter(flt_type, blur, scale.a11, scale.a13, rout->getLx(), + rad_x, pmin, pmax, dummy); + colf = create_filter(flt_type, blur, scale.a22, scale.a23, rout->getLy(), + rad_y, qmin, qmax, nrows); + rown = create_nocalc(flt_type, blur, scale.a11, scale.a13, rout->getLx(), + pmin, pmax, nocdiamx); + coln = create_nocalc(flt_type, blur, scale.a22, scale.a23, rout->getLy(), + qmin, qmax, nocdiamy); #ifdef DBMALLOC - malloc_chain_check(TRUE); + malloc_chain_check(TRUE); #endif #ifdef MEMLEAK - CheckMemory(); + CheckMemory(); #endif - aff_0 = aff.place(0.0, 0.0, 0.0, 0.0); - inv_0 = aff_0.inv(); + aff_0 = aff.place(0.0, 0.0, 0.0, 0.0); + inv_0 = aff_0.inv(); - minmax(-0.5, -0.5, 0.5, 0.5, aff_0, - negradx_, negrady_, posradx_, posrady_); - minmax(negradx_ - rad_x, negrady_ - rad_y, posradx_ + rad_x, posrady_ + rad_y, inv_0, - negradu_, negradv_, posradu_, posradv_); + minmax(-0.5, -0.5, 0.5, 0.5, aff_0, negradx_, negrady_, posradx_, posrady_); + minmax(negradx_ - rad_x, negrady_ - rad_y, posradx_ + rad_x, posrady_ + rad_y, + inv_0, negradu_, negradv_, posradu_, posradv_); - if (coln) - delete (coln); - if (rown) - delete (rown); - free_filter(colf, rout->getLy()); - free_filter(rowf, rout->getLx()); + if (coln) delete (coln); + if (rown) delete (rown); + free_filter(colf, rout->getLy()); + free_filter(rowf, rout->getLx()); #endif } //----------------------------------------------------------------------------- -typedef struct - { - TUINT32 val; - double tot; +typedef struct { + TUINT32 val; + double tot; } BLOB24; //----------------------------------------------------------------------------- @@ -2962,329 +2882,325 @@ typedef struct #define MINOR(x, a) ((x) >= 0 && (x) < (a)) //----------------------------------------------------------------------------- -} //namespace +} // namespace #ifndef TNZCORE_LIGHT -namespace -{ -void do_resample(TRasterCM32P rout, const TRasterCM32P &rin, const TAffine &aff) -{ - TAffine inv; - int lx, ly, mx, my; - int lu, lv, mu, mv; - int x, y, u, v; - double u_0, v_0, u_, v_; - double fu, fv, gu, gv; - int i, j; - int wrapin, wrapout; - TUINT32 *bufin_tcm, *bufout_tcm; - TUINT32 *in_tcm, *out_tcm; - TUINT32 tcm[4]; - double w[4]; - TUINT32 transp; - BLOB24 color_blob[4], new_color_blob; - BLOB24 pencil_blob[4], new_pencil_blob; - int color_blobs; - int pencil_blobs; - bool some_pencil; - double tone_tot; - TUINT32 color_mask, pencil_mask; - TUINT32 tone_mask; - int tone; +namespace { +void do_resample(TRasterCM32P rout, const TRasterCM32P &rin, + const TAffine &aff) { + TAffine inv; + int lx, ly, mx, my; + int lu, lv, mu, mv; + int x, y, u, v; + double u_0, v_0, u_, v_; + double fu, fv, gu, gv; + int i, j; + int wrapin, wrapout; + TUINT32 *bufin_tcm, *bufout_tcm; + TUINT32 *in_tcm, *out_tcm; + TUINT32 tcm[4]; + double w[4]; + TUINT32 transp; + BLOB24 color_blob[4], new_color_blob; + BLOB24 pencil_blob[4], new_pencil_blob; + int color_blobs; + int pencil_blobs; + bool some_pencil; + double tone_tot; + TUINT32 color_mask, pencil_mask; + TUINT32 tone_mask; + int tone; #ifdef USE_DOUBLE_TO_INT - double d2iaux; + double d2iaux; #endif - if (!(rout->getLx() > 0 && rout->getLy() > 0)) /* immagine out vuota */ - return; - - rout->lock(); - - if (!(rin->getLx() > 0 && rin->getLy() > 0)) /* immagine in vuota */ - { - for (y = 0; y < rout->getLy(); y++) - for (x = 0; x < rout->getLx(); x++) - ((TUINT32 *)rout->getRawData())[x + y * rout->getWrap()] = 0xff; - rout->unlock(); - return; - } - - rin->lock(); - - bufin_tcm = (TUINT32 *)rin->getRawData(); - bufout_tcm = (TUINT32 *)rout->getRawData(); - wrapin = rin->getWrap(); - wrapout = rout->getWrap(); - lu = rin->getLx(); - mu = lu - 1; - lv = rin->getLy(); - mv = lv - 1; - lx = rout->getLx(); - mx = lx - 1; - ly = rout->getLy(); - my = ly - 1; - inv = aff.inv(); - - pencil_mask = TPixelCM32::getInkMask(); - color_mask = TPixelCM32::getPaintMask(); - tone_mask = TPixelCM32::getToneMask(); - - transp = tone_mask; - - assert(tone_mask & 0x1); //Ensure that tone lies in the less significative bits - - //deal with every output line independently - for (y = 0; y < ly; y++) { - //Take inv*(0,y) - u_0 = inv.a12 * y + inv.a13; - v_0 = inv.a22 * y + inv.a23; - - out_tcm = bufout_tcm + wrapout * y; - x = 0; - - //Place transparent pixels until we reach a useful source pos. - for (; x < lx; x++) { - //Add inv*(x,0) and floor it - u_ = u_0 + x * inv.a11; - u = tfloor(u_); - v_ = v_0 + x * inv.a21; - v = tfloor(v_); - if (MINOREQ(u + 1, lu) && MINOREQ(v + 1, lv)) //u>=-1 && u=-1 && v=0 && u=0 && v 0 && color_blob[j].tot > color_blob[j - 1].tot; j--) - tswap(color_blob[j], color_blob[j - 1]); - new_pencil_blob.val = tcm[i] & pencil_mask; - new_pencil_blob.tot = (tone_mask - tone) * w[i]; - for (j = 0; j < pencil_blobs; j++) - if (pencil_blob[j].val == new_pencil_blob.val) - break; - if (j < pencil_blobs) - pencil_blob[j].tot += new_pencil_blob.tot; - else - pencil_blob[pencil_blobs++] = new_pencil_blob; - for (; j > 0 && pencil_blob[j].tot > pencil_blob[j - 1].tot; j--) - tswap(pencil_blob[j], pencil_blob[j - 1]); - } - tone = troundp(tone_tot); - //if (some_pencil && (TUINT32)tone == tone_mask) - // tone--; - //if (color_blob[0].val==0 && pencil_blob[0].val==0) - // tone = 255; - *out_tcm++ = color_blob[0].val | pencil_blob[0].val | tone; - } - } - - //Deal with useful source positions on the output line's pre-image - for (; x < lx; x++) { - u_ = u_0 + x * inv.a11; - u = tfloor(u_); - v_ = v_0 + x * inv.a21; - v = tfloor(v_); - if (!(MINOR(u, lu) && MINOR(v, lv))) //u<0 || u>=lu || v<0 || v>=lv - break; - in_tcm = bufin_tcm + u + v * wrapin; //Take the associated input pixel pointer - tcm[0] = in_tcm[0]; - if (u < lu - 1 && v < lv - 1) { - //Also take their 4 next neighours (we shall perform a kinf of bilinear interpolation) - tcm[1] = in_tcm[1]; - tcm[2] = in_tcm[wrapin]; - tcm[3] = in_tcm[wrapin + 1]; - } else { - //Eventually, simulate the off-boundary ones - tcm[1] = (u == lu - 1) ? in_tcm[0] : in_tcm[1]; - tcm[2] = (v == lv - 1) ? in_tcm[0] : in_tcm[wrapin]; - tcm[3] = (u == lu - 1 || v == lv - 1) ? in_tcm[0] : in_tcm[wrapin + 1]; - } - if (tcm[0] == tcm[1] && tcm[1] == tcm[2] && tcm[2] == tcm[3]) - *out_tcm++ = tcm[0]; //If they are all equal, it's a copy-op - else { - //Otherwise, take the bilinear coordinates - fu = u_ - u; - gu = 1. - fu; - fv = v_ - v; - gv = 1. - fv; - w[0] = gu * gv; - w[2] = gu * fv; //And the associated weights - w[1] = fu * gv; - w[3] = fu * fv; - color_blobs = pencil_blobs = 0; - tone_tot = 0.0; - some_pencil = false; - //Examine all neighbouring pixels - for (i = 0; i < 4; i++) { - tone = tcm[i] & tone_mask; //Take the tone - if ((TUINT32)tone != tone_mask) - some_pencil = true; - tone_tot += tone * w[i]; //Build the weighted tone sum - new_color_blob.val = tcm[i] & color_mask; - new_color_blob.tot = tone * w[i]; //And the weighted paint tone for this pixel - //Fill in the different colors found in an array. Equal colors are stored as one - //with summed weighted total tone. - for (j = 0; j < color_blobs; j++) - if (color_blob[j].val == new_color_blob.val) - break; - if (j < color_blobs) - color_blob[j].tot += new_color_blob.tot; - else - color_blob[color_blobs++] = new_color_blob; - //Sort the stored colors for decreasing weighted total tone - for (; j > 0 && color_blob[j].tot > color_blob[j - 1].tot; j--) - tswap(color_blob[j], color_blob[j - 1]); - - //Deal the same way with ink colors. - new_pencil_blob.val = tcm[i] & pencil_mask; - new_pencil_blob.tot = (tone_mask - tone) * w[i]; - for (j = 0; j < pencil_blobs; j++) - if (pencil_blob[j].val == new_pencil_blob.val) - break; - if (j < pencil_blobs) - pencil_blob[j].tot += new_pencil_blob.tot; - else - pencil_blob[pencil_blobs++] = new_pencil_blob; - for (; j > 0 && pencil_blob[j].tot > pencil_blob[j - 1].tot; j--) - tswap(pencil_blob[j], pencil_blob[j - 1]); - } - - tone = tround(tone_tot); - //if (some_pencil && (TUINT32)tone == tone_mask) - // tone--; - //if (color_blob[0].val==0 && pencil_blob[0].val==0) - // tone = 255; - - //The output colors shall be the ones with maximum weighted total tone, - //with the overall total tone as output tone. - *out_tcm++ = color_blob[0].val | pencil_blob[0].val | tone; - } - } - - //Again, deal with border pixels at the end of line's pre-image - for (; x < lx; x++) { - u_ = u_0 + x * inv.a11; - u = tfloor(u_); - v_ = v_0 + x * inv.a21; - v = tfloor(v_); - if (!(MINOREQ(u + 1, lu) && MINOREQ(v + 1, lv))) //u<-1 || u>=lu || v<-1 || v>=lv - break; - in_tcm = bufin_tcm + u + v * wrapin; - bool u0 = MINOREQ(u, mu); - bool v0 = MINOREQ(v, mv); - bool u1 = MINOREQ(u + 1, mv); - bool v1 = MINOREQ(v + 1, mv); - - tcm[0] = (u0 && v0) ? in_tcm[0] : transp; - tcm[1] = (u1 && v0) ? in_tcm[1] : transp; - tcm[2] = (u0 && v1) ? in_tcm[wrapin] : transp; - tcm[3] = (u1 && v1) ? in_tcm[wrapin + 1] : transp; - if (tcm[0] == tcm[1] && tcm[1] == tcm[2] && tcm[2] == tcm[3]) - *out_tcm++ = tcm[0]; - else { - fu = u_ - u; - gu = 1. - fu; - fv = v_ - v; - gv = 1. - fv; - w[0] = gu * gv; - w[2] = gu * fv; - w[1] = fu * gv; - w[3] = fu * fv; - color_blobs = pencil_blobs = 0; - tone_tot = 0.0; - some_pencil = false; - for (i = 0; i < 4; i++) { - tone = tcm[i] & tone_mask; - if ((TUINT32)tone != tone_mask) - some_pencil = true; - tone_tot += tone * w[i]; - new_color_blob.val = tcm[i] & color_mask; - new_color_blob.tot = tone * w[i]; - for (j = 0; j < color_blobs; j++) - if (color_blob[j].val == new_color_blob.val) - break; - if (j < color_blobs) - color_blob[j].tot += new_color_blob.tot; - else - color_blob[color_blobs++] = new_color_blob; - for (; j > 0 && color_blob[j].tot > color_blob[j - 1].tot; j--) - tswap(color_blob[j], color_blob[j - 1]); - new_pencil_blob.val = tcm[i] & pencil_mask; - new_pencil_blob.tot = (tone_mask - tone) * w[i]; - for (j = 0; j < pencil_blobs; j++) - if (pencil_blob[j].val == new_pencil_blob.val) - break; - if (j < pencil_blobs) - pencil_blob[j].tot += new_pencil_blob.tot; - else - pencil_blob[pencil_blobs++] = new_pencil_blob; - for (; j > 0 && pencil_blob[j].tot > pencil_blob[j - 1].tot; j--) - tswap(pencil_blob[j], pencil_blob[j - 1]); - } - tone = troundp(tone_tot); - //if (some_pencil && (TUINT32)tone == tone_mask) - // tone--; - //if (color_blob[0].val==0 && pencil_blob[0].val==0) - // tone = 255; - - *out_tcm++ = color_blob[0].val | pencil_blob[0].val | tone; - } - } - - //Finally, deal with out-of-source pixels at the end of line's pre-image - for (; x < lx; x++) - *out_tcm++ = transp; - } - - rin->unlock(); - rout->unlock(); + if (!(rout->getLx() > 0 && rout->getLy() > 0)) /* immagine out vuota */ + return; + + rout->lock(); + + if (!(rin->getLx() > 0 && rin->getLy() > 0)) /* immagine in vuota */ + { + for (y = 0; y < rout->getLy(); y++) + for (x = 0; x < rout->getLx(); x++) + ((TUINT32 *)rout->getRawData())[x + y * rout->getWrap()] = 0xff; + rout->unlock(); + return; + } + + rin->lock(); + + bufin_tcm = (TUINT32 *)rin->getRawData(); + bufout_tcm = (TUINT32 *)rout->getRawData(); + wrapin = rin->getWrap(); + wrapout = rout->getWrap(); + lu = rin->getLx(); + mu = lu - 1; + lv = rin->getLy(); + mv = lv - 1; + lx = rout->getLx(); + mx = lx - 1; + ly = rout->getLy(); + my = ly - 1; + inv = aff.inv(); + + pencil_mask = TPixelCM32::getInkMask(); + color_mask = TPixelCM32::getPaintMask(); + tone_mask = TPixelCM32::getToneMask(); + + transp = tone_mask; + + assert(tone_mask & + 0x1); // Ensure that tone lies in the less significative bits + + // deal with every output line independently + for (y = 0; y < ly; y++) { + // Take inv*(0,y) + u_0 = inv.a12 * y + inv.a13; + v_0 = inv.a22 * y + inv.a23; + + out_tcm = bufout_tcm + wrapout * y; + x = 0; + + // Place transparent pixels until we reach a useful source pos. + for (; x < lx; x++) { + // Add inv*(x,0) and floor it + u_ = u_0 + x * inv.a11; + u = tfloor(u_); + v_ = v_0 + x * inv.a21; + v = tfloor(v_); + if (MINOREQ(u + 1, lu) && + MINOREQ(v + 1, lv)) // u>=-1 && u=-1 && v=0 && u=0 && v 0 && color_blob[j].tot > color_blob[j - 1].tot; j--) + tswap(color_blob[j], color_blob[j - 1]); + new_pencil_blob.val = tcm[i] & pencil_mask; + new_pencil_blob.tot = (tone_mask - tone) * w[i]; + for (j = 0; j < pencil_blobs; j++) + if (pencil_blob[j].val == new_pencil_blob.val) break; + if (j < pencil_blobs) + pencil_blob[j].tot += new_pencil_blob.tot; + else + pencil_blob[pencil_blobs++] = new_pencil_blob; + for (; j > 0 && pencil_blob[j].tot > pencil_blob[j - 1].tot; j--) + tswap(pencil_blob[j], pencil_blob[j - 1]); + } + tone = troundp(tone_tot); + // if (some_pencil && (TUINT32)tone == tone_mask) + // tone--; + // if (color_blob[0].val==0 && pencil_blob[0].val==0) + // tone = 255; + *out_tcm++ = color_blob[0].val | pencil_blob[0].val | tone; + } + } + + // Deal with useful source positions on the output line's pre-image + for (; x < lx; x++) { + u_ = u_0 + x * inv.a11; + u = tfloor(u_); + v_ = v_0 + x * inv.a21; + v = tfloor(v_); + if (!(MINOR(u, lu) && MINOR(v, lv))) // u<0 || u>=lu || v<0 || v>=lv + break; + in_tcm = bufin_tcm + u + + v * wrapin; // Take the associated input pixel pointer + tcm[0] = in_tcm[0]; + if (u < lu - 1 && v < lv - 1) { + // Also take their 4 next neighours (we shall perform a kinf of bilinear + // interpolation) + tcm[1] = in_tcm[1]; + tcm[2] = in_tcm[wrapin]; + tcm[3] = in_tcm[wrapin + 1]; + } else { + // Eventually, simulate the off-boundary ones + tcm[1] = (u == lu - 1) ? in_tcm[0] : in_tcm[1]; + tcm[2] = (v == lv - 1) ? in_tcm[0] : in_tcm[wrapin]; + tcm[3] = (u == lu - 1 || v == lv - 1) ? in_tcm[0] : in_tcm[wrapin + 1]; + } + if (tcm[0] == tcm[1] && tcm[1] == tcm[2] && tcm[2] == tcm[3]) + *out_tcm++ = tcm[0]; // If they are all equal, it's a copy-op + else { + // Otherwise, take the bilinear coordinates + fu = u_ - u; + gu = 1. - fu; + fv = v_ - v; + gv = 1. - fv; + w[0] = gu * gv; + w[2] = gu * fv; // And the associated weights + w[1] = fu * gv; + w[3] = fu * fv; + color_blobs = pencil_blobs = 0; + tone_tot = 0.0; + some_pencil = false; + // Examine all neighbouring pixels + for (i = 0; i < 4; i++) { + tone = tcm[i] & tone_mask; // Take the tone + if ((TUINT32)tone != tone_mask) some_pencil = true; + tone_tot += tone * w[i]; // Build the weighted tone sum + new_color_blob.val = tcm[i] & color_mask; + new_color_blob.tot = + tone * w[i]; // And the weighted paint tone for this pixel + // Fill in the different colors found in an array. Equal colors are + // stored as one + // with summed weighted total tone. + for (j = 0; j < color_blobs; j++) + if (color_blob[j].val == new_color_blob.val) break; + if (j < color_blobs) + color_blob[j].tot += new_color_blob.tot; + else + color_blob[color_blobs++] = new_color_blob; + // Sort the stored colors for decreasing weighted total tone + for (; j > 0 && color_blob[j].tot > color_blob[j - 1].tot; j--) + tswap(color_blob[j], color_blob[j - 1]); + + // Deal the same way with ink colors. + new_pencil_blob.val = tcm[i] & pencil_mask; + new_pencil_blob.tot = (tone_mask - tone) * w[i]; + for (j = 0; j < pencil_blobs; j++) + if (pencil_blob[j].val == new_pencil_blob.val) break; + if (j < pencil_blobs) + pencil_blob[j].tot += new_pencil_blob.tot; + else + pencil_blob[pencil_blobs++] = new_pencil_blob; + for (; j > 0 && pencil_blob[j].tot > pencil_blob[j - 1].tot; j--) + tswap(pencil_blob[j], pencil_blob[j - 1]); + } + + tone = tround(tone_tot); + // if (some_pencil && (TUINT32)tone == tone_mask) + // tone--; + // if (color_blob[0].val==0 && pencil_blob[0].val==0) + // tone = 255; + + // The output colors shall be the ones with maximum weighted total tone, + // with the overall total tone as output tone. + *out_tcm++ = color_blob[0].val | pencil_blob[0].val | tone; + } + } + + // Again, deal with border pixels at the end of line's pre-image + for (; x < lx; x++) { + u_ = u_0 + x * inv.a11; + u = tfloor(u_); + v_ = v_0 + x * inv.a21; + v = tfloor(v_); + if (!(MINOREQ(u + 1, lu) && + MINOREQ(v + 1, lv))) // u<-1 || u>=lu || v<-1 || v>=lv + break; + in_tcm = bufin_tcm + u + v * wrapin; + bool u0 = MINOREQ(u, mu); + bool v0 = MINOREQ(v, mv); + bool u1 = MINOREQ(u + 1, mv); + bool v1 = MINOREQ(v + 1, mv); + + tcm[0] = (u0 && v0) ? in_tcm[0] : transp; + tcm[1] = (u1 && v0) ? in_tcm[1] : transp; + tcm[2] = (u0 && v1) ? in_tcm[wrapin] : transp; + tcm[3] = (u1 && v1) ? in_tcm[wrapin + 1] : transp; + if (tcm[0] == tcm[1] && tcm[1] == tcm[2] && tcm[2] == tcm[3]) + *out_tcm++ = tcm[0]; + else { + fu = u_ - u; + gu = 1. - fu; + fv = v_ - v; + gv = 1. - fv; + w[0] = gu * gv; + w[2] = gu * fv; + w[1] = fu * gv; + w[3] = fu * fv; + color_blobs = pencil_blobs = 0; + tone_tot = 0.0; + some_pencil = false; + for (i = 0; i < 4; i++) { + tone = tcm[i] & tone_mask; + if ((TUINT32)tone != tone_mask) some_pencil = true; + tone_tot += tone * w[i]; + new_color_blob.val = tcm[i] & color_mask; + new_color_blob.tot = tone * w[i]; + for (j = 0; j < color_blobs; j++) + if (color_blob[j].val == new_color_blob.val) break; + if (j < color_blobs) + color_blob[j].tot += new_color_blob.tot; + else + color_blob[color_blobs++] = new_color_blob; + for (; j > 0 && color_blob[j].tot > color_blob[j - 1].tot; j--) + tswap(color_blob[j], color_blob[j - 1]); + new_pencil_blob.val = tcm[i] & pencil_mask; + new_pencil_blob.tot = (tone_mask - tone) * w[i]; + for (j = 0; j < pencil_blobs; j++) + if (pencil_blob[j].val == new_pencil_blob.val) break; + if (j < pencil_blobs) + pencil_blob[j].tot += new_pencil_blob.tot; + else + pencil_blob[pencil_blobs++] = new_pencil_blob; + for (; j > 0 && pencil_blob[j].tot > pencil_blob[j - 1].tot; j--) + tswap(pencil_blob[j], pencil_blob[j - 1]); + } + tone = troundp(tone_tot); + // if (some_pencil && (TUINT32)tone == tone_mask) + // tone--; + // if (color_blob[0].val==0 && pencil_blob[0].val==0) + // tone = 255; + + *out_tcm++ = color_blob[0].val | pencil_blob[0].val | tone; + } + } + + // Finally, deal with out-of-source pixels at the end of line's pre-image + for (; x < lx; x++) *out_tcm++ = transp; + } + + rin->unlock(); + rout->unlock(); } //----------------------------------------------------------------------------- @@ -3292,573 +3208,568 @@ void do_resample(TRasterCM32P rout, const TRasterCM32P &rin, const TAffine &aff) #ifdef _WIN32 template void resample_main_cm32_rgbm_SSE2(TRasterPT rout, const TRasterCM32P &rin, - const TAffine &aff_xy2uv, - const TAffine &aff0_uv2fg, - int min_pix_ref_u, int min_pix_ref_v, - int max_pix_ref_u, int max_pix_ref_v, - int n_pix, - int *pix_ref_u, int *pix_ref_v, - int *pix_ref_f, int *pix_ref_g, - short *filter, TPalette *palette) -{ - __m128i zeros = _mm_setzero_si128(); - const TPixelCM32 *buffer_in; - T *buffer_out; - int lu, lv, wrap_in, mu, mv; - int lx, ly, wrap_out; - int out_x, out_y; - double out_x_, out_y_; - double out_u_, out_v_; - int ref_u, ref_v; - int pix_u, pix_v; - double ref_out_u_, ref_out_v_; - double ref_out_f_, ref_out_g_; - int ref_out_f, ref_out_g; - int pix_out_f, pix_out_g; - int inside_offset_u, inside_offset_v; - UINT inside_limit_u, inside_limit_v; - int inside_nonempty; - double outside_min_u_, outside_min_v_; - double outside_max_u_, outside_max_v_; - UCHAR *calc; - int calc_allocsize; - int calc_bytewrap; - UCHAR calc_value; - bool must_calc; - T pix_value; - T default_value(0, 0, 0, 0); - float weight; - float sum_weights; - float inv_sum_weights; - int i; + const TAffine &aff_xy2uv, + const TAffine &aff0_uv2fg, int min_pix_ref_u, + int min_pix_ref_v, int max_pix_ref_u, + int max_pix_ref_v, int n_pix, int *pix_ref_u, + int *pix_ref_v, int *pix_ref_f, + int *pix_ref_g, short *filter, + TPalette *palette) { + __m128i zeros = _mm_setzero_si128(); + const TPixelCM32 *buffer_in; + T *buffer_out; + int lu, lv, wrap_in, mu, mv; + int lx, ly, wrap_out; + int out_x, out_y; + double out_x_, out_y_; + double out_u_, out_v_; + int ref_u, ref_v; + int pix_u, pix_v; + double ref_out_u_, ref_out_v_; + double ref_out_f_, ref_out_g_; + int ref_out_f, ref_out_g; + int pix_out_f, pix_out_g; + int inside_offset_u, inside_offset_v; + UINT inside_limit_u, inside_limit_v; + int inside_nonempty; + double outside_min_u_, outside_min_v_; + double outside_max_u_, outside_max_v_; + UCHAR *calc; + int calc_allocsize; + int calc_bytewrap; + UCHAR calc_value; + bool must_calc; + T pix_value; + T default_value(0, 0, 0, 0); + float weight; + float sum_weights; + float inv_sum_weights; + int i; #ifdef USE_DOUBLE_TO_INT - double d2iaux; + double d2iaux; #endif - T *pix_out; - - __m128 sum_contribs_packed; - __m128 pix_value_packed; - __m128 weight_packed; - - __m128 zeros2 = _mm_setzero_ps(); - - float maxChannelValue = (float)T::maxChannelValue; - __m128 maxChanneValue_packed = _mm_load1_ps(&maxChannelValue); - - if (!(rout->getLx() > 0 && rout->getLy() > 0)) - return; - if (!(rin->getLx() > 0 && rin->getLy() > 0)) { - resample_clear_rgbm(rout, default_value); - return; - } - calc = 0; - calc_allocsize = 0; - - create_calc(rin, min_pix_ref_u, max_pix_ref_u, - min_pix_ref_v, max_pix_ref_v, - calc, calc_allocsize, calc_bytewrap); - - buffer_in = rin->pixels(); - buffer_out = rout->pixels(); - lu = rin->getLx(); - lx = rout->getLx(); - lv = rin->getLy(); - ly = rout->getLy(); - wrap_in = rin->getWrap(); - wrap_out = rout->getWrap(); - mu = lu - 1; - mv = lv - 1; - - inside_offset_u = -min_pix_ref_u; - inside_offset_v = -min_pix_ref_v; - inside_limit_u = lu - max_pix_ref_u - inside_offset_u; - inside_limit_v = lv - max_pix_ref_v - inside_offset_v; - inside_nonempty = (int)inside_limit_u > 0 && (int)inside_limit_v > 0; - outside_min_u_ = -0.5; - outside_min_v_ = -0.5; - outside_max_u_ = lu - 0.5; - outside_max_v_ = lv - 0.5; - - int count = palette->getStyleCount(); - int count2 = std::max({count, TPixelCM32::getMaxInk(), TPixelCM32::getMaxPaint()}); - - TPixelFloat *paints = (TPixelFloat *)_aligned_malloc(count2 * sizeof(TPixelFloat), 16); - TPixelFloat *inks = (TPixelFloat *)_aligned_malloc(count2 * sizeof(TPixelFloat), 16); - - std::vector paints2(count2); - std::vector inks2(count2); - for (i = 0; i < palette->getStyleCount(); i++) { - TPixel32 color = ::premultiply(palette->getStyle(i)->getAverageColor()); - paints[i] = inks[i] = TPixelFloat(color); - paints2[i] = inks2[i] = color; - } - - float maxTone = (float)TPixelCM32::getMaxTone(); - __m128 den_packed = _mm_load1_ps(&maxTone); - - for (out_y = 0, out_y_ = 0.0; out_y < ly; out_y++, out_y_ += 1.0) { - for (out_x = 0, out_x_ = 0.0; out_x < lx; out_x++, out_x_ += 1.0) { - pix_out = buffer_out + out_y * wrap_out + out_x; - - out_u_ = affMV1(aff_xy2uv, out_x_, out_y_); - out_v_ = affMV2(aff_xy2uv, out_x_, out_y_); - ref_u = intLE(out_u_); - ref_v = intLE(out_v_); - - if (inside_nonempty && - (UINT)(ref_u - inside_offset_u) < inside_limit_u && - (UINT)(ref_v - inside_offset_v) < inside_limit_v) { - calc_value = calc[(ref_u >> 3) + ref_v * calc_bytewrap]; - if (calc_value && ((calc_value >> (ref_u & 7)) & 1)) { - ref_out_u_ = ref_u - out_u_; - ref_out_v_ = ref_v - out_v_; - ref_out_f_ = aff0MV1(aff0_uv2fg, ref_out_u_, ref_out_v_); - ref_out_g_ = aff0MV2(aff0_uv2fg, ref_out_u_, ref_out_v_); - ref_out_f = tround(ref_out_f_); - ref_out_g = tround(ref_out_g_); - sum_weights = 0; - - sum_contribs_packed = _mm_setzero_ps(); - - for (i = n_pix - 1; i >= 0; i--) { - pix_out_f = pix_ref_f[i] + ref_out_f; - pix_out_g = pix_ref_g[i] + ref_out_g; - weight = (float)((filter[pix_out_f] * filter[pix_out_g]) >> 16); - pix_u = pix_ref_u[i] + ref_u; - pix_v = pix_ref_v[i] + ref_v; - - int pix_in_pos = pix_u + pix_v * wrap_in; - const TPixelCM32 *pix_in = buffer_in + pix_in_pos; - int tone = pix_in->getTone(); - int paint = pix_in->getPaint(); - int ink = pix_in->getInk(); - - if (tone == TPixelCM32::getMaxTone()) - pix_value_packed = _mm_load_ps((float *)&(paints[paint])); - else if (tone == 0) - pix_value_packed = _mm_load_ps((float *)&(inks[ink])); - else { - float tt = (float)tone; - blendBySSE2( - pix_value_packed, // il valore calcolato - (float *)&(inks[ink]), - (float *)&(paints[paint]), - &tt, den_packed, zeros); - } - - weight_packed = _mm_load1_ps(&weight); - sum_contribs_packed = _mm_add_ps(sum_contribs_packed, _mm_mul_ps(pix_value_packed, weight_packed)); - - sum_weights += weight; - } - - inv_sum_weights = 1.0f / sum_weights; - __m128 inv_sum_weights_packed = _mm_load1_ps(&inv_sum_weights); - - __m128 out_fval_packed = _mm_mul_ps(sum_contribs_packed, inv_sum_weights_packed); - out_fval_packed = _mm_max_ps(out_fval_packed, zeros2); - out_fval_packed = _mm_min_ps(out_fval_packed, maxChanneValue_packed); - - __m128i out_value_packed_i = _mm_cvtps_epi32(out_fval_packed); - out_value_packed_i = _mm_packs_epi32(out_value_packed_i, zeros); - out_value_packed_i = _mm_packus_epi16(out_value_packed_i, zeros); - *(DWORD *)(pix_out) = _mm_cvtsi128_si32(out_value_packed_i); - } else { - int pix_in_pos = ref_u + ref_v * wrap_in; - const TPixelCM32 *pix_in = buffer_in + pix_in_pos; - int tone = pix_in->getTone(); - int paint = pix_in->getPaint(); - int ink = pix_in->getInk(); - - if (tone == TPixelCM32::getMaxTone()) - *pix_out = paints2[paint]; - else if (tone == 0) - *pix_out = inks2[ink]; - else - *pix_out = blend(inks2[ink], paints2[paint], tone, TPixelCM32::getMaxTone()); - } - } else if (outside_min_u_ <= out_u_ && out_u_ <= outside_max_u_ && - outside_min_v_ <= out_v_ && out_v_ <= outside_max_v_) { - if ((UINT)ref_u >= (UINT)lu || (UINT)ref_v >= (UINT)lv) - must_calc = true; - else { - calc_value = calc[(ref_u >> 3) + ref_v * calc_bytewrap]; - must_calc = calc_value && ((calc_value >> (ref_u & 7)) & 1); - } - - if (must_calc) { - ref_out_u_ = ref_u - out_u_; - ref_out_v_ = ref_v - out_v_; - ref_out_f_ = aff0MV1(aff0_uv2fg, ref_out_u_, ref_out_v_); - ref_out_g_ = aff0MV2(aff0_uv2fg, ref_out_u_, ref_out_v_); - ref_out_f = tround(ref_out_f_); - ref_out_g = tround(ref_out_g_); - sum_weights = 0; - sum_contribs_packed = _mm_setzero_ps(); - - for (i = n_pix - 1; i >= 0; i--) { - pix_out_f = pix_ref_f[i] + ref_out_f; - pix_out_g = pix_ref_g[i] + ref_out_g; - weight = (float)((filter[pix_out_f] * filter[pix_out_g]) >> 16); - pix_u = pix_ref_u[i] + ref_u; - pix_v = pix_ref_v[i] + ref_v; - notLessThan(0, pix_u); - notLessThan(0, pix_v); - notMoreThan(mu, pix_u); - notMoreThan(mv, pix_v); - - int pix_in_pos = pix_u + pix_v * wrap_in; - const TPixelCM32 *pix_in = buffer_in + pix_in_pos; - int tone = pix_in->getTone(); - int paint = pix_in->getPaint(); - int ink = pix_in->getInk(); - - if (tone == TPixelCM32::getMaxTone()) - pix_value_packed = _mm_load_ps((float *)&(paints[paint])); - else if (tone == 0) - pix_value_packed = _mm_load_ps((float *)&(inks[ink])); - else { - float tt = (float)tone; - blendBySSE2( - pix_value_packed, // il valore calcolato - (float *)&(inks[ink]), (float *)&(paints[paint]), - &tt, den_packed, zeros); - } - - weight_packed = _mm_load1_ps(&weight); - sum_contribs_packed = _mm_add_ps(sum_contribs_packed, _mm_mul_ps(pix_value_packed, weight_packed)); - - sum_weights += weight; - } - - inv_sum_weights = 1.0f / sum_weights; - - __m128 inv_sum_weights_packed = _mm_load1_ps(&inv_sum_weights); - __m128 out_fval_packed = _mm_mul_ps(sum_contribs_packed, inv_sum_weights_packed); - out_fval_packed = _mm_max_ps(out_fval_packed, zeros2); - out_fval_packed = _mm_min_ps(out_fval_packed, maxChanneValue_packed); - - __m128i out_value_packed_i = _mm_cvtps_epi32(out_fval_packed); - out_value_packed_i = _mm_packs_epi32(out_value_packed_i, zeros); - out_value_packed_i = _mm_packus_epi16(out_value_packed_i, zeros); - *(DWORD *)(pix_out) = _mm_cvtsi128_si32(out_value_packed_i); - } else { - int pix_in_pos = ref_u + ref_v * wrap_in; - const TPixelCM32 *pix_in = buffer_in + pix_in_pos; - int tone = pix_in->getTone(); - int paint = pix_in->getPaint(); - int ink = pix_in->getInk(); - - if (tone == TPixelCM32::getMaxTone()) - *pix_out = paints2[paint]; - else if (tone == 0) - *pix_out = inks2[ink]; - else - *pix_out = blend(inks2[ink], paints2[paint], tone, TPixelCM32::getMaxTone()); - } - } else { - *pix_out = default_value; - } - } - } - if (calc) - delete[] calc; + T *pix_out; + + __m128 sum_contribs_packed; + __m128 pix_value_packed; + __m128 weight_packed; + + __m128 zeros2 = _mm_setzero_ps(); + + float maxChannelValue = (float)T::maxChannelValue; + __m128 maxChanneValue_packed = _mm_load1_ps(&maxChannelValue); + + if (!(rout->getLx() > 0 && rout->getLy() > 0)) return; + if (!(rin->getLx() > 0 && rin->getLy() > 0)) { + resample_clear_rgbm(rout, default_value); + return; + } + calc = 0; + calc_allocsize = 0; + + create_calc(rin, min_pix_ref_u, max_pix_ref_u, min_pix_ref_v, max_pix_ref_v, + calc, calc_allocsize, calc_bytewrap); + + buffer_in = rin->pixels(); + buffer_out = rout->pixels(); + lu = rin->getLx(); + lx = rout->getLx(); + lv = rin->getLy(); + ly = rout->getLy(); + wrap_in = rin->getWrap(); + wrap_out = rout->getWrap(); + mu = lu - 1; + mv = lv - 1; + + inside_offset_u = -min_pix_ref_u; + inside_offset_v = -min_pix_ref_v; + inside_limit_u = lu - max_pix_ref_u - inside_offset_u; + inside_limit_v = lv - max_pix_ref_v - inside_offset_v; + inside_nonempty = (int)inside_limit_u > 0 && (int)inside_limit_v > 0; + outside_min_u_ = -0.5; + outside_min_v_ = -0.5; + outside_max_u_ = lu - 0.5; + outside_max_v_ = lv - 0.5; + + int count = palette->getStyleCount(); + int count2 = + std::max({count, TPixelCM32::getMaxInk(), TPixelCM32::getMaxPaint()}); + + TPixelFloat *paints = + (TPixelFloat *)_aligned_malloc(count2 * sizeof(TPixelFloat), 16); + TPixelFloat *inks = + (TPixelFloat *)_aligned_malloc(count2 * sizeof(TPixelFloat), 16); + + std::vector paints2(count2); + std::vector inks2(count2); + for (i = 0; i < palette->getStyleCount(); i++) { + TPixel32 color = ::premultiply(palette->getStyle(i)->getAverageColor()); + paints[i] = inks[i] = TPixelFloat(color); + paints2[i] = inks2[i] = color; + } + + float maxTone = (float)TPixelCM32::getMaxTone(); + __m128 den_packed = _mm_load1_ps(&maxTone); + + for (out_y = 0, out_y_ = 0.0; out_y < ly; out_y++, out_y_ += 1.0) { + for (out_x = 0, out_x_ = 0.0; out_x < lx; out_x++, out_x_ += 1.0) { + pix_out = buffer_out + out_y * wrap_out + out_x; + + out_u_ = affMV1(aff_xy2uv, out_x_, out_y_); + out_v_ = affMV2(aff_xy2uv, out_x_, out_y_); + ref_u = intLE(out_u_); + ref_v = intLE(out_v_); + + if (inside_nonempty && (UINT)(ref_u - inside_offset_u) < inside_limit_u && + (UINT)(ref_v - inside_offset_v) < inside_limit_v) { + calc_value = calc[(ref_u >> 3) + ref_v * calc_bytewrap]; + if (calc_value && ((calc_value >> (ref_u & 7)) & 1)) { + ref_out_u_ = ref_u - out_u_; + ref_out_v_ = ref_v - out_v_; + ref_out_f_ = aff0MV1(aff0_uv2fg, ref_out_u_, ref_out_v_); + ref_out_g_ = aff0MV2(aff0_uv2fg, ref_out_u_, ref_out_v_); + ref_out_f = tround(ref_out_f_); + ref_out_g = tround(ref_out_g_); + sum_weights = 0; + + sum_contribs_packed = _mm_setzero_ps(); + + for (i = n_pix - 1; i >= 0; i--) { + pix_out_f = pix_ref_f[i] + ref_out_f; + pix_out_g = pix_ref_g[i] + ref_out_g; + weight = (float)((filter[pix_out_f] * filter[pix_out_g]) >> 16); + pix_u = pix_ref_u[i] + ref_u; + pix_v = pix_ref_v[i] + ref_v; + + int pix_in_pos = pix_u + pix_v * wrap_in; + const TPixelCM32 *pix_in = buffer_in + pix_in_pos; + int tone = pix_in->getTone(); + int paint = pix_in->getPaint(); + int ink = pix_in->getInk(); + + if (tone == TPixelCM32::getMaxTone()) + pix_value_packed = _mm_load_ps((float *)&(paints[paint])); + else if (tone == 0) + pix_value_packed = _mm_load_ps((float *)&(inks[ink])); + else { + float tt = (float)tone; + blendBySSE2(pix_value_packed, // il valore calcolato + (float *)&(inks[ink]), (float *)&(paints[paint]), &tt, + den_packed, zeros); + } + + weight_packed = _mm_load1_ps(&weight); + sum_contribs_packed = + _mm_add_ps(sum_contribs_packed, + _mm_mul_ps(pix_value_packed, weight_packed)); + + sum_weights += weight; + } + + inv_sum_weights = 1.0f / sum_weights; + __m128 inv_sum_weights_packed = _mm_load1_ps(&inv_sum_weights); + + __m128 out_fval_packed = + _mm_mul_ps(sum_contribs_packed, inv_sum_weights_packed); + out_fval_packed = _mm_max_ps(out_fval_packed, zeros2); + out_fval_packed = _mm_min_ps(out_fval_packed, maxChanneValue_packed); + + __m128i out_value_packed_i = _mm_cvtps_epi32(out_fval_packed); + out_value_packed_i = _mm_packs_epi32(out_value_packed_i, zeros); + out_value_packed_i = _mm_packus_epi16(out_value_packed_i, zeros); + *(DWORD *)(pix_out) = _mm_cvtsi128_si32(out_value_packed_i); + } else { + int pix_in_pos = ref_u + ref_v * wrap_in; + const TPixelCM32 *pix_in = buffer_in + pix_in_pos; + int tone = pix_in->getTone(); + int paint = pix_in->getPaint(); + int ink = pix_in->getInk(); + + if (tone == TPixelCM32::getMaxTone()) + *pix_out = paints2[paint]; + else if (tone == 0) + *pix_out = inks2[ink]; + else + *pix_out = blend(inks2[ink], paints2[paint], tone, + TPixelCM32::getMaxTone()); + } + } else if (outside_min_u_ <= out_u_ && out_u_ <= outside_max_u_ && + outside_min_v_ <= out_v_ && out_v_ <= outside_max_v_) { + if ((UINT)ref_u >= (UINT)lu || (UINT)ref_v >= (UINT)lv) + must_calc = true; + else { + calc_value = calc[(ref_u >> 3) + ref_v * calc_bytewrap]; + must_calc = calc_value && ((calc_value >> (ref_u & 7)) & 1); + } + + if (must_calc) { + ref_out_u_ = ref_u - out_u_; + ref_out_v_ = ref_v - out_v_; + ref_out_f_ = aff0MV1(aff0_uv2fg, ref_out_u_, ref_out_v_); + ref_out_g_ = aff0MV2(aff0_uv2fg, ref_out_u_, ref_out_v_); + ref_out_f = tround(ref_out_f_); + ref_out_g = tround(ref_out_g_); + sum_weights = 0; + sum_contribs_packed = _mm_setzero_ps(); + + for (i = n_pix - 1; i >= 0; i--) { + pix_out_f = pix_ref_f[i] + ref_out_f; + pix_out_g = pix_ref_g[i] + ref_out_g; + weight = (float)((filter[pix_out_f] * filter[pix_out_g]) >> 16); + pix_u = pix_ref_u[i] + ref_u; + pix_v = pix_ref_v[i] + ref_v; + notLessThan(0, pix_u); + notLessThan(0, pix_v); + notMoreThan(mu, pix_u); + notMoreThan(mv, pix_v); + + int pix_in_pos = pix_u + pix_v * wrap_in; + const TPixelCM32 *pix_in = buffer_in + pix_in_pos; + int tone = pix_in->getTone(); + int paint = pix_in->getPaint(); + int ink = pix_in->getInk(); + + if (tone == TPixelCM32::getMaxTone()) + pix_value_packed = _mm_load_ps((float *)&(paints[paint])); + else if (tone == 0) + pix_value_packed = _mm_load_ps((float *)&(inks[ink])); + else { + float tt = (float)tone; + blendBySSE2(pix_value_packed, // il valore calcolato + (float *)&(inks[ink]), (float *)&(paints[paint]), &tt, + den_packed, zeros); + } + + weight_packed = _mm_load1_ps(&weight); + sum_contribs_packed = + _mm_add_ps(sum_contribs_packed, + _mm_mul_ps(pix_value_packed, weight_packed)); + + sum_weights += weight; + } + + inv_sum_weights = 1.0f / sum_weights; + + __m128 inv_sum_weights_packed = _mm_load1_ps(&inv_sum_weights); + __m128 out_fval_packed = + _mm_mul_ps(sum_contribs_packed, inv_sum_weights_packed); + out_fval_packed = _mm_max_ps(out_fval_packed, zeros2); + out_fval_packed = _mm_min_ps(out_fval_packed, maxChanneValue_packed); + + __m128i out_value_packed_i = _mm_cvtps_epi32(out_fval_packed); + out_value_packed_i = _mm_packs_epi32(out_value_packed_i, zeros); + out_value_packed_i = _mm_packus_epi16(out_value_packed_i, zeros); + *(DWORD *)(pix_out) = _mm_cvtsi128_si32(out_value_packed_i); + } else { + int pix_in_pos = ref_u + ref_v * wrap_in; + const TPixelCM32 *pix_in = buffer_in + pix_in_pos; + int tone = pix_in->getTone(); + int paint = pix_in->getPaint(); + int ink = pix_in->getInk(); + + if (tone == TPixelCM32::getMaxTone()) + *pix_out = paints2[paint]; + else if (tone == 0) + *pix_out = inks2[ink]; + else + *pix_out = blend(inks2[ink], paints2[paint], tone, + TPixelCM32::getMaxTone()); + } + } else { + *pix_out = default_value; + } + } + } + if (calc) delete[] calc; } #endif /*---------------------------------------------------------------------------*/ -namespace -{ +namespace { template -void resample_main_cm32_rgbm_bigradius(TRasterPT rout, const TRasterCM32P &rin, - const TAffine &aff_xy2uv, - const TAffine &aff0_uv2fg, - int min_pix_ref_u, int min_pix_ref_v, - int max_pix_ref_u, int max_pix_ref_v, - int n_pix, - int *pix_ref_u, int *pix_ref_v, - int *pix_ref_f, int *pix_ref_g, - short *filter, - TPalette *palette) -{ - // bigradius: cambia solo che i sum_contribs sono double invece che int - - const TPixelCM32 *buffer_in; - T *buffer_out; - int lu, lv, wrap_in, mu, mv; - int lx, ly, wrap_out; - int out_x, out_y; - double out_x_, out_y_; - double out_u_, out_v_; - int ref_u, ref_v; - int pix_u, pix_v; - double ref_out_u_, ref_out_v_; - double ref_out_f_, ref_out_g_; - int ref_out_f, ref_out_g; - int pix_out_f, pix_out_g; - int inside_offset_u, inside_offset_v; - UINT inside_limit_u, inside_limit_v; - int inside_nonempty; - double outside_min_u_, outside_min_v_; - double outside_max_u_, outside_max_v_; - UCHAR *calc; - int calc_allocsize; - int calc_bytewrap; - UCHAR calc_value; - bool must_calc; - T pix_value; - T default_value; - float weight; - float sum_weights; - double inv_sum_weights; - double sum_contribs_r, sum_contribs_g, sum_contribs_b, sum_contribs_m; - double out_fval_r, out_fval_g, out_fval_b, out_fval_m; - int out_value_r, out_value_g, out_value_b, out_value_m; - int i; +void resample_main_cm32_rgbm_bigradius( + TRasterPT rout, const TRasterCM32P &rin, const TAffine &aff_xy2uv, + const TAffine &aff0_uv2fg, int min_pix_ref_u, int min_pix_ref_v, + int max_pix_ref_u, int max_pix_ref_v, int n_pix, int *pix_ref_u, + int *pix_ref_v, int *pix_ref_f, int *pix_ref_g, short *filter, + TPalette *palette) { + // bigradius: cambia solo che i sum_contribs sono double invece che int + + const TPixelCM32 *buffer_in; + T *buffer_out; + int lu, lv, wrap_in, mu, mv; + int lx, ly, wrap_out; + int out_x, out_y; + double out_x_, out_y_; + double out_u_, out_v_; + int ref_u, ref_v; + int pix_u, pix_v; + double ref_out_u_, ref_out_v_; + double ref_out_f_, ref_out_g_; + int ref_out_f, ref_out_g; + int pix_out_f, pix_out_g; + int inside_offset_u, inside_offset_v; + UINT inside_limit_u, inside_limit_v; + int inside_nonempty; + double outside_min_u_, outside_min_v_; + double outside_max_u_, outside_max_v_; + UCHAR *calc; + int calc_allocsize; + int calc_bytewrap; + UCHAR calc_value; + bool must_calc; + T pix_value; + T default_value; + float weight; + float sum_weights; + double inv_sum_weights; + double sum_contribs_r, sum_contribs_g, sum_contribs_b, sum_contribs_m; + double out_fval_r, out_fval_g, out_fval_b, out_fval_m; + int out_value_r, out_value_g, out_value_b, out_value_m; + int i; #ifdef USE_DOUBLE_TO_INT - double d2iaux; + double d2iaux; #endif - T *pix_out; - - default_value.r = 0; - default_value.g = 0; - default_value.b = 0; - default_value.m = 0; - - if (!(rout->getLx() > 0 && rout->getLy() > 0)) - return; - if (!(rin->getLx() > 0 && rin->getLy() > 0)) { - rout->clear(); - return; - } - - calc = 0; - calc_allocsize = 0; - create_calc(rin, min_pix_ref_u, max_pix_ref_u, - min_pix_ref_v, max_pix_ref_v, - calc, calc_allocsize, calc_bytewrap); - - buffer_in = rin->pixels(); - buffer_out = rout->pixels(); - lu = rin->getLx(); - lx = rout->getLx(); - lv = rin->getLy(); - ly = rout->getLy(); - wrap_in = rin->getWrap(); - wrap_out = rout->getWrap(); - mu = lu - 1; - mv = lv - 1; - - inside_offset_u = -min_pix_ref_u; - inside_offset_v = -min_pix_ref_v; - inside_limit_u = lu - max_pix_ref_u - inside_offset_u; - inside_limit_v = lv - max_pix_ref_v - inside_offset_v; - inside_nonempty = (int)inside_limit_u > 0 && (int)inside_limit_v > 0; - outside_min_u_ = -0.5; - outside_min_v_ = -0.5; - outside_max_u_ = lu - 0.5; - outside_max_v_ = lv - 0.5; - - int colorCount = palette->getStyleCount(); - colorCount = std::max({colorCount, TPixelCM32::getMaxInk(), TPixelCM32::getMaxPaint()}); - - std::vector paints(colorCount); - std::vector inks(colorCount); - for (i = 0; i < palette->getStyleCount(); i++) - paints[i] = inks[i] = ::premultiply(palette->getStyle(i)->getAverageColor()); - - for (out_y = 0, out_y_ = 0.0; out_y < ly; out_y++, out_y_ += 1.0) { - for (out_x = 0, out_x_ = 0.0; out_x < lx; out_x++, out_x_ += 1.0) { - pix_out = buffer_out + out_y * wrap_out + out_x; - - out_u_ = affMV1(aff_xy2uv, out_x_, out_y_); - out_v_ = affMV2(aff_xy2uv, out_x_, out_y_); - ref_u = intLE(out_u_); - ref_v = intLE(out_v_); - - if (inside_nonempty && - (UINT)(ref_u - inside_offset_u) < inside_limit_u && - (UINT)(ref_v - inside_offset_v) < inside_limit_v) { - calc_value = calc[(ref_u >> 3) + ref_v * calc_bytewrap]; - if (calc_value && ((calc_value >> (ref_u & 7)) & 1)) { - ref_out_u_ = ref_u - out_u_; - ref_out_v_ = ref_v - out_v_; - ref_out_f_ = aff0MV1(aff0_uv2fg, ref_out_u_, ref_out_v_); - ref_out_g_ = aff0MV2(aff0_uv2fg, ref_out_u_, ref_out_v_); - ref_out_f = tround(ref_out_f_); - ref_out_g = tround(ref_out_g_); - sum_weights = 0; - sum_contribs_r = 0; - sum_contribs_g = 0; - sum_contribs_b = 0; - sum_contribs_m = 0; - for (i = n_pix - 1; i >= 0; i--) { - pix_out_f = pix_ref_f[i] + ref_out_f; - pix_out_g = pix_ref_g[i] + ref_out_g; - weight = (float)((filter[pix_out_f] * filter[pix_out_g]) >> 16); - pix_u = pix_ref_u[i] + ref_u; - pix_v = pix_ref_v[i] + ref_v; - - int pix_in_pos = pix_u + pix_v * wrap_in; - int tone = buffer_in[pix_in_pos].getTone(); - int paint = buffer_in[pix_in_pos].getPaint(); - int ink = buffer_in[pix_in_pos].getInk(); - - if (tone == TPixelCM32::getMaxTone()) - pix_value = Converter::convert(paints[paint]); - else if (tone == 0) - pix_value = Converter::convert(inks[ink]); - else - pix_value = Converter::convert( - blend(inks[ink], paints[paint], tone, TPixelCM32::getMaxTone())); - - sum_contribs_r += (int)pix_value.r * weight; - sum_contribs_g += (int)pix_value.g * weight; - sum_contribs_b += (int)pix_value.b * weight; - sum_contribs_m += (int)pix_value.m * weight; - sum_weights += weight; - } - inv_sum_weights = 1.0 / sum_weights; - out_fval_r = sum_contribs_r * inv_sum_weights; - out_fval_g = sum_contribs_g * inv_sum_weights; - out_fval_b = sum_contribs_b * inv_sum_weights; - out_fval_m = sum_contribs_m * inv_sum_weights; - notLessThan(0.0, out_fval_r); - notLessThan(0.0, out_fval_g); - notLessThan(0.0, out_fval_b); - notLessThan(0.0, out_fval_m); - out_value_r = troundp(out_fval_r); - out_value_g = troundp(out_fval_g); - out_value_b = troundp(out_fval_b); - out_value_m = troundp(out_fval_m); - notMoreThan(T::maxChannelValue, out_value_r); - notMoreThan(T::maxChannelValue, out_value_g); - notMoreThan(T::maxChannelValue, out_value_b); - notMoreThan(T::maxChannelValue, out_value_m); - - pix_out->r = out_value_r; - pix_out->g = out_value_g; - pix_out->b = out_value_b; - pix_out->m = out_value_m; - - } else { - // *pix_out = buffer_in[ref_u + ref_v * wrap_in]; - - int pix_in_pos = ref_u + ref_v * wrap_in; - int tone = buffer_in[pix_in_pos].getTone(); - int paint = buffer_in[pix_in_pos].getPaint(); - int ink = buffer_in[pix_in_pos].getInk(); - - if (tone == TPixelCM32::getMaxTone()) - *pix_out = Converter::convert(paints[paint]); - else if (tone == 0) - *pix_out = Converter::convert(inks[ink]); - else - *pix_out = Converter::convert(blend(inks[ink], paints[paint], tone, TPixelCM32::getMaxTone())); - } - } else if (outside_min_u_ <= out_u_ && out_u_ <= outside_max_u_ && - outside_min_v_ <= out_v_ && out_v_ <= outside_max_v_) { - if ((UINT)ref_u >= (UINT)lu || (UINT)ref_v >= (UINT)lv) - must_calc = true; - else { - calc_value = calc[(ref_u >> 3) + ref_v * calc_bytewrap]; - must_calc = calc_value && ((calc_value >> (ref_u & 7)) & 1); - } - if (must_calc) { - ref_out_u_ = ref_u - out_u_; - ref_out_v_ = ref_v - out_v_; - ref_out_f_ = aff0MV1(aff0_uv2fg, ref_out_u_, ref_out_v_); - ref_out_g_ = aff0MV2(aff0_uv2fg, ref_out_u_, ref_out_v_); - ref_out_f = tround(ref_out_f_); - ref_out_g = tround(ref_out_g_); - sum_weights = 0; - sum_contribs_r = 0; - sum_contribs_g = 0; - sum_contribs_b = 0; - sum_contribs_m = 0; - for (i = n_pix - 1; i >= 0; i--) { - pix_out_f = pix_ref_f[i] + ref_out_f; - pix_out_g = pix_ref_g[i] + ref_out_g; - weight = (float)((filter[pix_out_f] * filter[pix_out_g]) >> 16); - pix_u = pix_ref_u[i] + ref_u; - pix_v = pix_ref_v[i] + ref_v; - notLessThan(0, pix_u); - notLessThan(0, pix_v); - notMoreThan(mu, pix_u); - notMoreThan(mv, pix_v); - - // pix_value = buffer_in[pix_u + pix_v * wrap_in]; - - int pix_in_pos = pix_u + pix_v * wrap_in; - int tone = buffer_in[pix_in_pos].getTone(); - int paint = buffer_in[pix_in_pos].getPaint(); - int ink = buffer_in[pix_in_pos].getInk(); - - if (tone == TPixelCM32::getMaxTone()) - pix_value = Converter::convert(paints[paint]); - else if (tone == 0) - pix_value = Converter::convert(inks[ink]); - else - pix_value = Converter::convert( - blend(inks[ink], paints[paint], tone, TPixelCM32::getMaxTone())); - - sum_contribs_r += (int)pix_value.r * weight; - sum_contribs_g += (int)pix_value.g * weight; - sum_contribs_b += (int)pix_value.b * weight; - sum_contribs_m += (int)pix_value.m * weight; - sum_weights += weight; - } - - inv_sum_weights = 1.0 / sum_weights; - out_fval_r = sum_contribs_r * inv_sum_weights; - out_fval_g = sum_contribs_g * inv_sum_weights; - out_fval_b = sum_contribs_b * inv_sum_weights; - out_fval_m = sum_contribs_m * inv_sum_weights; - notLessThan(0.0, out_fval_r); - notLessThan(0.0, out_fval_g); - notLessThan(0.0, out_fval_b); - notLessThan(0.0, out_fval_m); - out_value_r = troundp(out_fval_r); - out_value_g = troundp(out_fval_g); - out_value_b = troundp(out_fval_b); - out_value_m = troundp(out_fval_m); - notMoreThan(T::maxChannelValue, out_value_r); - notMoreThan(T::maxChannelValue, out_value_g); - notMoreThan(T::maxChannelValue, out_value_b); - notMoreThan(T::maxChannelValue, out_value_m); - pix_out->r = out_value_r; - pix_out->g = out_value_g; - pix_out->b = out_value_b; - pix_out->m = out_value_m; - } else { - int pix_in_pos = ref_u + ref_v * wrap_in; - int tone = buffer_in[pix_in_pos].getTone(); - int paint = buffer_in[pix_in_pos].getPaint(); - int ink = buffer_in[pix_in_pos].getInk(); - - if (tone == TPixelCM32::getMaxTone()) - *pix_out = Converter::convert(paints[paint]); - else if (tone == 0) - *pix_out = Converter::convert(inks[ink]); - else - *pix_out = Converter::convert( - blend(inks[ink], paints[paint], tone, TPixelCM32::getMaxTone())); - } - } else { - *pix_out = default_value; - } - } - } - - if (calc) - delete[] calc; + T *pix_out; + + default_value.r = 0; + default_value.g = 0; + default_value.b = 0; + default_value.m = 0; + + if (!(rout->getLx() > 0 && rout->getLy() > 0)) return; + if (!(rin->getLx() > 0 && rin->getLy() > 0)) { + rout->clear(); + return; + } + + calc = 0; + calc_allocsize = 0; + create_calc(rin, min_pix_ref_u, max_pix_ref_u, min_pix_ref_v, max_pix_ref_v, + calc, calc_allocsize, calc_bytewrap); + + buffer_in = rin->pixels(); + buffer_out = rout->pixels(); + lu = rin->getLx(); + lx = rout->getLx(); + lv = rin->getLy(); + ly = rout->getLy(); + wrap_in = rin->getWrap(); + wrap_out = rout->getWrap(); + mu = lu - 1; + mv = lv - 1; + + inside_offset_u = -min_pix_ref_u; + inside_offset_v = -min_pix_ref_v; + inside_limit_u = lu - max_pix_ref_u - inside_offset_u; + inside_limit_v = lv - max_pix_ref_v - inside_offset_v; + inside_nonempty = (int)inside_limit_u > 0 && (int)inside_limit_v > 0; + outside_min_u_ = -0.5; + outside_min_v_ = -0.5; + outside_max_u_ = lu - 0.5; + outside_max_v_ = lv - 0.5; + + int colorCount = palette->getStyleCount(); + colorCount = std::max( + {colorCount, TPixelCM32::getMaxInk(), TPixelCM32::getMaxPaint()}); + + std::vector paints(colorCount); + std::vector inks(colorCount); + for (i = 0; i < palette->getStyleCount(); i++) + paints[i] = inks[i] = + ::premultiply(palette->getStyle(i)->getAverageColor()); + + for (out_y = 0, out_y_ = 0.0; out_y < ly; out_y++, out_y_ += 1.0) { + for (out_x = 0, out_x_ = 0.0; out_x < lx; out_x++, out_x_ += 1.0) { + pix_out = buffer_out + out_y * wrap_out + out_x; + + out_u_ = affMV1(aff_xy2uv, out_x_, out_y_); + out_v_ = affMV2(aff_xy2uv, out_x_, out_y_); + ref_u = intLE(out_u_); + ref_v = intLE(out_v_); + + if (inside_nonempty && (UINT)(ref_u - inside_offset_u) < inside_limit_u && + (UINT)(ref_v - inside_offset_v) < inside_limit_v) { + calc_value = calc[(ref_u >> 3) + ref_v * calc_bytewrap]; + if (calc_value && ((calc_value >> (ref_u & 7)) & 1)) { + ref_out_u_ = ref_u - out_u_; + ref_out_v_ = ref_v - out_v_; + ref_out_f_ = aff0MV1(aff0_uv2fg, ref_out_u_, ref_out_v_); + ref_out_g_ = aff0MV2(aff0_uv2fg, ref_out_u_, ref_out_v_); + ref_out_f = tround(ref_out_f_); + ref_out_g = tround(ref_out_g_); + sum_weights = 0; + sum_contribs_r = 0; + sum_contribs_g = 0; + sum_contribs_b = 0; + sum_contribs_m = 0; + for (i = n_pix - 1; i >= 0; i--) { + pix_out_f = pix_ref_f[i] + ref_out_f; + pix_out_g = pix_ref_g[i] + ref_out_g; + weight = (float)((filter[pix_out_f] * filter[pix_out_g]) >> 16); + pix_u = pix_ref_u[i] + ref_u; + pix_v = pix_ref_v[i] + ref_v; + + int pix_in_pos = pix_u + pix_v * wrap_in; + int tone = buffer_in[pix_in_pos].getTone(); + int paint = buffer_in[pix_in_pos].getPaint(); + int ink = buffer_in[pix_in_pos].getInk(); + + if (tone == TPixelCM32::getMaxTone()) + pix_value = Converter::convert(paints[paint]); + else if (tone == 0) + pix_value = Converter::convert(inks[ink]); + else + pix_value = Converter::convert(blend( + inks[ink], paints[paint], tone, TPixelCM32::getMaxTone())); + + sum_contribs_r += (int)pix_value.r * weight; + sum_contribs_g += (int)pix_value.g * weight; + sum_contribs_b += (int)pix_value.b * weight; + sum_contribs_m += (int)pix_value.m * weight; + sum_weights += weight; + } + inv_sum_weights = 1.0 / sum_weights; + out_fval_r = sum_contribs_r * inv_sum_weights; + out_fval_g = sum_contribs_g * inv_sum_weights; + out_fval_b = sum_contribs_b * inv_sum_weights; + out_fval_m = sum_contribs_m * inv_sum_weights; + notLessThan(0.0, out_fval_r); + notLessThan(0.0, out_fval_g); + notLessThan(0.0, out_fval_b); + notLessThan(0.0, out_fval_m); + out_value_r = troundp(out_fval_r); + out_value_g = troundp(out_fval_g); + out_value_b = troundp(out_fval_b); + out_value_m = troundp(out_fval_m); + notMoreThan(T::maxChannelValue, out_value_r); + notMoreThan(T::maxChannelValue, out_value_g); + notMoreThan(T::maxChannelValue, out_value_b); + notMoreThan(T::maxChannelValue, out_value_m); + + pix_out->r = out_value_r; + pix_out->g = out_value_g; + pix_out->b = out_value_b; + pix_out->m = out_value_m; + + } else { + // *pix_out = buffer_in[ref_u + ref_v * wrap_in]; + + int pix_in_pos = ref_u + ref_v * wrap_in; + int tone = buffer_in[pix_in_pos].getTone(); + int paint = buffer_in[pix_in_pos].getPaint(); + int ink = buffer_in[pix_in_pos].getInk(); + + if (tone == TPixelCM32::getMaxTone()) + *pix_out = Converter::convert(paints[paint]); + else if (tone == 0) + *pix_out = Converter::convert(inks[ink]); + else + *pix_out = Converter::convert(blend( + inks[ink], paints[paint], tone, TPixelCM32::getMaxTone())); + } + } else if (outside_min_u_ <= out_u_ && out_u_ <= outside_max_u_ && + outside_min_v_ <= out_v_ && out_v_ <= outside_max_v_) { + if ((UINT)ref_u >= (UINT)lu || (UINT)ref_v >= (UINT)lv) + must_calc = true; + else { + calc_value = calc[(ref_u >> 3) + ref_v * calc_bytewrap]; + must_calc = calc_value && ((calc_value >> (ref_u & 7)) & 1); + } + if (must_calc) { + ref_out_u_ = ref_u - out_u_; + ref_out_v_ = ref_v - out_v_; + ref_out_f_ = aff0MV1(aff0_uv2fg, ref_out_u_, ref_out_v_); + ref_out_g_ = aff0MV2(aff0_uv2fg, ref_out_u_, ref_out_v_); + ref_out_f = tround(ref_out_f_); + ref_out_g = tround(ref_out_g_); + sum_weights = 0; + sum_contribs_r = 0; + sum_contribs_g = 0; + sum_contribs_b = 0; + sum_contribs_m = 0; + for (i = n_pix - 1; i >= 0; i--) { + pix_out_f = pix_ref_f[i] + ref_out_f; + pix_out_g = pix_ref_g[i] + ref_out_g; + weight = (float)((filter[pix_out_f] * filter[pix_out_g]) >> 16); + pix_u = pix_ref_u[i] + ref_u; + pix_v = pix_ref_v[i] + ref_v; + notLessThan(0, pix_u); + notLessThan(0, pix_v); + notMoreThan(mu, pix_u); + notMoreThan(mv, pix_v); + + // pix_value = buffer_in[pix_u + pix_v * wrap_in]; + + int pix_in_pos = pix_u + pix_v * wrap_in; + int tone = buffer_in[pix_in_pos].getTone(); + int paint = buffer_in[pix_in_pos].getPaint(); + int ink = buffer_in[pix_in_pos].getInk(); + + if (tone == TPixelCM32::getMaxTone()) + pix_value = Converter::convert(paints[paint]); + else if (tone == 0) + pix_value = Converter::convert(inks[ink]); + else + pix_value = Converter::convert(blend( + inks[ink], paints[paint], tone, TPixelCM32::getMaxTone())); + + sum_contribs_r += (int)pix_value.r * weight; + sum_contribs_g += (int)pix_value.g * weight; + sum_contribs_b += (int)pix_value.b * weight; + sum_contribs_m += (int)pix_value.m * weight; + sum_weights += weight; + } + + inv_sum_weights = 1.0 / sum_weights; + out_fval_r = sum_contribs_r * inv_sum_weights; + out_fval_g = sum_contribs_g * inv_sum_weights; + out_fval_b = sum_contribs_b * inv_sum_weights; + out_fval_m = sum_contribs_m * inv_sum_weights; + notLessThan(0.0, out_fval_r); + notLessThan(0.0, out_fval_g); + notLessThan(0.0, out_fval_b); + notLessThan(0.0, out_fval_m); + out_value_r = troundp(out_fval_r); + out_value_g = troundp(out_fval_g); + out_value_b = troundp(out_fval_b); + out_value_m = troundp(out_fval_m); + notMoreThan(T::maxChannelValue, out_value_r); + notMoreThan(T::maxChannelValue, out_value_g); + notMoreThan(T::maxChannelValue, out_value_b); + notMoreThan(T::maxChannelValue, out_value_m); + pix_out->r = out_value_r; + pix_out->g = out_value_g; + pix_out->b = out_value_b; + pix_out->m = out_value_m; + } else { + int pix_in_pos = ref_u + ref_v * wrap_in; + int tone = buffer_in[pix_in_pos].getTone(); + int paint = buffer_in[pix_in_pos].getPaint(); + int ink = buffer_in[pix_in_pos].getInk(); + + if (tone == TPixelCM32::getMaxTone()) + *pix_out = Converter::convert(paints[paint]); + else if (tone == 0) + *pix_out = Converter::convert(inks[ink]); + else + *pix_out = Converter::convert(blend( + inks[ink], paints[paint], tone, TPixelCM32::getMaxTone())); + } + } else { + *pix_out = default_value; + } + } + } + + if (calc) delete[] calc; } } @@ -3866,961 +3777,926 @@ void resample_main_cm32_rgbm_bigradius(TRasterPT rout, const TRasterCM32P &ri template void resample_main_cm32_rgbm(TRasterPT rout, const TRasterCM32P &rin, - const TAffine &aff_xy2uv, - const TAffine &aff0_uv2fg, - int min_pix_ref_u, int min_pix_ref_v, - int max_pix_ref_u, int max_pix_ref_v, - int n_pix, - int *pix_ref_u, int *pix_ref_v, - int *pix_ref_f, int *pix_ref_g, - short *filter, - TPalette *palette) -{ - const TPixelCM32 *buffer_in; - T *buffer_out; - int lu, lv, wrap_in, mu, mv; - int lx, ly, wrap_out; - int out_x, out_y; - double out_x_, out_y_; - double out_u_, out_v_; - int ref_u, ref_v; - int pix_u, pix_v; - double ref_out_u_, ref_out_v_; - double ref_out_f_, ref_out_g_; - int ref_out_f, ref_out_g; - int pix_out_f, pix_out_g; - int inside_offset_u, inside_offset_v; - UINT inside_limit_u, inside_limit_v; - int inside_nonempty; - double outside_min_u_, outside_min_v_; - double outside_max_u_, outside_max_v_; - UCHAR *calc; - int calc_allocsize; - int calc_bytewrap; - UCHAR calc_value; - bool must_calc; - T pix_value; - T default_value(0, 0, 0, 0); - int weight; - int sum_weights; - double inv_sum_weights; - int sum_contribs_r, sum_contribs_g, sum_contribs_b, sum_contribs_m; - double out_fval_r, out_fval_g, out_fval_b, out_fval_m; - int out_value_r, out_value_g, out_value_b, out_value_m; - T out_value; - int i; + const TAffine &aff_xy2uv, + const TAffine &aff0_uv2fg, int min_pix_ref_u, + int min_pix_ref_v, int max_pix_ref_u, + int max_pix_ref_v, int n_pix, int *pix_ref_u, + int *pix_ref_v, int *pix_ref_f, int *pix_ref_g, + short *filter, TPalette *palette) { + const TPixelCM32 *buffer_in; + T *buffer_out; + int lu, lv, wrap_in, mu, mv; + int lx, ly, wrap_out; + int out_x, out_y; + double out_x_, out_y_; + double out_u_, out_v_; + int ref_u, ref_v; + int pix_u, pix_v; + double ref_out_u_, ref_out_v_; + double ref_out_f_, ref_out_g_; + int ref_out_f, ref_out_g; + int pix_out_f, pix_out_g; + int inside_offset_u, inside_offset_v; + UINT inside_limit_u, inside_limit_v; + int inside_nonempty; + double outside_min_u_, outside_min_v_; + double outside_max_u_, outside_max_v_; + UCHAR *calc; + int calc_allocsize; + int calc_bytewrap; + UCHAR calc_value; + bool must_calc; + T pix_value; + T default_value(0, 0, 0, 0); + int weight; + int sum_weights; + double inv_sum_weights; + int sum_contribs_r, sum_contribs_g, sum_contribs_b, sum_contribs_m; + double out_fval_r, out_fval_g, out_fval_b, out_fval_m; + int out_value_r, out_value_g, out_value_b, out_value_m; + T out_value; + int i; #ifdef USE_DOUBLE_TO_INT - double d2iaux; + double d2iaux; #endif - if (n_pix >= 512 || T::maxChannelValue > 255) { - resample_main_cm32_rgbm_bigradius(rout, rin, - aff_xy2uv, - aff0_uv2fg, - min_pix_ref_u, min_pix_ref_v, - max_pix_ref_u, max_pix_ref_v, - n_pix, - pix_ref_u, pix_ref_v, - pix_ref_f, pix_ref_g, - filter, palette); - return; - } - - if (!(rout->getLx() > 0 && rout->getLy() > 0)) - return; - - if (!(rin->getLx() > 0 && rin->getLy() > 0)) { - resample_clear_rgbm(rout, default_value); - return; - } - calc = 0; - calc_allocsize = 0; - create_calc(rin, min_pix_ref_u, max_pix_ref_u, - min_pix_ref_v, max_pix_ref_v, - calc, calc_allocsize, calc_bytewrap); - - buffer_in = rin->pixels(); - buffer_out = rout->pixels(); - lu = rin->getLx(); - lx = rout->getLx(); - lv = rin->getLy(); - ly = rout->getLy(); - wrap_in = rin->getWrap(); - wrap_out = rout->getWrap(); - mu = lu - 1; - mv = lv - 1; - - inside_offset_u = -min_pix_ref_u; - inside_offset_v = -min_pix_ref_v; - inside_limit_u = lu - max_pix_ref_u - inside_offset_u; - inside_limit_v = lv - max_pix_ref_v - inside_offset_v; - inside_nonempty = (int)inside_limit_u > 0 && (int)inside_limit_v > 0; - outside_min_u_ = -0.5; - outside_min_v_ = -0.5; - outside_max_u_ = lu - 0.5; - outside_max_v_ = lv - 0.5; - - int colorCount = palette->getStyleCount(); - colorCount = std::max({colorCount, TPixelCM32::getMaxInk(), TPixelCM32::getMaxPaint()}); - - std::vector paints(colorCount); - std::vector inks(colorCount); - for (i = 0; i < palette->getStyleCount(); i++) - paints[i] = inks[i] = ::premultiply(palette->getStyle(i)->getAverageColor()); - - for (out_y = 0, out_y_ = 0.0; out_y < ly; out_y++, out_y_ += 1.0) { - for (out_x = 0, out_x_ = 0.0; out_x < lx; out_x++, out_x_ += 1.0) { - out_u_ = affMV1(aff_xy2uv, out_x_, out_y_); - out_v_ = affMV2(aff_xy2uv, out_x_, out_y_); - ref_u = intLE(out_u_); - ref_v = intLE(out_v_); - - if (inside_nonempty && - (UINT)(ref_u - inside_offset_u) < inside_limit_u && - (UINT)(ref_v - inside_offset_v) < inside_limit_v) { - calc_value = calc[(ref_u >> 3) + ref_v * calc_bytewrap]; - if (calc_value && ((calc_value >> (ref_u & 7)) & 1)) { - ref_out_u_ = ref_u - out_u_; - ref_out_v_ = ref_v - out_v_; - ref_out_f_ = aff0MV1(aff0_uv2fg, ref_out_u_, ref_out_v_); - ref_out_g_ = aff0MV2(aff0_uv2fg, ref_out_u_, ref_out_v_); - ref_out_f = tround(ref_out_f_); - ref_out_g = tround(ref_out_g_); - sum_weights = 0; - sum_contribs_r = 0; - sum_contribs_g = 0; - sum_contribs_b = 0; - sum_contribs_m = 0; - for (i = n_pix - 1; i >= 0; i--) { - pix_out_f = pix_ref_f[i] + ref_out_f; - pix_out_g = pix_ref_g[i] + ref_out_g; - weight = (filter[pix_out_f] * filter[pix_out_g]) >> 16; - pix_u = pix_ref_u[i] + ref_u; - pix_v = pix_ref_v[i] + ref_v; - - // pix_value = buffer_in[pix_u + pix_v * wrap_in]; - - int pix_in_pos = pix_u + pix_v * wrap_in; - int tone = buffer_in[pix_in_pos].getTone(); - int paint = buffer_in[pix_in_pos].getPaint(); - int ink = buffer_in[pix_in_pos].getInk(); - - if (tone == TPixelCM32::getMaxTone()) - pix_value = Converter::convert(paints[paint]); - else if (tone == 0) - pix_value = Converter::convert(inks[ink]); - else - pix_value = Converter::convert( - blend(inks[ink], paints[paint], tone, TPixelCM32::getMaxTone())); - - sum_contribs_r += (int)pix_value.r * weight; - sum_contribs_g += (int)pix_value.g * weight; - sum_contribs_b += (int)pix_value.b * weight; - sum_contribs_m += (int)pix_value.m * weight; - sum_weights += weight; - } - - inv_sum_weights = 1.0 / sum_weights; - out_fval_r = sum_contribs_r * inv_sum_weights; - out_fval_g = sum_contribs_g * inv_sum_weights; - out_fval_b = sum_contribs_b * inv_sum_weights; - out_fval_m = sum_contribs_m * inv_sum_weights; - notLessThan(0.0, out_fval_r); - notLessThan(0.0, out_fval_g); - notLessThan(0.0, out_fval_b); - notLessThan(0.0, out_fval_m); - out_value_r = troundp(out_fval_r); - out_value_g = troundp(out_fval_g); - out_value_b = troundp(out_fval_b); - out_value_m = troundp(out_fval_m); - notMoreThan(T::maxChannelValue, out_value_r); - notMoreThan(T::maxChannelValue, out_value_g); - notMoreThan(T::maxChannelValue, out_value_b); - notMoreThan(T::maxChannelValue, out_value_m); - out_value.r = out_value_r; - out_value.g = out_value_g; - out_value.b = out_value_b; - out_value.m = out_value_m; - } else { - // out_value = buffer_in[ref_u + ref_v * wrap_in]; - int pix_in_pos = ref_u + ref_v * wrap_in; - int tone = buffer_in[pix_in_pos].getTone(); - int paint = buffer_in[pix_in_pos].getPaint(); - int ink = buffer_in[pix_in_pos].getInk(); - - if (tone == TPixelCM32::getMaxTone()) - out_value = Converter::convert(paints[paint]); - else if (tone == 0) - out_value = Converter::convert(inks[ink]); - else - out_value = Converter::convert( - blend(inks[ink], paints[paint], tone, TPixelCM32::getMaxTone())); - } - } else if (outside_min_u_ <= out_u_ && out_u_ <= outside_max_u_ && - outside_min_v_ <= out_v_ && out_v_ <= outside_max_v_) { - if ((UINT)ref_u >= (UINT)lu || (UINT)ref_v >= (UINT)lv) - must_calc = true; - else { - calc_value = calc[(ref_u >> 3) + ref_v * calc_bytewrap]; - must_calc = calc_value && ((calc_value >> (ref_u & 7)) & 1); - } - - if (must_calc) { - ref_out_u_ = ref_u - out_u_; - ref_out_v_ = ref_v - out_v_; - ref_out_f_ = aff0MV1(aff0_uv2fg, ref_out_u_, ref_out_v_); - ref_out_g_ = aff0MV2(aff0_uv2fg, ref_out_u_, ref_out_v_); - ref_out_f = tround(ref_out_f_); - ref_out_g = tround(ref_out_g_); - sum_weights = 0; - sum_contribs_r = 0; - sum_contribs_g = 0; - sum_contribs_b = 0; - sum_contribs_m = 0; - - for (i = n_pix - 1; i >= 0; i--) { - pix_out_f = pix_ref_f[i] + ref_out_f; - pix_out_g = pix_ref_g[i] + ref_out_g; - weight = (filter[pix_out_f] * filter[pix_out_g]) >> 16; - pix_u = pix_ref_u[i] + ref_u; - pix_v = pix_ref_v[i] + ref_v; - notLessThan(0, pix_u); - notLessThan(0, pix_v); - notMoreThan(mu, pix_u); - notMoreThan(mv, pix_v); - - // pix_value = buffer_in[pix_u + pix_v * wrap_in]; - - int pix_in_pos = pix_u + pix_v * wrap_in; - int tone = buffer_in[pix_in_pos].getTone(); - int paint = buffer_in[pix_in_pos].getPaint(); - int ink = buffer_in[pix_in_pos].getInk(); - - if (tone == TPixelCM32::getMaxTone()) - pix_value = Converter::convert(paints[paint]); - else if (tone == 0) - pix_value = Converter::convert(inks[ink]); - else - pix_value = Converter::convert( - blend(inks[ink], paints[paint], tone, TPixelCM32::getMaxTone())); - - sum_contribs_r += (int)pix_value.r * weight; - sum_contribs_g += (int)pix_value.g * weight; - sum_contribs_b += (int)pix_value.b * weight; - sum_contribs_m += (int)pix_value.m * weight; - sum_weights += weight; - } - - inv_sum_weights = 1.0 / sum_weights; - out_fval_r = sum_contribs_r * inv_sum_weights; - out_fval_g = sum_contribs_g * inv_sum_weights; - out_fval_b = sum_contribs_b * inv_sum_weights; - out_fval_m = sum_contribs_m * inv_sum_weights; - notLessThan(0.0, out_fval_r); - notLessThan(0.0, out_fval_g); - notLessThan(0.0, out_fval_b); - notLessThan(0.0, out_fval_m); - out_value_r = troundp(out_fval_r); - out_value_g = troundp(out_fval_g); - out_value_b = troundp(out_fval_b); - out_value_m = troundp(out_fval_m); - notMoreThan(T::maxChannelValue, out_value_r); - notMoreThan(T::maxChannelValue, out_value_g); - notMoreThan(T::maxChannelValue, out_value_b); - notMoreThan(T::maxChannelValue, out_value_m); - out_value.r = out_value_r; - out_value.g = out_value_g; - out_value.b = out_value_b; - out_value.m = out_value_m; - } else { - // out_value = buffer_in[ref_u + ref_v * wrap_in]; - - int pix_in_pos = ref_u + ref_v * wrap_in; - int tone = buffer_in[pix_in_pos].getTone(); - int paint = buffer_in[pix_in_pos].getPaint(); - int ink = buffer_in[pix_in_pos].getInk(); - - if (tone == TPixelCM32::getMaxTone()) - out_value = Converter::convert(paints[paint]); - else if (tone == 0) - out_value = Converter::convert(inks[ink]); - else - out_value = Converter::convert( - blend(inks[ink], paints[paint], tone, TPixelCM32::getMaxTone())); - } - } else { - out_value = default_value; - } - - buffer_out[out_x + out_y * wrap_out] = out_value; - } - } - - if (calc) - delete[] calc; + if (n_pix >= 512 || T::maxChannelValue > 255) { + resample_main_cm32_rgbm_bigradius( + rout, rin, aff_xy2uv, aff0_uv2fg, min_pix_ref_u, min_pix_ref_v, + max_pix_ref_u, max_pix_ref_v, n_pix, pix_ref_u, pix_ref_v, pix_ref_f, + pix_ref_g, filter, palette); + return; + } + + if (!(rout->getLx() > 0 && rout->getLy() > 0)) return; + + if (!(rin->getLx() > 0 && rin->getLy() > 0)) { + resample_clear_rgbm(rout, default_value); + return; + } + calc = 0; + calc_allocsize = 0; + create_calc(rin, min_pix_ref_u, max_pix_ref_u, min_pix_ref_v, max_pix_ref_v, + calc, calc_allocsize, calc_bytewrap); + + buffer_in = rin->pixels(); + buffer_out = rout->pixels(); + lu = rin->getLx(); + lx = rout->getLx(); + lv = rin->getLy(); + ly = rout->getLy(); + wrap_in = rin->getWrap(); + wrap_out = rout->getWrap(); + mu = lu - 1; + mv = lv - 1; + + inside_offset_u = -min_pix_ref_u; + inside_offset_v = -min_pix_ref_v; + inside_limit_u = lu - max_pix_ref_u - inside_offset_u; + inside_limit_v = lv - max_pix_ref_v - inside_offset_v; + inside_nonempty = (int)inside_limit_u > 0 && (int)inside_limit_v > 0; + outside_min_u_ = -0.5; + outside_min_v_ = -0.5; + outside_max_u_ = lu - 0.5; + outside_max_v_ = lv - 0.5; + + int colorCount = palette->getStyleCount(); + colorCount = std::max( + {colorCount, TPixelCM32::getMaxInk(), TPixelCM32::getMaxPaint()}); + + std::vector paints(colorCount); + std::vector inks(colorCount); + for (i = 0; i < palette->getStyleCount(); i++) + paints[i] = inks[i] = + ::premultiply(palette->getStyle(i)->getAverageColor()); + + for (out_y = 0, out_y_ = 0.0; out_y < ly; out_y++, out_y_ += 1.0) { + for (out_x = 0, out_x_ = 0.0; out_x < lx; out_x++, out_x_ += 1.0) { + out_u_ = affMV1(aff_xy2uv, out_x_, out_y_); + out_v_ = affMV2(aff_xy2uv, out_x_, out_y_); + ref_u = intLE(out_u_); + ref_v = intLE(out_v_); + + if (inside_nonempty && (UINT)(ref_u - inside_offset_u) < inside_limit_u && + (UINT)(ref_v - inside_offset_v) < inside_limit_v) { + calc_value = calc[(ref_u >> 3) + ref_v * calc_bytewrap]; + if (calc_value && ((calc_value >> (ref_u & 7)) & 1)) { + ref_out_u_ = ref_u - out_u_; + ref_out_v_ = ref_v - out_v_; + ref_out_f_ = aff0MV1(aff0_uv2fg, ref_out_u_, ref_out_v_); + ref_out_g_ = aff0MV2(aff0_uv2fg, ref_out_u_, ref_out_v_); + ref_out_f = tround(ref_out_f_); + ref_out_g = tround(ref_out_g_); + sum_weights = 0; + sum_contribs_r = 0; + sum_contribs_g = 0; + sum_contribs_b = 0; + sum_contribs_m = 0; + for (i = n_pix - 1; i >= 0; i--) { + pix_out_f = pix_ref_f[i] + ref_out_f; + pix_out_g = pix_ref_g[i] + ref_out_g; + weight = (filter[pix_out_f] * filter[pix_out_g]) >> 16; + pix_u = pix_ref_u[i] + ref_u; + pix_v = pix_ref_v[i] + ref_v; + + // pix_value = buffer_in[pix_u + pix_v * wrap_in]; + + int pix_in_pos = pix_u + pix_v * wrap_in; + int tone = buffer_in[pix_in_pos].getTone(); + int paint = buffer_in[pix_in_pos].getPaint(); + int ink = buffer_in[pix_in_pos].getInk(); + + if (tone == TPixelCM32::getMaxTone()) + pix_value = Converter::convert(paints[paint]); + else if (tone == 0) + pix_value = Converter::convert(inks[ink]); + else + pix_value = Converter::convert(blend( + inks[ink], paints[paint], tone, TPixelCM32::getMaxTone())); + + sum_contribs_r += (int)pix_value.r * weight; + sum_contribs_g += (int)pix_value.g * weight; + sum_contribs_b += (int)pix_value.b * weight; + sum_contribs_m += (int)pix_value.m * weight; + sum_weights += weight; + } + + inv_sum_weights = 1.0 / sum_weights; + out_fval_r = sum_contribs_r * inv_sum_weights; + out_fval_g = sum_contribs_g * inv_sum_weights; + out_fval_b = sum_contribs_b * inv_sum_weights; + out_fval_m = sum_contribs_m * inv_sum_weights; + notLessThan(0.0, out_fval_r); + notLessThan(0.0, out_fval_g); + notLessThan(0.0, out_fval_b); + notLessThan(0.0, out_fval_m); + out_value_r = troundp(out_fval_r); + out_value_g = troundp(out_fval_g); + out_value_b = troundp(out_fval_b); + out_value_m = troundp(out_fval_m); + notMoreThan(T::maxChannelValue, out_value_r); + notMoreThan(T::maxChannelValue, out_value_g); + notMoreThan(T::maxChannelValue, out_value_b); + notMoreThan(T::maxChannelValue, out_value_m); + out_value.r = out_value_r; + out_value.g = out_value_g; + out_value.b = out_value_b; + out_value.m = out_value_m; + } else { + // out_value = buffer_in[ref_u + ref_v * wrap_in]; + int pix_in_pos = ref_u + ref_v * wrap_in; + int tone = buffer_in[pix_in_pos].getTone(); + int paint = buffer_in[pix_in_pos].getPaint(); + int ink = buffer_in[pix_in_pos].getInk(); + + if (tone == TPixelCM32::getMaxTone()) + out_value = Converter::convert(paints[paint]); + else if (tone == 0) + out_value = Converter::convert(inks[ink]); + else + out_value = Converter::convert(blend( + inks[ink], paints[paint], tone, TPixelCM32::getMaxTone())); + } + } else if (outside_min_u_ <= out_u_ && out_u_ <= outside_max_u_ && + outside_min_v_ <= out_v_ && out_v_ <= outside_max_v_) { + if ((UINT)ref_u >= (UINT)lu || (UINT)ref_v >= (UINT)lv) + must_calc = true; + else { + calc_value = calc[(ref_u >> 3) + ref_v * calc_bytewrap]; + must_calc = calc_value && ((calc_value >> (ref_u & 7)) & 1); + } + + if (must_calc) { + ref_out_u_ = ref_u - out_u_; + ref_out_v_ = ref_v - out_v_; + ref_out_f_ = aff0MV1(aff0_uv2fg, ref_out_u_, ref_out_v_); + ref_out_g_ = aff0MV2(aff0_uv2fg, ref_out_u_, ref_out_v_); + ref_out_f = tround(ref_out_f_); + ref_out_g = tround(ref_out_g_); + sum_weights = 0; + sum_contribs_r = 0; + sum_contribs_g = 0; + sum_contribs_b = 0; + sum_contribs_m = 0; + + for (i = n_pix - 1; i >= 0; i--) { + pix_out_f = pix_ref_f[i] + ref_out_f; + pix_out_g = pix_ref_g[i] + ref_out_g; + weight = (filter[pix_out_f] * filter[pix_out_g]) >> 16; + pix_u = pix_ref_u[i] + ref_u; + pix_v = pix_ref_v[i] + ref_v; + notLessThan(0, pix_u); + notLessThan(0, pix_v); + notMoreThan(mu, pix_u); + notMoreThan(mv, pix_v); + + // pix_value = buffer_in[pix_u + pix_v * wrap_in]; + + int pix_in_pos = pix_u + pix_v * wrap_in; + int tone = buffer_in[pix_in_pos].getTone(); + int paint = buffer_in[pix_in_pos].getPaint(); + int ink = buffer_in[pix_in_pos].getInk(); + + if (tone == TPixelCM32::getMaxTone()) + pix_value = Converter::convert(paints[paint]); + else if (tone == 0) + pix_value = Converter::convert(inks[ink]); + else + pix_value = Converter::convert(blend( + inks[ink], paints[paint], tone, TPixelCM32::getMaxTone())); + + sum_contribs_r += (int)pix_value.r * weight; + sum_contribs_g += (int)pix_value.g * weight; + sum_contribs_b += (int)pix_value.b * weight; + sum_contribs_m += (int)pix_value.m * weight; + sum_weights += weight; + } + + inv_sum_weights = 1.0 / sum_weights; + out_fval_r = sum_contribs_r * inv_sum_weights; + out_fval_g = sum_contribs_g * inv_sum_weights; + out_fval_b = sum_contribs_b * inv_sum_weights; + out_fval_m = sum_contribs_m * inv_sum_weights; + notLessThan(0.0, out_fval_r); + notLessThan(0.0, out_fval_g); + notLessThan(0.0, out_fval_b); + notLessThan(0.0, out_fval_m); + out_value_r = troundp(out_fval_r); + out_value_g = troundp(out_fval_g); + out_value_b = troundp(out_fval_b); + out_value_m = troundp(out_fval_m); + notMoreThan(T::maxChannelValue, out_value_r); + notMoreThan(T::maxChannelValue, out_value_g); + notMoreThan(T::maxChannelValue, out_value_b); + notMoreThan(T::maxChannelValue, out_value_m); + out_value.r = out_value_r; + out_value.g = out_value_g; + out_value.b = out_value_b; + out_value.m = out_value_m; + } else { + // out_value = buffer_in[ref_u + ref_v * wrap_in]; + + int pix_in_pos = ref_u + ref_v * wrap_in; + int tone = buffer_in[pix_in_pos].getTone(); + int paint = buffer_in[pix_in_pos].getPaint(); + int ink = buffer_in[pix_in_pos].getInk(); + + if (tone == TPixelCM32::getMaxTone()) + out_value = Converter::convert(paints[paint]); + else if (tone == 0) + out_value = Converter::convert(inks[ink]); + else + out_value = Converter::convert(blend( + inks[ink], paints[paint], tone, TPixelCM32::getMaxTone())); + } + } else { + out_value = default_value; + } + + buffer_out[out_x + out_y * wrap_out] = out_value; + } + } + + if (calc) delete[] calc; } //--------------------------------------------------------------------------- void resample_cm32_rgbm(TRaster32P rout, const TRasterCM32P &rin, - const TAffine &aff_xy2uv, - const TAffine &aff0_uv2fg, - int min_pix_ref_u, int min_pix_ref_v, - int max_pix_ref_u, int max_pix_ref_v, - int n_pix, - int *pix_ref_u, int *pix_ref_v, - int *pix_ref_f, int *pix_ref_g, - short *filter, TPalette *palette) -{ - const TPixelCM32 *buffer_in; - /*T*/ TPixel32 *buffer_out; - int lu, lv, wrap_in, mu, mv; - int lx, ly, wrap_out; - int out_x, out_y; - double out_x_, out_y_; - double out_u_, out_v_; - int ref_u, ref_v; - int pix_u, pix_v; - double ref_out_u_, ref_out_v_; - double ref_out_f_, ref_out_g_; - int ref_out_f, ref_out_g; - int pix_out_f, pix_out_g; - int inside_offset_u, inside_offset_v; - UINT inside_limit_u, inside_limit_v; - int inside_nonempty; - double outside_min_u_, outside_min_v_; - double outside_max_u_, outside_max_v_; - UCHAR *calc; - int calc_allocsize; - int calc_bytewrap; - UCHAR calc_value; - bool must_calc; - /*T*/ TPixel32 pix_value; - /*T*/ TPixel32 default_value(0, 0, 0, 0); - int weight; - int sum_weights; - double inv_sum_weights; - int sum_contribs_r, sum_contribs_g, sum_contribs_b, sum_contribs_m; - double out_fval_r, out_fval_g, out_fval_b, out_fval_m; - int out_value_r, out_value_g, out_value_b, out_value_m; - /*T*/ TPixel32 out_value; - int i; + const TAffine &aff_xy2uv, const TAffine &aff0_uv2fg, + int min_pix_ref_u, int min_pix_ref_v, int max_pix_ref_u, + int max_pix_ref_v, int n_pix, int *pix_ref_u, + int *pix_ref_v, int *pix_ref_f, int *pix_ref_g, + short *filter, TPalette *palette) { + const TPixelCM32 *buffer_in; + /*T*/ TPixel32 *buffer_out; + int lu, lv, wrap_in, mu, mv; + int lx, ly, wrap_out; + int out_x, out_y; + double out_x_, out_y_; + double out_u_, out_v_; + int ref_u, ref_v; + int pix_u, pix_v; + double ref_out_u_, ref_out_v_; + double ref_out_f_, ref_out_g_; + int ref_out_f, ref_out_g; + int pix_out_f, pix_out_g; + int inside_offset_u, inside_offset_v; + UINT inside_limit_u, inside_limit_v; + int inside_nonempty; + double outside_min_u_, outside_min_v_; + double outside_max_u_, outside_max_v_; + UCHAR *calc; + int calc_allocsize; + int calc_bytewrap; + UCHAR calc_value; + bool must_calc; + /*T*/ TPixel32 pix_value; + /*T*/ TPixel32 default_value(0, 0, 0, 0); + int weight; + int sum_weights; + double inv_sum_weights; + int sum_contribs_r, sum_contribs_g, sum_contribs_b, sum_contribs_m; + double out_fval_r, out_fval_g, out_fval_b, out_fval_m; + int out_value_r, out_value_g, out_value_b, out_value_m; + /*T*/ TPixel32 out_value; + int i; #ifdef USE_DOUBLE_TO_INT - double d2iaux; + double d2iaux; #endif - if (n_pix >= 512 || /*T*/ TPixel32::maxChannelValue > 255) { - assert(false); - /* - resample_main_rgbm_bigradius( rout, rin, - aff_xy2uv, - aff0_uv2fg, - min_pix_ref_u, min_pix_ref_v, - max_pix_ref_u, max_pix_ref_v, - n_pix, - pix_ref_u, pix_ref_v, - pix_ref_f, pix_ref_g, - filter ); - */ - return; - } - - if (!(rout->getLx() > 0 && rout->getLy() > 0)) - return; - - if (!(rin->getLx() > 0 && rin->getLy() > 0)) { - resample_clear_rgbm(rout, default_value); - return; - } - - int colorCount = palette->getStyleCount(); - colorCount = std::max({colorCount, TPixelCM32::getMaxInk(), TPixelCM32::getMaxPaint()}); - - std::vector paints(colorCount); - std::vector inks(colorCount); - for (i = 0; i < palette->getStyleCount(); i++) - paints[i] = inks[i] = ::premultiply(palette->getStyle(i)->getAverageColor()); - - calc = 0; - calc_allocsize = 0; - create_calc(rin, min_pix_ref_u, max_pix_ref_u, - min_pix_ref_v, max_pix_ref_v, - calc, calc_allocsize, calc_bytewrap); - - buffer_in = rin->pixels(); - buffer_out = rout->pixels(); - lu = rin->getLx(); - lx = rout->getLx(); - lv = rin->getLy(); - ly = rout->getLy(); - wrap_in = rin->getWrap(); - wrap_out = rout->getWrap(); - mu = lu - 1; - mv = lv - 1; - - inside_offset_u = -min_pix_ref_u; - inside_offset_v = -min_pix_ref_v; - inside_limit_u = lu - max_pix_ref_u - inside_offset_u; - inside_limit_v = lv - max_pix_ref_v - inside_offset_v; - inside_nonempty = (int)inside_limit_u > 0 && (int)inside_limit_v > 0; - outside_min_u_ = -0.5; - outside_min_v_ = -0.5; - outside_max_u_ = lu - 0.5; - outside_max_v_ = lv - 0.5; - - for (out_y = 0, out_y_ = 0.0; out_y < ly; out_y++, out_y_ += 1.0) { - for (out_x = 0, out_x_ = 0.0; out_x < lx; out_x++, out_x_ += 1.0) { - out_u_ = affMV1(aff_xy2uv, out_x_, out_y_); - out_v_ = affMV2(aff_xy2uv, out_x_, out_y_); - ref_u = intLE(out_u_); - ref_v = intLE(out_v_); - - if (inside_nonempty && - (UINT)(ref_u - inside_offset_u) < inside_limit_u && - (UINT)(ref_v - inside_offset_v) < inside_limit_v) { - calc_value = calc[(ref_u >> 3) + ref_v * calc_bytewrap]; - if (calc_value && ((calc_value >> (ref_u & 7)) & 1)) { - ref_out_u_ = ref_u - out_u_; - ref_out_v_ = ref_v - out_v_; - ref_out_f_ = aff0MV1(aff0_uv2fg, ref_out_u_, ref_out_v_); - ref_out_g_ = aff0MV2(aff0_uv2fg, ref_out_u_, ref_out_v_); - ref_out_f = tround(ref_out_f_); - ref_out_g = tround(ref_out_g_); - sum_weights = 0; - sum_contribs_r = 0; - sum_contribs_g = 0; - sum_contribs_b = 0; - sum_contribs_m = 0; - for (i = n_pix - 1; i >= 0; i--) { - pix_out_f = pix_ref_f[i] + ref_out_f; - pix_out_g = pix_ref_g[i] + ref_out_g; - weight = (filter[pix_out_f] * filter[pix_out_g]) >> 16; - pix_u = pix_ref_u[i] + ref_u; - pix_v = pix_ref_v[i] + ref_v; - - //pix_value = buffer_in[pix_u + pix_v * wrap_in]; - - int pix_in_pos = pix_u + pix_v * wrap_in; - int t = buffer_in[pix_in_pos].getTone(); - int p = buffer_in[pix_in_pos].getPaint(); - int i = buffer_in[pix_in_pos].getInk(); - - if (t == TPixelCM32::getMaxTone()) - pix_value = paints[p]; - else if (t == 0) - pix_value = inks[i]; - else - pix_value = blend(inks[i], paints[p], t, TPixelCM32::getMaxTone()); - - sum_contribs_r += (int)pix_value.r * weight; - sum_contribs_g += (int)pix_value.g * weight; - sum_contribs_b += (int)pix_value.b * weight; - sum_contribs_m += (int)pix_value.m * weight; - sum_weights += weight; - } - - inv_sum_weights = 1.0 / sum_weights; - out_fval_r = sum_contribs_r * inv_sum_weights; - out_fval_g = sum_contribs_g * inv_sum_weights; - out_fval_b = sum_contribs_b * inv_sum_weights; - out_fval_m = sum_contribs_m * inv_sum_weights; - notLessThan(0.0, out_fval_r); - notLessThan(0.0, out_fval_g); - notLessThan(0.0, out_fval_b); - notLessThan(0.0, out_fval_m); - out_value_r = troundp(out_fval_r); - out_value_g = troundp(out_fval_g); - out_value_b = troundp(out_fval_b); - out_value_m = troundp(out_fval_m); - notMoreThan(/*T*/ TPixel32::maxChannelValue, out_value_r); - notMoreThan(/*T*/ TPixel32::maxChannelValue, out_value_g); - notMoreThan(/*T*/ TPixel32::maxChannelValue, out_value_b); - notMoreThan(/*T*/ TPixel32::maxChannelValue, out_value_m); - out_value.r = out_value_r; - out_value.g = out_value_g; - out_value.b = out_value_b; - out_value.m = out_value_m; - } else { - int pix_in_pos = ref_u + ref_v * wrap_in; - int t = buffer_in[pix_in_pos].getTone(); - int p = buffer_in[pix_in_pos].getPaint(); - int i = buffer_in[pix_in_pos].getInk(); - - if (t == TPixelCM32::getMaxTone()) - out_value = paints[p]; - else if (t == 0) - out_value = inks[i]; - else - out_value = blend(inks[i], paints[p], t, TPixelCM32::getMaxTone()); - - // out_value = buffer_in[ref_u + ref_v * wrap_in]; - } - } else if (outside_min_u_ <= out_u_ && out_u_ <= outside_max_u_ && - outside_min_v_ <= out_v_ && out_v_ <= outside_max_v_) { - if ((UINT)ref_u >= (UINT)lu || (UINT)ref_v >= (UINT)lv) - must_calc = true; - else { - calc_value = calc[(ref_u >> 3) + ref_v * calc_bytewrap]; - must_calc = calc_value && ((calc_value >> (ref_u & 7)) & 1); - } - - if (must_calc) { - ref_out_u_ = ref_u - out_u_; - ref_out_v_ = ref_v - out_v_; - ref_out_f_ = aff0MV1(aff0_uv2fg, ref_out_u_, ref_out_v_); - ref_out_g_ = aff0MV2(aff0_uv2fg, ref_out_u_, ref_out_v_); - ref_out_f = tround(ref_out_f_); - ref_out_g = tround(ref_out_g_); - sum_weights = 0; - sum_contribs_r = 0; - sum_contribs_g = 0; - sum_contribs_b = 0; - sum_contribs_m = 0; - - for (i = n_pix - 1; i >= 0; i--) { - pix_out_f = pix_ref_f[i] + ref_out_f; - pix_out_g = pix_ref_g[i] + ref_out_g; - weight = (filter[pix_out_f] * filter[pix_out_g]) >> 16; - pix_u = pix_ref_u[i] + ref_u; - pix_v = pix_ref_v[i] + ref_v; - notLessThan(0, pix_u); - notLessThan(0, pix_v); - notMoreThan(mu, pix_u); - notMoreThan(mv, pix_v); - - //pix_value = buffer_in[pix_u + pix_v * wrap_in]; - - int pix_in_pos = pix_u + pix_v * wrap_in; - int t = buffer_in[pix_in_pos].getTone(); - int p = buffer_in[pix_in_pos].getPaint(); - int i = buffer_in[pix_in_pos].getInk(); - - if (t == TPixelCM32::getMaxTone()) - pix_value = paints[p]; - else if (t == 0) - pix_value = inks[i]; - else - pix_value = blend(inks[i], paints[p], t, TPixelCM32::getMaxTone()); - - sum_contribs_r += (int)pix_value.r * weight; - sum_contribs_g += (int)pix_value.g * weight; - sum_contribs_b += (int)pix_value.b * weight; - sum_contribs_m += (int)pix_value.m * weight; - sum_weights += weight; - } - - inv_sum_weights = 1.0 / sum_weights; - out_fval_r = sum_contribs_r * inv_sum_weights; - out_fval_g = sum_contribs_g * inv_sum_weights; - out_fval_b = sum_contribs_b * inv_sum_weights; - out_fval_m = sum_contribs_m * inv_sum_weights; - notLessThan(0.0, out_fval_r); - notLessThan(0.0, out_fval_g); - notLessThan(0.0, out_fval_b); - notLessThan(0.0, out_fval_m); - out_value_r = troundp(out_fval_r); - out_value_g = troundp(out_fval_g); - out_value_b = troundp(out_fval_b); - out_value_m = troundp(out_fval_m); - notMoreThan(/*T*/ TPixel32::maxChannelValue, out_value_r); - notMoreThan(/*T*/ TPixel32::maxChannelValue, out_value_g); - notMoreThan(/*T*/ TPixel32::maxChannelValue, out_value_b); - notMoreThan(/*T*/ TPixel32::maxChannelValue, out_value_m); - out_value.r = out_value_r; - out_value.g = out_value_g; - out_value.b = out_value_b; - out_value.m = out_value_m; - } else { - // out_value = buffer_in[ref_u + ref_v * wrap_in]; - - int pix_in_pos = ref_u + ref_v * wrap_in; - int t = buffer_in[pix_in_pos].getTone(); - int p = buffer_in[pix_in_pos].getPaint(); - int i = buffer_in[pix_in_pos].getInk(); - - if (t == TPixelCM32::getMaxTone()) - out_value = paints[p]; - else if (t == 0) - out_value = inks[i]; - else - out_value = blend(inks[i], paints[p], t, TPixelCM32::getMaxTone()); - } - } else { - out_value = default_value; - } - - buffer_out[out_x + out_y * wrap_out] = out_value; - } - } - - if (calc) - delete[] calc; + if (n_pix >= 512 || /*T*/ TPixel32::maxChannelValue > 255) { + assert(false); + /* +resample_main_rgbm_bigradius( rout, rin, + aff_xy2uv, + aff0_uv2fg, + min_pix_ref_u, min_pix_ref_v, + max_pix_ref_u, max_pix_ref_v, + n_pix, + pix_ref_u, pix_ref_v, + pix_ref_f, pix_ref_g, + filter ); +*/ + return; + } + + if (!(rout->getLx() > 0 && rout->getLy() > 0)) return; + + if (!(rin->getLx() > 0 && rin->getLy() > 0)) { + resample_clear_rgbm(rout, default_value); + return; + } + + int colorCount = palette->getStyleCount(); + colorCount = std::max( + {colorCount, TPixelCM32::getMaxInk(), TPixelCM32::getMaxPaint()}); + + std::vector paints(colorCount); + std::vector inks(colorCount); + for (i = 0; i < palette->getStyleCount(); i++) + paints[i] = inks[i] = + ::premultiply(palette->getStyle(i)->getAverageColor()); + + calc = 0; + calc_allocsize = 0; + create_calc(rin, min_pix_ref_u, max_pix_ref_u, min_pix_ref_v, max_pix_ref_v, + calc, calc_allocsize, calc_bytewrap); + + buffer_in = rin->pixels(); + buffer_out = rout->pixels(); + lu = rin->getLx(); + lx = rout->getLx(); + lv = rin->getLy(); + ly = rout->getLy(); + wrap_in = rin->getWrap(); + wrap_out = rout->getWrap(); + mu = lu - 1; + mv = lv - 1; + + inside_offset_u = -min_pix_ref_u; + inside_offset_v = -min_pix_ref_v; + inside_limit_u = lu - max_pix_ref_u - inside_offset_u; + inside_limit_v = lv - max_pix_ref_v - inside_offset_v; + inside_nonempty = (int)inside_limit_u > 0 && (int)inside_limit_v > 0; + outside_min_u_ = -0.5; + outside_min_v_ = -0.5; + outside_max_u_ = lu - 0.5; + outside_max_v_ = lv - 0.5; + + for (out_y = 0, out_y_ = 0.0; out_y < ly; out_y++, out_y_ += 1.0) { + for (out_x = 0, out_x_ = 0.0; out_x < lx; out_x++, out_x_ += 1.0) { + out_u_ = affMV1(aff_xy2uv, out_x_, out_y_); + out_v_ = affMV2(aff_xy2uv, out_x_, out_y_); + ref_u = intLE(out_u_); + ref_v = intLE(out_v_); + + if (inside_nonempty && (UINT)(ref_u - inside_offset_u) < inside_limit_u && + (UINT)(ref_v - inside_offset_v) < inside_limit_v) { + calc_value = calc[(ref_u >> 3) + ref_v * calc_bytewrap]; + if (calc_value && ((calc_value >> (ref_u & 7)) & 1)) { + ref_out_u_ = ref_u - out_u_; + ref_out_v_ = ref_v - out_v_; + ref_out_f_ = aff0MV1(aff0_uv2fg, ref_out_u_, ref_out_v_); + ref_out_g_ = aff0MV2(aff0_uv2fg, ref_out_u_, ref_out_v_); + ref_out_f = tround(ref_out_f_); + ref_out_g = tround(ref_out_g_); + sum_weights = 0; + sum_contribs_r = 0; + sum_contribs_g = 0; + sum_contribs_b = 0; + sum_contribs_m = 0; + for (i = n_pix - 1; i >= 0; i--) { + pix_out_f = pix_ref_f[i] + ref_out_f; + pix_out_g = pix_ref_g[i] + ref_out_g; + weight = (filter[pix_out_f] * filter[pix_out_g]) >> 16; + pix_u = pix_ref_u[i] + ref_u; + pix_v = pix_ref_v[i] + ref_v; + + // pix_value = buffer_in[pix_u + pix_v * wrap_in]; + + int pix_in_pos = pix_u + pix_v * wrap_in; + int t = buffer_in[pix_in_pos].getTone(); + int p = buffer_in[pix_in_pos].getPaint(); + int i = buffer_in[pix_in_pos].getInk(); + + if (t == TPixelCM32::getMaxTone()) + pix_value = paints[p]; + else if (t == 0) + pix_value = inks[i]; + else + pix_value = + blend(inks[i], paints[p], t, TPixelCM32::getMaxTone()); + + sum_contribs_r += (int)pix_value.r * weight; + sum_contribs_g += (int)pix_value.g * weight; + sum_contribs_b += (int)pix_value.b * weight; + sum_contribs_m += (int)pix_value.m * weight; + sum_weights += weight; + } + + inv_sum_weights = 1.0 / sum_weights; + out_fval_r = sum_contribs_r * inv_sum_weights; + out_fval_g = sum_contribs_g * inv_sum_weights; + out_fval_b = sum_contribs_b * inv_sum_weights; + out_fval_m = sum_contribs_m * inv_sum_weights; + notLessThan(0.0, out_fval_r); + notLessThan(0.0, out_fval_g); + notLessThan(0.0, out_fval_b); + notLessThan(0.0, out_fval_m); + out_value_r = troundp(out_fval_r); + out_value_g = troundp(out_fval_g); + out_value_b = troundp(out_fval_b); + out_value_m = troundp(out_fval_m); + notMoreThan(/*T*/ TPixel32::maxChannelValue, out_value_r); + notMoreThan(/*T*/ TPixel32::maxChannelValue, out_value_g); + notMoreThan(/*T*/ TPixel32::maxChannelValue, out_value_b); + notMoreThan(/*T*/ TPixel32::maxChannelValue, out_value_m); + out_value.r = out_value_r; + out_value.g = out_value_g; + out_value.b = out_value_b; + out_value.m = out_value_m; + } else { + int pix_in_pos = ref_u + ref_v * wrap_in; + int t = buffer_in[pix_in_pos].getTone(); + int p = buffer_in[pix_in_pos].getPaint(); + int i = buffer_in[pix_in_pos].getInk(); + + if (t == TPixelCM32::getMaxTone()) + out_value = paints[p]; + else if (t == 0) + out_value = inks[i]; + else + out_value = blend(inks[i], paints[p], t, TPixelCM32::getMaxTone()); + + // out_value = buffer_in[ref_u + ref_v * wrap_in]; + } + } else if (outside_min_u_ <= out_u_ && out_u_ <= outside_max_u_ && + outside_min_v_ <= out_v_ && out_v_ <= outside_max_v_) { + if ((UINT)ref_u >= (UINT)lu || (UINT)ref_v >= (UINT)lv) + must_calc = true; + else { + calc_value = calc[(ref_u >> 3) + ref_v * calc_bytewrap]; + must_calc = calc_value && ((calc_value >> (ref_u & 7)) & 1); + } + + if (must_calc) { + ref_out_u_ = ref_u - out_u_; + ref_out_v_ = ref_v - out_v_; + ref_out_f_ = aff0MV1(aff0_uv2fg, ref_out_u_, ref_out_v_); + ref_out_g_ = aff0MV2(aff0_uv2fg, ref_out_u_, ref_out_v_); + ref_out_f = tround(ref_out_f_); + ref_out_g = tround(ref_out_g_); + sum_weights = 0; + sum_contribs_r = 0; + sum_contribs_g = 0; + sum_contribs_b = 0; + sum_contribs_m = 0; + + for (i = n_pix - 1; i >= 0; i--) { + pix_out_f = pix_ref_f[i] + ref_out_f; + pix_out_g = pix_ref_g[i] + ref_out_g; + weight = (filter[pix_out_f] * filter[pix_out_g]) >> 16; + pix_u = pix_ref_u[i] + ref_u; + pix_v = pix_ref_v[i] + ref_v; + notLessThan(0, pix_u); + notLessThan(0, pix_v); + notMoreThan(mu, pix_u); + notMoreThan(mv, pix_v); + + // pix_value = buffer_in[pix_u + pix_v * wrap_in]; + + int pix_in_pos = pix_u + pix_v * wrap_in; + int t = buffer_in[pix_in_pos].getTone(); + int p = buffer_in[pix_in_pos].getPaint(); + int i = buffer_in[pix_in_pos].getInk(); + + if (t == TPixelCM32::getMaxTone()) + pix_value = paints[p]; + else if (t == 0) + pix_value = inks[i]; + else + pix_value = + blend(inks[i], paints[p], t, TPixelCM32::getMaxTone()); + + sum_contribs_r += (int)pix_value.r * weight; + sum_contribs_g += (int)pix_value.g * weight; + sum_contribs_b += (int)pix_value.b * weight; + sum_contribs_m += (int)pix_value.m * weight; + sum_weights += weight; + } + + inv_sum_weights = 1.0 / sum_weights; + out_fval_r = sum_contribs_r * inv_sum_weights; + out_fval_g = sum_contribs_g * inv_sum_weights; + out_fval_b = sum_contribs_b * inv_sum_weights; + out_fval_m = sum_contribs_m * inv_sum_weights; + notLessThan(0.0, out_fval_r); + notLessThan(0.0, out_fval_g); + notLessThan(0.0, out_fval_b); + notLessThan(0.0, out_fval_m); + out_value_r = troundp(out_fval_r); + out_value_g = troundp(out_fval_g); + out_value_b = troundp(out_fval_b); + out_value_m = troundp(out_fval_m); + notMoreThan(/*T*/ TPixel32::maxChannelValue, out_value_r); + notMoreThan(/*T*/ TPixel32::maxChannelValue, out_value_g); + notMoreThan(/*T*/ TPixel32::maxChannelValue, out_value_b); + notMoreThan(/*T*/ TPixel32::maxChannelValue, out_value_m); + out_value.r = out_value_r; + out_value.g = out_value_g; + out_value.b = out_value_b; + out_value.m = out_value_m; + } else { + // out_value = buffer_in[ref_u + ref_v * wrap_in]; + + int pix_in_pos = ref_u + ref_v * wrap_in; + int t = buffer_in[pix_in_pos].getTone(); + int p = buffer_in[pix_in_pos].getPaint(); + int i = buffer_in[pix_in_pos].getInk(); + + if (t == TPixelCM32::getMaxTone()) + out_value = paints[p]; + else if (t == 0) + out_value = inks[i]; + else + out_value = blend(inks[i], paints[p], t, TPixelCM32::getMaxTone()); + } + } else { + out_value = default_value; + } + + buffer_out[out_x + out_y * wrap_out] = out_value; + } + } + + if (calc) delete[] calc; } //--------------------------------------------------------------------------- template void rop_resample_rgbm_2(TRasterPT rout, const TRasterCM32P &rin, - const TAffine &aff, TRop::ResampleFilterType flt_type, double blur, TPalette *palette) -{ + const TAffine &aff, TRop::ResampleFilterType flt_type, + double blur, TPalette *palette) { #define FILTER_RESOLUTION 1024 #define MAX_FILTER_VAL 32767 #ifdef USE_STATIC_VARS - static TRop::ResampleFilterType current_flt_type = TRop::None; - static std::unique_ptr filter_array; - static short *filter = 0; - static int min_filter_fg, max_filter_fg; - static int filter_array_size = 0; - static int n_pix = 0; - static std::unique_ptr pix_ref_u; - static std::unique_ptr pix_ref_v; - static std::unique_ptr pix_ref_f; - static std::unique_ptr pix_ref_g; - static int current_max_n_pix = 0; + static TRop::ResampleFilterType current_flt_type = TRop::None; + static std::unique_ptr filter_array; + static short *filter = 0; + static int min_filter_fg, max_filter_fg; + static int filter_array_size = 0; + static int n_pix = 0; + static std::unique_ptr pix_ref_u; + static std::unique_ptr pix_ref_v; + static std::unique_ptr pix_ref_f; + static std::unique_ptr pix_ref_g; + static int current_max_n_pix = 0; #else - std::unique_ptr filter_array; - short *filter = 0; - int min_filter_fg, max_filter_fg; - int filter_array_size = 0; - int n_pix = 0; - std::unique_ptr pix_ref_u; - std::unique_ptr pix_ref_v; - std::unique_ptr pix_ref_f; - std::unique_ptr pix_ref_g; - int current_max_n_pix = 0; + std::unique_ptr filter_array; + short *filter = 0; + int min_filter_fg, max_filter_fg; + int filter_array_size = 0; + int n_pix = 0; + std::unique_ptr pix_ref_u; + std::unique_ptr pix_ref_v; + std::unique_ptr pix_ref_f; + std::unique_ptr pix_ref_g; + int current_max_n_pix = 0; #endif - int filter_st_radius; - int filter_fg_radius; - int filter_size; - int f; - double s_; - double weight_; - int weight; - TAffine aff_uv2xy; - TAffine aff_xy2uv; - TAffine aff0_uv2xy; - TAffine aff0_xy2st; - TAffine aff0_uv2st; - TAffine aff0_st2fg; - TAffine aff0_uv2fg; - TAffine aff0_fg2uv; - double scale_x, scale_y; - double inv_blur; - int max_n_pix; - double min_pix_out_u_, min_pix_out_v_; - double max_pix_out_u_, max_pix_out_v_; - int min_pix_ref_u, min_pix_ref_v; - int max_pix_ref_u, max_pix_ref_v; - int cur_pix_ref_u, cur_pix_ref_v; - double cur_pix_ref_f_, cur_pix_ref_g_; - int cur_pix_ref_f, cur_pix_ref_g; - double min_ref_out_f_, min_ref_out_g_; - double max_ref_out_f_, max_ref_out_g_; - int min_ref_out_f, min_ref_out_g; - int max_ref_out_f, max_ref_out_g; - int min_pix_ref_f, min_pix_ref_g; - int max_pix_ref_f, max_pix_ref_g; - int min_pix_out_f, min_pix_out_g; - int max_pix_out_f, max_pix_out_g; - int min_pix_out_fg; - int max_pix_out_fg; + int filter_st_radius; + int filter_fg_radius; + int filter_size; + int f; + double s_; + double weight_; + int weight; + TAffine aff_uv2xy; + TAffine aff_xy2uv; + TAffine aff0_uv2xy; + TAffine aff0_xy2st; + TAffine aff0_uv2st; + TAffine aff0_st2fg; + TAffine aff0_uv2fg; + TAffine aff0_fg2uv; + double scale_x, scale_y; + double inv_blur; + int max_n_pix; + double min_pix_out_u_, min_pix_out_v_; + double max_pix_out_u_, max_pix_out_v_; + int min_pix_ref_u, min_pix_ref_v; + int max_pix_ref_u, max_pix_ref_v; + int cur_pix_ref_u, cur_pix_ref_v; + double cur_pix_ref_f_, cur_pix_ref_g_; + int cur_pix_ref_f, cur_pix_ref_g; + double min_ref_out_f_, min_ref_out_g_; + double max_ref_out_f_, max_ref_out_g_; + int min_ref_out_f, min_ref_out_g; + int max_ref_out_f, max_ref_out_g; + int min_pix_ref_f, min_pix_ref_g; + int max_pix_ref_f, max_pix_ref_g; + int min_pix_out_f, min_pix_out_g; + int max_pix_out_f, max_pix_out_g; + int min_pix_out_fg; + int max_pix_out_fg; #ifdef USE_DOUBLE_TO_INT - double d2iaux; + double d2iaux; #endif - assert(flt_type != TRop::None); - - filter_st_radius = get_filter_radius(flt_type); - filter_fg_radius = filter_st_radius * FILTER_RESOLUTION; - - aff_uv2xy = aff; - aff0_uv2xy = aff_uv2xy.place(0.0, 0.0, 0.0, 0.0); - aff_xy2uv = aff_uv2xy.inv(); - - scale_x = sqrt(sq(aff_uv2xy.a11) + sq(aff_uv2xy.a12)); - scale_y = sqrt(sq(aff_uv2xy.a21) + sq(aff_uv2xy.a22)); - aff0_xy2st = TScale((scale_x > 1.0) ? 1.0 / scale_x : 1.0, - (scale_y > 1.0) ? 1.0 / scale_y : 1.0); - - if (blur > 1.0) //per ora il blur e' 1.0 - { - inv_blur = 1.0 / blur; - aff0_xy2st = TScale(inv_blur, inv_blur) * aff0_xy2st; - } - - aff0_uv2st = aff0_xy2st * aff0_uv2xy; - aff0_st2fg = TScale(FILTER_RESOLUTION, FILTER_RESOLUTION); - aff0_uv2fg = aff0_st2fg * aff0_uv2st; - aff0_fg2uv = aff0_uv2fg.inv(); - - minmax(-filter_fg_radius, -filter_fg_radius, - filter_fg_radius, filter_fg_radius, - aff0_fg2uv, - min_pix_out_u_, min_pix_out_v_, - max_pix_out_u_, max_pix_out_v_); - - min_pix_ref_u = intGT(min_pix_out_u_); - min_pix_ref_v = intGT(min_pix_out_v_); - max_pix_ref_u = intLT(max_pix_out_u_) + 1; - max_pix_ref_v = intLT(max_pix_out_v_) + 1; - - if (blur <= 1.0) { - if (aff_uv2xy.a12 == 0.0 && aff_uv2xy.a21 == 0.0) { - if (aff_uv2xy.a11 == 1.0 && isInt(aff_uv2xy.a13)) { - min_pix_ref_u = 0; - max_pix_ref_u = 0; - } - if (aff_uv2xy.a22 == 1.0 && isInt(aff_uv2xy.a23)) { - min_pix_ref_v = 0; - max_pix_ref_v = 0; - } - } else if (aff_uv2xy.a11 == 0.0 && aff_uv2xy.a22 == 0.0) { - if (aff_uv2xy.a12 == 1.0 && isInt(aff_uv2xy.a13)) { - min_pix_ref_v = 0; - max_pix_ref_v = 0; - } - if (aff_uv2xy.a21 == 1.0 && isInt(aff_uv2xy.a23)) { - min_pix_ref_u = 0; - max_pix_ref_u = 0; - } - } - } - - max_n_pix = (max_pix_ref_u - min_pix_ref_u + 1) * - (max_pix_ref_v - min_pix_ref_v + 1); - - if (max_n_pix > current_max_n_pix) { - current_max_n_pix = max_n_pix; - pix_ref_u.reset(new int[current_max_n_pix]); - pix_ref_v.reset(new int[current_max_n_pix]); - pix_ref_f.reset(new int[current_max_n_pix]); - pix_ref_g.reset(new int[current_max_n_pix]); - assert(pix_ref_u && pix_ref_v && pix_ref_f && pix_ref_g); - } - - minmax(-1, -1, 0, 0, - aff0_uv2fg, - min_ref_out_f_, min_ref_out_g_, - max_ref_out_f_, max_ref_out_g_); - - min_ref_out_f = tround(min_ref_out_f_); - min_ref_out_g = tround(min_ref_out_g_); - max_ref_out_f = tround(max_ref_out_f_); - max_ref_out_g = tround(max_ref_out_g_); - min_pix_ref_f = -filter_fg_radius - max_ref_out_f; - min_pix_ref_g = -filter_fg_radius - max_ref_out_g; - max_pix_ref_f = filter_fg_radius - min_ref_out_f; - max_pix_ref_g = filter_fg_radius - min_ref_out_g; - - min_pix_out_f = c_maxint; - min_pix_out_g = c_maxint; - max_pix_out_f = c_minint; - max_pix_out_g = c_minint; - n_pix = 0; - for (cur_pix_ref_v = min_pix_ref_v; - cur_pix_ref_v <= max_pix_ref_v; - cur_pix_ref_v++) - for (cur_pix_ref_u = min_pix_ref_u; - cur_pix_ref_u <= max_pix_ref_u; - cur_pix_ref_u++) { - cur_pix_ref_f_ = affMV1(aff0_uv2fg, cur_pix_ref_u, cur_pix_ref_v); - cur_pix_ref_g_ = affMV2(aff0_uv2fg, cur_pix_ref_u, cur_pix_ref_v); - cur_pix_ref_f = tround(cur_pix_ref_f_); - cur_pix_ref_g = tround(cur_pix_ref_g_); - if (min_pix_ref_f <= cur_pix_ref_f && cur_pix_ref_f <= max_pix_ref_f && - min_pix_ref_g <= cur_pix_ref_g && cur_pix_ref_g <= max_pix_ref_g) { - pix_ref_u[n_pix] = cur_pix_ref_u; - pix_ref_v[n_pix] = cur_pix_ref_v; - pix_ref_f[n_pix] = cur_pix_ref_f; - pix_ref_g[n_pix] = cur_pix_ref_g; - notMoreThan(cur_pix_ref_f + min_ref_out_f, min_pix_out_f); - notMoreThan(cur_pix_ref_g + min_ref_out_g, min_pix_out_g); - notLessThan(cur_pix_ref_f + max_ref_out_f, max_pix_out_f); - notLessThan(cur_pix_ref_g + max_ref_out_g, max_pix_out_g); - n_pix++; - } - } - assert(n_pix > 0); + assert(flt_type != TRop::None); + + filter_st_radius = get_filter_radius(flt_type); + filter_fg_radius = filter_st_radius * FILTER_RESOLUTION; + + aff_uv2xy = aff; + aff0_uv2xy = aff_uv2xy.place(0.0, 0.0, 0.0, 0.0); + aff_xy2uv = aff_uv2xy.inv(); + + scale_x = sqrt(sq(aff_uv2xy.a11) + sq(aff_uv2xy.a12)); + scale_y = sqrt(sq(aff_uv2xy.a21) + sq(aff_uv2xy.a22)); + aff0_xy2st = TScale((scale_x > 1.0) ? 1.0 / scale_x : 1.0, + (scale_y > 1.0) ? 1.0 / scale_y : 1.0); + + if (blur > 1.0) // per ora il blur e' 1.0 + { + inv_blur = 1.0 / blur; + aff0_xy2st = TScale(inv_blur, inv_blur) * aff0_xy2st; + } + + aff0_uv2st = aff0_xy2st * aff0_uv2xy; + aff0_st2fg = TScale(FILTER_RESOLUTION, FILTER_RESOLUTION); + aff0_uv2fg = aff0_st2fg * aff0_uv2st; + aff0_fg2uv = aff0_uv2fg.inv(); + + minmax(-filter_fg_radius, -filter_fg_radius, filter_fg_radius, + filter_fg_radius, aff0_fg2uv, min_pix_out_u_, min_pix_out_v_, + max_pix_out_u_, max_pix_out_v_); + + min_pix_ref_u = intGT(min_pix_out_u_); + min_pix_ref_v = intGT(min_pix_out_v_); + max_pix_ref_u = intLT(max_pix_out_u_) + 1; + max_pix_ref_v = intLT(max_pix_out_v_) + 1; + + if (blur <= 1.0) { + if (aff_uv2xy.a12 == 0.0 && aff_uv2xy.a21 == 0.0) { + if (aff_uv2xy.a11 == 1.0 && isInt(aff_uv2xy.a13)) { + min_pix_ref_u = 0; + max_pix_ref_u = 0; + } + if (aff_uv2xy.a22 == 1.0 && isInt(aff_uv2xy.a23)) { + min_pix_ref_v = 0; + max_pix_ref_v = 0; + } + } else if (aff_uv2xy.a11 == 0.0 && aff_uv2xy.a22 == 0.0) { + if (aff_uv2xy.a12 == 1.0 && isInt(aff_uv2xy.a13)) { + min_pix_ref_v = 0; + max_pix_ref_v = 0; + } + if (aff_uv2xy.a21 == 1.0 && isInt(aff_uv2xy.a23)) { + min_pix_ref_u = 0; + max_pix_ref_u = 0; + } + } + } + + max_n_pix = + (max_pix_ref_u - min_pix_ref_u + 1) * (max_pix_ref_v - min_pix_ref_v + 1); + + if (max_n_pix > current_max_n_pix) { + current_max_n_pix = max_n_pix; + pix_ref_u.reset(new int[current_max_n_pix]); + pix_ref_v.reset(new int[current_max_n_pix]); + pix_ref_f.reset(new int[current_max_n_pix]); + pix_ref_g.reset(new int[current_max_n_pix]); + assert(pix_ref_u && pix_ref_v && pix_ref_f && pix_ref_g); + } + + minmax(-1, -1, 0, 0, aff0_uv2fg, min_ref_out_f_, min_ref_out_g_, + max_ref_out_f_, max_ref_out_g_); + + min_ref_out_f = tround(min_ref_out_f_); + min_ref_out_g = tround(min_ref_out_g_); + max_ref_out_f = tround(max_ref_out_f_); + max_ref_out_g = tround(max_ref_out_g_); + min_pix_ref_f = -filter_fg_radius - max_ref_out_f; + min_pix_ref_g = -filter_fg_radius - max_ref_out_g; + max_pix_ref_f = filter_fg_radius - min_ref_out_f; + max_pix_ref_g = filter_fg_radius - min_ref_out_g; + + min_pix_out_f = c_maxint; + min_pix_out_g = c_maxint; + max_pix_out_f = c_minint; + max_pix_out_g = c_minint; + n_pix = 0; + for (cur_pix_ref_v = min_pix_ref_v; cur_pix_ref_v <= max_pix_ref_v; + cur_pix_ref_v++) + for (cur_pix_ref_u = min_pix_ref_u; cur_pix_ref_u <= max_pix_ref_u; + cur_pix_ref_u++) { + cur_pix_ref_f_ = affMV1(aff0_uv2fg, cur_pix_ref_u, cur_pix_ref_v); + cur_pix_ref_g_ = affMV2(aff0_uv2fg, cur_pix_ref_u, cur_pix_ref_v); + cur_pix_ref_f = tround(cur_pix_ref_f_); + cur_pix_ref_g = tround(cur_pix_ref_g_); + if (min_pix_ref_f <= cur_pix_ref_f && cur_pix_ref_f <= max_pix_ref_f && + min_pix_ref_g <= cur_pix_ref_g && cur_pix_ref_g <= max_pix_ref_g) { + pix_ref_u[n_pix] = cur_pix_ref_u; + pix_ref_v[n_pix] = cur_pix_ref_v; + pix_ref_f[n_pix] = cur_pix_ref_f; + pix_ref_g[n_pix] = cur_pix_ref_g; + notMoreThan(cur_pix_ref_f + min_ref_out_f, min_pix_out_f); + notMoreThan(cur_pix_ref_g + min_ref_out_g, min_pix_out_g); + notLessThan(cur_pix_ref_f + max_ref_out_f, max_pix_out_f); + notLessThan(cur_pix_ref_g + max_ref_out_g, max_pix_out_g); + n_pix++; + } + } + assert(n_pix > 0); #ifdef USE_STATIC_VARS - if (flt_type != current_flt_type) { - current_flt_type = flt_type; + if (flt_type != current_flt_type) { + current_flt_type = flt_type; #endif - min_filter_fg = -filter_fg_radius - FILTER_RESOLUTION * 3 / 2; - max_filter_fg = filter_fg_radius + FILTER_RESOLUTION * 3 / 2; - filter_size = max_filter_fg - min_filter_fg + 1; - if (filter_size > filter_array_size) { - filter_array.reset(new short[filter_size]); - assert(filter_array); - filter_array_size = filter_size; - } - filter = filter_array.get() - min_filter_fg; - filter[0] = MAX_FILTER_VAL; - for (f = 1, s_ = 1.0 / FILTER_RESOLUTION; - f < filter_fg_radius; - f++, s_ += 1.0 / FILTER_RESOLUTION) { - weight_ = get_filter_value(flt_type, s_) * (double)MAX_FILTER_VAL; - weight = tround(weight_); - filter[f] = weight; - filter[-f] = weight; - } - for (f = filter_fg_radius; f <= max_filter_fg; f++) - filter[f] = 0; - for (f = -filter_fg_radius; f >= min_filter_fg; f--) - filter[f] = 0; + min_filter_fg = -filter_fg_radius - FILTER_RESOLUTION * 3 / 2; + max_filter_fg = filter_fg_radius + FILTER_RESOLUTION * 3 / 2; + filter_size = max_filter_fg - min_filter_fg + 1; + if (filter_size > filter_array_size) { + filter_array.reset(new short[filter_size]); + assert(filter_array); + filter_array_size = filter_size; + } + filter = filter_array.get() - min_filter_fg; + filter[0] = MAX_FILTER_VAL; + for (f = 1, s_ = 1.0 / FILTER_RESOLUTION; f < filter_fg_radius; + f++, s_ += 1.0 / FILTER_RESOLUTION) { + weight_ = get_filter_value(flt_type, s_) * (double)MAX_FILTER_VAL; + weight = tround(weight_); + filter[f] = weight; + filter[-f] = weight; + } + for (f = filter_fg_radius; f <= max_filter_fg; f++) filter[f] = 0; + for (f = -filter_fg_radius; f >= min_filter_fg; f--) filter[f] = 0; #ifdef USE_STATIC_VARS - } + } #endif - min_pix_out_fg = std::min(min_pix_out_f, min_pix_out_g); - max_pix_out_fg = std::max(max_pix_out_f, max_pix_out_g); - if (min_pix_out_fg < min_filter_fg || max_pix_out_fg > max_filter_fg) { - filter_size = max_pix_out_fg - min_pix_out_fg + 1; - if (filter_size > filter_array_size) { - //controllare!! - //TREALLOC (filter_array, filter_size) - filter_array.reset(new short[filter_size]); - - assert(filter_array); - filter_array_size = filter_size; - } - filter = filter_array.get() - min_filter_fg; - if (min_pix_out_fg < min_filter_fg) { - int delta = min_filter_fg - min_pix_out_fg; - - for (f = max_filter_fg; f >= min_filter_fg; f--) - filter[f + delta] = filter[f]; - filter += delta; - for (f = min_filter_fg - 1; f >= min_pix_out_fg; f--) - filter[f] = 0; - min_filter_fg = min_pix_out_fg; - } - if (max_pix_out_fg > max_filter_fg) { - for (f = max_filter_fg + 1; f <= max_pix_out_fg; f++) - filter[f] = 0; - max_filter_fg = max_pix_out_fg; - } - } + min_pix_out_fg = std::min(min_pix_out_f, min_pix_out_g); + max_pix_out_fg = std::max(max_pix_out_f, max_pix_out_g); + if (min_pix_out_fg < min_filter_fg || max_pix_out_fg > max_filter_fg) { + filter_size = max_pix_out_fg - min_pix_out_fg + 1; + if (filter_size > filter_array_size) { + // controllare!! + // TREALLOC (filter_array, filter_size) + filter_array.reset(new short[filter_size]); + + assert(filter_array); + filter_array_size = filter_size; + } + filter = filter_array.get() - min_filter_fg; + if (min_pix_out_fg < min_filter_fg) { + int delta = min_filter_fg - min_pix_out_fg; + + for (f = max_filter_fg; f >= min_filter_fg; f--) + filter[f + delta] = filter[f]; + filter += delta; + for (f = min_filter_fg - 1; f >= min_pix_out_fg; f--) filter[f] = 0; + min_filter_fg = min_pix_out_fg; + } + if (max_pix_out_fg > max_filter_fg) { + for (f = max_filter_fg + 1; f <= max_pix_out_fg; f++) filter[f] = 0; + max_filter_fg = max_pix_out_fg; + } + } #ifdef _WIN32 - TRaster32P rout32 = rout; - if ((TSystem::getCPUExtensions() & TSystem::CpuSupportsSse2) && rout32) - resample_main_cm32_rgbm_SSE2(rout32, rin, aff_xy2uv, aff0_uv2fg, - min_pix_ref_u, min_pix_ref_v, - max_pix_ref_u, max_pix_ref_v, - n_pix, - pix_ref_u.get(), pix_ref_v.get(), - pix_ref_f.get(), pix_ref_g.get(), - filter, palette); - else + TRaster32P rout32 = rout; + if ((TSystem::getCPUExtensions() & TSystem::CpuSupportsSse2) && rout32) + resample_main_cm32_rgbm_SSE2( + rout32, rin, aff_xy2uv, aff0_uv2fg, min_pix_ref_u, min_pix_ref_v, + max_pix_ref_u, max_pix_ref_v, n_pix, pix_ref_u.get(), pix_ref_v.get(), + pix_ref_f.get(), pix_ref_g.get(), filter, palette); + else #endif - resample_main_cm32_rgbm(rout, rin, aff_xy2uv, aff0_uv2fg, - min_pix_ref_u, min_pix_ref_v, - max_pix_ref_u, max_pix_ref_v, - n_pix, - pix_ref_u.get(), pix_ref_v.get(), - pix_ref_f.get(), pix_ref_g.get(), - filter, palette); + resample_main_cm32_rgbm( + rout, rin, aff_xy2uv, aff0_uv2fg, min_pix_ref_u, min_pix_ref_v, + max_pix_ref_u, max_pix_ref_v, n_pix, pix_ref_u.get(), pix_ref_v.get(), + pix_ref_f.get(), pix_ref_g.get(), filter, palette); } //----------------------------------------------------------------------------- -} //namespace +} // namespace //----------------------------------------------------------------------------- -void TRop::resample(const TRasterP &out, - const TRasterCM32P &in, - const TPaletteP palette, - const TAffine &aff, - TRop::ResampleFilterType filterType, - double blur) -{ - TRasterP rin = in; - TRaster32P rout32 = out; - in->lock(); - out->lock(); - if (rout32) - rop_resample_rgbm_2(rout32, rin, aff, filterType, blur, palette.getPointer()); - else { - TRaster64P rout64 = out; - if (rout64) - rop_resample_rgbm_2(rout64, rin, aff, filterType, blur, palette.getPointer()); - else { - in->unlock(); - out->unlock(); - throw TRopException("unsupported pixel type"); - return; - } - } - in->unlock(); - out->unlock(); +void TRop::resample(const TRasterP &out, const TRasterCM32P &in, + const TPaletteP palette, const TAffine &aff, + TRop::ResampleFilterType filterType, double blur) { + TRasterP rin = in; + TRaster32P rout32 = out; + in->lock(); + out->lock(); + if (rout32) + rop_resample_rgbm_2(rout32, rin, aff, filterType, blur, + palette.getPointer()); + else { + TRaster64P rout64 = out; + if (rout64) + rop_resample_rgbm_2(rout64, rin, aff, filterType, blur, + palette.getPointer()); + else { + in->unlock(); + out->unlock(); + throw TRopException("unsupported pixel type"); + return; + } + } + in->unlock(); + out->unlock(); } -#endif //TNZCORE_LIGHT +#endif // TNZCORE_LIGHT void TRop::resample(const TRasterP &rout, const TRasterP &rin, - const TAffine &aff, ResampleFilterType filterType, double blur) -{ - rin->lock(); - rout->lock(); - - if (filterType == ClosestPixel || - filterType == Bilinear) { - if ((TRaster64P)rout || (TRaster64P)rin) - filterType = Triangle; - else { - quickResample(rout, rin, aff, filterType); - rin->unlock(); - rout->unlock(); - return; - } - } - - TRaster32P rout32 = rout, rin32 = rin; - if (rout32) { - if (!rin32) { - rin32 = TRaster32P(rin->getLx(), rin->getLy()); - TRop::convert(rin32, rin); - } - do_resample(rout32, rin32, aff, filterType, blur); - } else { + const TAffine &aff, ResampleFilterType filterType, + double blur) { + rin->lock(); + rout->lock(); + + if (filterType == ClosestPixel || filterType == Bilinear) { + if ((TRaster64P)rout || (TRaster64P)rin) + filterType = Triangle; + else { + quickResample(rout, rin, aff, filterType); + rin->unlock(); + rout->unlock(); + return; + } + } + + TRaster32P rout32 = rout, rin32 = rin; + if (rout32) { + if (!rin32) { + rin32 = TRaster32P(rin->getLx(), rin->getLy()); + TRop::convert(rin32, rin); + } + do_resample(rout32, rin32, aff, filterType, blur); + } else { #ifndef TNZCORE_LIGHT - TRasterCM32P routCM32 = rout, rinCM32 = rin; - if (routCM32 && rinCM32) - do_resample(routCM32, rinCM32, aff); - else + TRasterCM32P routCM32 = rout, rinCM32 = rin; + if (routCM32 && rinCM32) + do_resample(routCM32, rinCM32, aff); + else #endif - { - TRaster64P rout64 = rout, rin64 = rin; - if (rout64) { - if (!rin64) { - rin64 = TRaster64P(rin->getLx(), rin->getLy()); - TRop::convert(rin64, rin); - } - do_resample(rout64, rin64, aff, filterType, blur); - } else { - TRasterGR8P routGR8 = rout, rinGR8 = rin; - TRaster32P rin32 = rin; - if (routGR8 && rinGR8) - do_resample(routGR8, rinGR8, aff, filterType, blur); - else if (routGR8 && rin32) - do_resample(routGR8, rin32, aff, filterType, blur); - else { - rin->unlock(); - rout->unlock(); - throw TRopException("unsupported pixel type"); - } - } - } - } - rin->unlock(); - rout->unlock(); + { + TRaster64P rout64 = rout, rin64 = rin; + if (rout64) { + if (!rin64) { + rin64 = TRaster64P(rin->getLx(), rin->getLy()); + TRop::convert(rin64, rin); + } + do_resample(rout64, rin64, aff, filterType, blur); + } else { + TRasterGR8P routGR8 = rout, rinGR8 = rin; + TRaster32P rin32 = rin; + if (routGR8 && rinGR8) + do_resample(routGR8, rinGR8, aff, filterType, blur); + else if (routGR8 && rin32) + do_resample(routGR8, rin32, aff, filterType, blur); + else { + rin->unlock(); + rout->unlock(); + throw TRopException("unsupported pixel type"); + } + } + } + } + rin->unlock(); + rout->unlock(); } //----------------------------------------------------------------------------- diff --git a/toonz/sources/common/trop/trgbmscale.cpp b/toonz/sources/common/trop/trgbmscale.cpp index 656219d..f782d50 100644 --- a/toonz/sources/common/trop/trgbmscale.cpp +++ b/toonz/sources/common/trop/trgbmscale.cpp @@ -17,290 +17,291 @@ //----------------------------------------------------------------------------- -namespace -{ +namespace { template -void buildLUT(Chan *lut, double a, double k, int chanLow, int chanHigh) -{ - int i, max = (std::numeric_limits::max)(); +void buildLUT(Chan *lut, double a, double k, int chanLow, int chanHigh) { + int i, max = (std::numeric_limits::max)(); - a += 0.5; //round rather than trunc - for (i = 0; i <= max; ++i) - lut[i] = tcrop((int)(a + i * k), chanLow, chanHigh); + a += 0.5; // round rather than trunc + for (i = 0; i <= max; ++i) + lut[i] = tcrop((int)(a + i * k), chanLow, chanHigh); } //----------------------------------------------------------------------------- template -void do_greyScale_lut(TRasterPT rout, TRasterPT rin, - double a, double k, int out0, int out1) -{ - assert(rout->getSize() == rin->getSize()); +void do_greyScale_lut(TRasterPT rout, TRasterPT rin, double a, double k, + int out0, int out1) { + assert(rout->getSize() == rin->getSize()); - typedef typename T::Channel Channel; - int chanValuesCount = T::maxChannelValue + 1; + typedef typename T::Channel Channel; + int chanValuesCount = T::maxChannelValue + 1; - int fac = chanValuesCount / 256; - out0 = std::max(fac * out0, 0), out1 = std::min(fac * out1, T::maxChannelValue); + int fac = chanValuesCount / 256; + out0 = std::max(fac * out0, 0), + out1 = std::min(fac * out1, T::maxChannelValue); - //Build lut - Channel *lut = new Channel[chanValuesCount]; - buildLUT(lut, a, k, out0, out1); + // Build lut + Channel *lut = new Channel[chanValuesCount]; + buildLUT(lut, a, k, out0, out1); - //Perform scale - T *in, *end, *out; + // Perform scale + T *in, *end, *out; - int y, lx = rin->getLx(), ly = rin->getLy(); - for (y = 0; y < ly; ++y) { - in = rin->pixels(y), end = in + lx, out = rout->pixels(y); - for (; in < end; ++in, ++out) - out->value = lut[in->value]; - } + int y, lx = rin->getLx(), ly = rin->getLy(); + for (y = 0; y < ly; ++y) { + in = rin->pixels(y), end = in + lx, out = rout->pixels(y); + for (; in < end; ++in, ++out) out->value = lut[in->value]; + } - delete[] lut; + delete[] lut; } //----------------------------------------------------------------------------- template -void do_greyAdjust(TRasterPT rout, TRasterPT rin, - const int in0, const int in1, const int out0, const int out1) -{ - typedef typename T::Channel Channel; +void do_greyAdjust(TRasterPT rout, TRasterPT rin, const int in0, + const int in1, const int out0, const int out1) { + typedef typename T::Channel Channel; - assert(rout->getSize() == rin->getSize()); + assert(rout->getSize() == rin->getSize()); - //Build scale parameters - double k = (out1 - out0) / (double)(in1 - in0); - double a = out0 - k * in0; + // Build scale parameters + double k = (out1 - out0) / (double)(in1 - in0); + double a = out0 - k * in0; - do_greyScale_lut(rout, rin, a, k, out0, out1); + do_greyScale_lut(rout, rin, a, k, out0, out1); } //----------------------------------------------------------------------------- template -void do_rgbmScale_lut(TRasterPT rout, TRasterPT rin, - const double *a, const double *k, - const int *out0, const int *out1) -{ - assert(rout->getSize() == rin->getSize()); - - typedef typename T::Channel Channel; - int m, max = T::maxChannelValue, chanValuesCount = max + 1; - - int fac = chanValuesCount / 256; - int out0R = std::max(fac * out0[0], 0), out1R = std::min(fac * out1[0], T::maxChannelValue); - int out0G = std::max(fac * out0[1], 0), out1G = std::min(fac * out1[1], T::maxChannelValue); - int out0B = std::max(fac * out0[2], 0), out1B = std::min(fac * out1[2], T::maxChannelValue); - int out0M = std::max(fac * out0[3], 0), out1M = std::min(fac * out1[3], T::maxChannelValue); - - //Build luts - Channel *lut_r = new Channel[chanValuesCount]; - buildLUT(lut_r, a[0], k[0], out0R, out1R); - - Channel *lut_g = new Channel[chanValuesCount]; - buildLUT(lut_g, a[1], k[1], out0G, out1G); - - Channel *lut_b = new Channel[chanValuesCount]; - buildLUT(lut_b, a[2], k[2], out0B, out1B); - - Channel *lut_m = new Channel[chanValuesCount]; - buildLUT(lut_m, a[3], k[3], out0M, out1M); - - //Retrieve de/premultiplication luts - const double *lut_prem = premultiplyTable(); - const double *lut_deprem = depremultiplyTable(); - double premFac, depremFac; - - //Process raster - int y, lx = rin->getLx(), ly = rin->getLy(); - T *in, *end, *out; - - for (y = 0; y < ly; ++y) { - in = rin->pixels(y), end = in + lx, out = rout->pixels(y); - for (; in < end; ++in, ++out) { - m = lut_m[in->m]; - depremFac = lut_deprem[in->m]; - premFac = lut_prem[m]; - - out->r = premFac * lut_r[std::min((int)(in->r * depremFac), max)]; - out->g = premFac * lut_g[std::min((int)(in->g * depremFac), max)]; - out->b = premFac * lut_b[std::min((int)(in->b * depremFac), max)]; - out->m = m; - } - } - - delete[] lut_r; - delete[] lut_g; - delete[] lut_b; - delete[] lut_m; +void do_rgbmScale_lut(TRasterPT rout, TRasterPT rin, const double *a, + const double *k, const int *out0, const int *out1) { + assert(rout->getSize() == rin->getSize()); + + typedef typename T::Channel Channel; + int m, max = T::maxChannelValue, chanValuesCount = max + 1; + + int fac = chanValuesCount / 256; + int out0R = std::max(fac * out0[0], 0), + out1R = std::min(fac * out1[0], T::maxChannelValue); + int out0G = std::max(fac * out0[1], 0), + out1G = std::min(fac * out1[1], T::maxChannelValue); + int out0B = std::max(fac * out0[2], 0), + out1B = std::min(fac * out1[2], T::maxChannelValue); + int out0M = std::max(fac * out0[3], 0), + out1M = std::min(fac * out1[3], T::maxChannelValue); + + // Build luts + Channel *lut_r = new Channel[chanValuesCount]; + buildLUT(lut_r, a[0], k[0], out0R, out1R); + + Channel *lut_g = new Channel[chanValuesCount]; + buildLUT(lut_g, a[1], k[1], out0G, out1G); + + Channel *lut_b = new Channel[chanValuesCount]; + buildLUT(lut_b, a[2], k[2], out0B, out1B); + + Channel *lut_m = new Channel[chanValuesCount]; + buildLUT(lut_m, a[3], k[3], out0M, out1M); + + // Retrieve de/premultiplication luts + const double *lut_prem = premultiplyTable(); + const double *lut_deprem = depremultiplyTable(); + double premFac, depremFac; + + // Process raster + int y, lx = rin->getLx(), ly = rin->getLy(); + T *in, *end, *out; + + for (y = 0; y < ly; ++y) { + in = rin->pixels(y), end = in + lx, out = rout->pixels(y); + for (; in < end; ++in, ++out) { + m = lut_m[in->m]; + depremFac = lut_deprem[in->m]; + premFac = lut_prem[m]; + + out->r = premFac * lut_r[std::min((int)(in->r * depremFac), max)]; + out->g = premFac * lut_g[std::min((int)(in->g * depremFac), max)]; + out->b = premFac * lut_b[std::min((int)(in->b * depremFac), max)]; + out->m = m; + } + } + + delete[] lut_r; + delete[] lut_g; + delete[] lut_b; + delete[] lut_m; } //----------------------------------------------------------------------------- template -void do_rgbmScale(TRasterPT rout, TRasterPT rin, - const double *a, const double *k, - const int *out0, const int *out1) -{ - assert(rout->getSize() == rin->getSize()); - - typedef typename T::Channel Channel; - int m, chanValuesCount = T::maxChannelValue + 1; - - int fac = chanValuesCount / 256; - - int out0R = std::max(fac * out0[0], 0), out1R = std::min(fac * out1[0], T::maxChannelValue); - int out0G = std::max(fac * out0[1], 0), out1G = std::min(fac * out1[1], T::maxChannelValue); - int out0B = std::max(fac * out0[2], 0), out1B = std::min(fac * out1[2], T::maxChannelValue); - int out0M = std::max(fac * out0[3], 0), out1M = std::min(fac * out1[3], T::maxChannelValue); - - //Retrieve de/premultiplication luts - const double *lut_prem = premultiplyTable(); - const double *lut_deprem = depremultiplyTable(); - double premFac, depremFac; - - //Process raster - int y, lx = rin->getLx(), ly = rin->getLy(); - T *in, *end, *out; - - for (y = 0; y < ly; ++y) { - in = rin->pixels(y), end = in + lx, out = rout->pixels(y); - for (; in < end; ++in, ++out) { - m = tcrop((int)(a[3] + k[3] * in->m), out0M, out1M); - depremFac = lut_deprem[in->m]; - premFac = lut_prem[m]; - - out->r = premFac * tcrop((int)(a[0] + k[0] * in->r * depremFac), out0R, out1R); - out->g = premFac * tcrop((int)(a[1] + k[1] * in->g * depremFac), out0G, out1G); - out->b = premFac * tcrop((int)(a[2] + k[2] * in->b * depremFac), out0B, out1B); - out->m = m; - } - } +void do_rgbmScale(TRasterPT rout, TRasterPT rin, const double *a, + const double *k, const int *out0, const int *out1) { + assert(rout->getSize() == rin->getSize()); + + typedef typename T::Channel Channel; + int m, chanValuesCount = T::maxChannelValue + 1; + + int fac = chanValuesCount / 256; + + int out0R = std::max(fac * out0[0], 0), + out1R = std::min(fac * out1[0], T::maxChannelValue); + int out0G = std::max(fac * out0[1], 0), + out1G = std::min(fac * out1[1], T::maxChannelValue); + int out0B = std::max(fac * out0[2], 0), + out1B = std::min(fac * out1[2], T::maxChannelValue); + int out0M = std::max(fac * out0[3], 0), + out1M = std::min(fac * out1[3], T::maxChannelValue); + + // Retrieve de/premultiplication luts + const double *lut_prem = premultiplyTable(); + const double *lut_deprem = depremultiplyTable(); + double premFac, depremFac; + + // Process raster + int y, lx = rin->getLx(), ly = rin->getLy(); + T *in, *end, *out; + + for (y = 0; y < ly; ++y) { + in = rin->pixels(y), end = in + lx, out = rout->pixels(y); + for (; in < end; ++in, ++out) { + m = tcrop((int)(a[3] + k[3] * in->m), out0M, out1M); + depremFac = lut_deprem[in->m]; + premFac = lut_prem[m]; + + out->r = + premFac * tcrop((int)(a[0] + k[0] * in->r * depremFac), out0R, out1R); + out->g = + premFac * tcrop((int)(a[1] + k[1] * in->g * depremFac), out0G, out1G); + out->b = + premFac * tcrop((int)(a[2] + k[2] * in->b * depremFac), out0B, out1B); + out->m = m; + } + } } //----------------------------------------------------------------------------- template void do_rgbmAdjust(TRasterPT rout, TRasterPT rin, ScaleFunc scaleFunc, - const int *in0, const int *in1, const int *out0, const int *out1) -{ - assert(rout->getSize() == rin->getSize()); + const int *in0, const int *in1, const int *out0, + const int *out1) { + assert(rout->getSize() == rin->getSize()); - double a[5], k[5]; + double a[5], k[5]; - //Build scale parameters - int i; - for (i = 0; i < 5; ++i) { - k[i] = (out1[i] - out0[i]) / (double)(in1[i] - in0[i]); - a[i] = out0[i] - k[i] * in0[i]; - } - for (i = 1; i < 4; ++i) { - a[i] += k[i] * a[0]; - k[i] *= k[0]; - } + // Build scale parameters + int i; + for (i = 0; i < 5; ++i) { + k[i] = (out1[i] - out0[i]) / (double)(in1[i] - in0[i]); + a[i] = out0[i] - k[i] * in0[i]; + } + for (i = 1; i < 4; ++i) { + a[i] += k[i] * a[0]; + k[i] *= k[0]; + } - //Ensure that the output is cropped according to output params - int out0i[4], out1i[4]; + // Ensure that the output is cropped according to output params + int out0i[4], out1i[4]; - out0i[0] = std::max(out0[0], tcrop((int)(a[0] + k[0] * out0[1]), 0, 255)); - out1i[0] = std::min(out1[0], tcrop((int)(a[0] + k[0] * out1[1]), 0, 255)); + out0i[0] = std::max(out0[0], tcrop((int)(a[0] + k[0] * out0[1]), 0, 255)); + out1i[0] = std::min(out1[0], tcrop((int)(a[0] + k[0] * out1[1]), 0, 255)); - out0i[1] = std::max(out0[0], tcrop((int)(a[0] + k[0] * out0[2]), 0, 255)); - out1i[1] = std::min(out1[0], tcrop((int)(a[0] + k[0] * out1[2]), 0, 255)); + out0i[1] = std::max(out0[0], tcrop((int)(a[0] + k[0] * out0[2]), 0, 255)); + out1i[1] = std::min(out1[0], tcrop((int)(a[0] + k[0] * out1[2]), 0, 255)); - out0i[2] = std::max(out0[0], tcrop((int)(a[0] + k[0] * out0[3]), 0, 255)); - out1i[2] = std::min(out1[0], tcrop((int)(a[0] + k[0] * out1[3]), 0, 255)); + out0i[2] = std::max(out0[0], tcrop((int)(a[0] + k[0] * out0[3]), 0, 255)); + out1i[2] = std::min(out1[0], tcrop((int)(a[0] + k[0] * out1[3]), 0, 255)); - out0i[3] = out0[4]; - out1i[3] = out1[4]; + out0i[3] = out0[4]; + out1i[3] = out1[4]; - scaleFunc(rout, rin, &a[1], &k[1], out0i, out1i); + scaleFunc(rout, rin, &a[1], &k[1], out0i, out1i); } -} //namespace +} // namespace //----------------------------------------------------------------------------- -void TRop::rgbmScale(TRasterP rout, TRasterP rin, - const double *k, const double *a, const int *out0, const int *out1) -{ - if (rout->getSize() != rin->getSize()) - throw TRopException("size mismatch"); - - rout->lock(); - rin->lock(); - - if ((TRaster32P)rout && (TRaster32P)rin) - do_rgbmScale_lut(rout, rin, a, k, out0, out1); - else if ((TRaster64P)rout && (TRaster64P)rin) { - if (rin->getLx() * rin->getLy() < TPixel64::maxChannelValue) - do_rgbmScale(rout, rin, a, k, out0, out1); - else - do_rgbmScale_lut(rout, rin, a, k, out0, out1); - } else if ((TRasterGR8P)rout && (TRasterGR8P)rin) - do_greyScale_lut(rout, rin, a[0], k[0], out0[0], out1[0]); - else if ((TRasterGR16P)rout && (TRasterGR16P)rin) - do_greyScale_lut(rout, rin, a[0], k[0], out0[0], out1[0]); - else { - rout->unlock(); - rin->unlock(); - throw TRopException("pixel type mismatch"); - } - - rout->unlock(); - rin->unlock(); +void TRop::rgbmScale(TRasterP rout, TRasterP rin, const double *k, + const double *a, const int *out0, const int *out1) { + if (rout->getSize() != rin->getSize()) throw TRopException("size mismatch"); + + rout->lock(); + rin->lock(); + + if ((TRaster32P)rout && (TRaster32P)rin) + do_rgbmScale_lut(rout, rin, a, k, out0, out1); + else if ((TRaster64P)rout && (TRaster64P)rin) { + if (rin->getLx() * rin->getLy() < TPixel64::maxChannelValue) + do_rgbmScale(rout, rin, a, k, out0, out1); + else + do_rgbmScale_lut(rout, rin, a, k, out0, out1); + } else if ((TRasterGR8P)rout && (TRasterGR8P)rin) + do_greyScale_lut(rout, rin, a[0], k[0], out0[0], out1[0]); + else if ((TRasterGR16P)rout && (TRasterGR16P)rin) + do_greyScale_lut(rout, rin, a[0], k[0], out0[0], out1[0]); + else { + rout->unlock(); + rin->unlock(); + throw TRopException("pixel type mismatch"); + } + + rout->unlock(); + rin->unlock(); } //----------------------------------------------------------------------------- -void TRop::rgbmScale(TRasterP rout, TRasterP rin, - double kr, double kg, double kb, double km, - double ar, double ag, double ab, double am) -{ - double k[4], a[4]; +void TRop::rgbmScale(TRasterP rout, TRasterP rin, double kr, double kg, + double kb, double km, double ar, double ag, double ab, + double am) { + double k[4], a[4]; - a[0] = ar, a[1] = ag, a[2] = ab, a[3] = am; - k[0] = kr, k[1] = kg, k[2] = kb, k[3] = km; + a[0] = ar, a[1] = ag, a[2] = ab, a[3] = am; + k[0] = kr, k[1] = kg, k[2] = kb, k[3] = km; - int out0[4], out1[4]; + int out0[4], out1[4]; - out0[0] = out0[1] = out0[2] = out0[3] = 0; - out1[0] = out1[1] = out1[2] = out1[3] = 255; + out0[0] = out0[1] = out0[2] = out0[3] = 0; + out1[0] = out1[1] = out1[2] = out1[3] = 255; - rgbmScale(rout, rin, k, a, out0, out1); + rgbmScale(rout, rin, k, a, out0, out1); } //----------------------------------------------------------------------------- -void TRop::rgbmAdjust(TRasterP rout, TRasterP rin, - const int *in0, const int *in1, const int *out0, const int *out1) -{ - if (rout->getSize() != rin->getSize()) - throw TRopException("size mismatch"); - - rout->lock(); - rin->lock(); - - if ((TRaster32P)rout && (TRaster32P)rin) - do_rgbmAdjust(rout, rin, &do_rgbmScale_lut, in0, in1, out0, out1); - else if ((TRaster64P)rout && (TRaster64P)rin) { - if (rin->getLx() * rin->getLy() < TPixel64::maxChannelValue) - do_rgbmAdjust(rout, rin, &do_rgbmScale, in0, in1, out0, out1); - else - do_rgbmAdjust(rout, rin, &do_rgbmScale_lut, in0, in1, out0, out1); - } else if ((TRasterGR8P)rout && (TRasterGR8P)rin) - do_greyAdjust(rout, rin, in0[0], in1[0], out0[0], out1[0]); - else if ((TRasterGR16P)rout && (TRasterGR16P)rin) - do_greyAdjust(rout, rin, in0[0], in1[0], out0[0], out1[0]); - else { - rout->unlock(); - rin->unlock(); - throw TRopException("pixel type mismatch"); - } - - rout->unlock(); - rin->unlock(); +void TRop::rgbmAdjust(TRasterP rout, TRasterP rin, const int *in0, + const int *in1, const int *out0, const int *out1) { + if (rout->getSize() != rin->getSize()) throw TRopException("size mismatch"); + + rout->lock(); + rin->lock(); + + if ((TRaster32P)rout && (TRaster32P)rin) + do_rgbmAdjust(rout, rin, &do_rgbmScale_lut, in0, in1, + out0, out1); + else if ((TRaster64P)rout && (TRaster64P)rin) { + if (rin->getLx() * rin->getLy() < TPixel64::maxChannelValue) + do_rgbmAdjust(rout, rin, &do_rgbmScale, in0, in1, + out0, out1); + else + do_rgbmAdjust(rout, rin, &do_rgbmScale_lut, in0, in1, + out0, out1); + } else if ((TRasterGR8P)rout && (TRasterGR8P)rin) + do_greyAdjust(rout, rin, in0[0], in1[0], out0[0], out1[0]); + else if ((TRasterGR16P)rout && (TRasterGR16P)rin) + do_greyAdjust(rout, rin, in0[0], in1[0], out0[0], out1[0]); + else { + rout->unlock(); + rin->unlock(); + throw TRopException("pixel type mismatch"); + } + + rout->unlock(); + rin->unlock(); } diff --git a/toonz/sources/common/trop/trop.cpp b/toonz/sources/common/trop/trop.cpp index e6b7fd5..9f51fad 100644 --- a/toonz/sources/common/trop/trop.cpp +++ b/toonz/sources/common/trop/trop.cpp @@ -10,420 +10,386 @@ #include "ttoonzimage.h" #endif -TString TRopException::getMessage() const -{ - return ::to_wstring(message); -} - -namespace -{ - -bool isOpaque32(TRaster32P &ras) -{ - ras->lock(); - UCHAR *m0 = &(ras->pixels()->m); - if (0 < m0[0] && m0[0] < 255) - return false; - - int wrap4 = ras->getWrap() * 4; - int lx4 = ras->getLx() * 4; - const UCHAR cm = *m0; - int nrows = ras->getLy(); - while (nrows-- > 0) { - UCHAR *m1 = m0 + lx4; - UCHAR *m = m0; - while (m < m1 && *m == cm) - m += 4; - if (m < m1) - break; - m0 += wrap4; - } - ras->unlock(); - return (nrows <= 0); - - //m_image->setOpaqueFlag(true); +TString TRopException::getMessage() const { return ::to_wstring(message); } + +namespace { + +bool isOpaque32(TRaster32P &ras) { + ras->lock(); + UCHAR *m0 = &(ras->pixels()->m); + if (0 < m0[0] && m0[0] < 255) return false; + + int wrap4 = ras->getWrap() * 4; + int lx4 = ras->getLx() * 4; + const UCHAR cm = *m0; + int nrows = ras->getLy(); + while (nrows-- > 0) { + UCHAR *m1 = m0 + lx4; + UCHAR *m = m0; + while (m < m1 && *m == cm) m += 4; + if (m < m1) break; + m0 += wrap4; + } + ras->unlock(); + return (nrows <= 0); + + // m_image->setOpaqueFlag(true); } -} //namespace +} // namespace -bool TRop::isOpaque(TRasterP ras) -{ - TRaster32P ras32 = ras; - if (ras32) - return isOpaque32(ras32); - else if (TRasterGR8P(ras)) - return true; - else - throw TRopException("isOpaque: unsupported pixel type"); +bool TRop::isOpaque(TRasterP ras) { + TRaster32P ras32 = ras; + if (ras32) + return isOpaque32(ras32); + else if (TRasterGR8P(ras)) + return true; + else + throw TRopException("isOpaque: unsupported pixel type"); } #ifdef TNZ_MACHINE_CHANNEL_ORDER_MRGB -void TRop::swapRBChannels(const TRaster32P &r) -{ - int lx = r->getLx(); - int y = r->getLy(); - r->lock(); - while (--y >= 0) { - TPixel32 *pix = r->pixels(y); - TPixel32 *endPix = pix + lx; - while (pix < endPix) { - tswap(pix->r, pix->b); - ++pix; - } - } - r->unlock(); +void TRop::swapRBChannels(const TRaster32P &r) { + int lx = r->getLx(); + int y = r->getLy(); + r->lock(); + while (--y >= 0) { + TPixel32 *pix = r->pixels(y); + TPixel32 *endPix = pix + lx; + while (pix < endPix) { + tswap(pix->r, pix->b); + ++pix; + } + } + r->unlock(); } #endif -TRaster32P TRop::copyAndSwapRBChannels(const TRaster32P &srcRaster) -{ - TRaster32P newRaster(srcRaster->getSize()); - int lx = srcRaster->getLx(); - int y = srcRaster->getLy(); - srcRaster->lock(); - newRaster->lock(); - while (--y >= 0) { - TPixel32 *pix = srcRaster->pixels(y); - TPixel32 *newpix = newRaster->pixels(y); - TPixel32 *endPix = pix + lx; - while (pix < endPix) { - newpix->r = pix->b; - newpix->g = pix->g; - newpix->b = pix->r; - newpix->m = pix->m; - ++pix; - ++newpix; - } - } - srcRaster->unlock(); - newRaster->unlock(); - - return newRaster; +TRaster32P TRop::copyAndSwapRBChannels(const TRaster32P &srcRaster) { + TRaster32P newRaster(srcRaster->getSize()); + int lx = srcRaster->getLx(); + int y = srcRaster->getLy(); + srcRaster->lock(); + newRaster->lock(); + while (--y >= 0) { + TPixel32 *pix = srcRaster->pixels(y); + TPixel32 *newpix = newRaster->pixels(y); + TPixel32 *endPix = pix + lx; + while (pix < endPix) { + newpix->r = pix->b; + newpix->g = pix->g; + newpix->b = pix->r; + newpix->m = pix->m; + ++pix; + ++newpix; + } + } + srcRaster->unlock(); + newRaster->unlock(); + + return newRaster; } -void TRop::copy(TRasterP dst, const TRasterP &src) -{ - assert(!((TRasterCM32P)src) || (TRasterCM32P)dst); - if (dst->getPixelSize() == src->getPixelSize()) - dst->copy(src); - else { - if (dst->getBounds() != src->getBounds()) { - TRect rect = dst->getBounds() * src->getBounds(); - if (rect.isEmpty()) - return; - TRop::convert(dst->extract(rect), src->extract(rect)); - } else - TRop::convert(dst, src); - } +void TRop::copy(TRasterP dst, const TRasterP &src) { + assert(!((TRasterCM32P)src) || (TRasterCM32P)dst); + if (dst->getPixelSize() == src->getPixelSize()) + dst->copy(src); + else { + if (dst->getBounds() != src->getBounds()) { + TRect rect = dst->getBounds() * src->getBounds(); + if (rect.isEmpty()) return; + TRop::convert(dst->extract(rect), src->extract(rect)); + } else + TRop::convert(dst, src); + } } //------------------------------------------------------------------- -namespace -{ +namespace { template -class Gamma_Lut -{ - +class Gamma_Lut { public: - std::vector m_table; - Gamma_Lut(int insteps, int outsteps, double gamma) - { - double inspace = (double)(insteps); - for (int i = 0; i <= insteps; i++) - m_table.push_back((Q)((outsteps) * - (pow(i / inspace, 1.0 / gamma)) + - 0.5)); - } + std::vector m_table; + Gamma_Lut(int insteps, int outsteps, double gamma) { + double inspace = (double)(insteps); + for (int i = 0; i <= insteps; i++) + m_table.push_back( + (Q)((outsteps) * (pow(i / inspace, 1.0 / gamma)) + 0.5)); + } }; template -void doGammaCorrect(TRasterPT raster, double gamma) +void doGammaCorrect(TRasterPT raster, double gamma) { + Gamma_Lut lut(T::maxChannelValue, T::maxChannelValue, gamma); + + int j; + for (j = 0; j < raster->getLy(); j++) { + T *pix = raster->pixels(j); + T *endPix = pix + raster->getLx(); + while (pix < endPix) { + pix->r = lut.m_table[pix->r]; + pix->b = lut.m_table[pix->b]; + pix->g = lut.m_table[pix->g]; + /*if(pix->m != T::maxChannelValue) { - Gamma_Lut lut(T::maxChannelValue, T::maxChannelValue, gamma); - - int j; - for (j = 0; j < raster->getLy(); j++) { - T *pix = raster->pixels(j); - T *endPix = pix + raster->getLx(); - while (pix < endPix) { - pix->r = lut.m_table[pix->r]; - pix->b = lut.m_table[pix->b]; - pix->g = lut.m_table[pix->g]; - /*if(pix->m != T::maxChannelValue) - { - pix->r= pix->r*pix->m/T::maxChannelValue; - pix->g= pix->g*pix->m/T::maxChannelValue; - pix->b= pix->b*pix->m/T::maxChannelValue; - }*/ - *pix++; - } - } +pix->r= pix->r*pix->m/T::maxChannelValue; +pix->g= pix->g*pix->m/T::maxChannelValue; +pix->b= pix->b*pix->m/T::maxChannelValue; +}*/ + *pix++; + } + } } template -void doGammaCorrectRGBM(TRasterPT raster, double gammar, double gammag, double gammab, double gammam) +void doGammaCorrectRGBM(TRasterPT raster, double gammar, double gammag, + double gammab, double gammam) { + Gamma_Lut lutr(T::maxChannelValue, T::maxChannelValue, gammar); + Gamma_Lut lutg(T::maxChannelValue, T::maxChannelValue, gammag); + Gamma_Lut lutb(T::maxChannelValue, T::maxChannelValue, gammab); + Gamma_Lut lutm(T::maxChannelValue, T::maxChannelValue, gammam); + int j; + for (j = 0; j < raster->getLy(); j++) { + T *pix = raster->pixels(j); + T *endPix = pix + raster->getLx(); + while (pix < endPix) { + pix->r = lutr.m_table[pix->r]; + pix->g = lutg.m_table[pix->g]; + pix->b = lutb.m_table[pix->b]; + pix->m = lutm.m_table[pix->m]; + /*if(pix->m != T::maxChannelValue) { - Gamma_Lut lutr(T::maxChannelValue, T::maxChannelValue, gammar); - Gamma_Lut lutg(T::maxChannelValue, T::maxChannelValue, gammag); - Gamma_Lut lutb(T::maxChannelValue, T::maxChannelValue, gammab); - Gamma_Lut lutm(T::maxChannelValue, T::maxChannelValue, gammam); - int j; - for (j = 0; j < raster->getLy(); j++) { - T *pix = raster->pixels(j); - T *endPix = pix + raster->getLx(); - while (pix < endPix) { - pix->r = lutr.m_table[pix->r]; - pix->g = lutg.m_table[pix->g]; - pix->b = lutb.m_table[pix->b]; - pix->m = lutm.m_table[pix->m]; - /*if(pix->m != T::maxChannelValue) - { - pix->r= pix->r*pix->m/T::maxChannelValue; - pix->g= pix->g*pix->m/T::maxChannelValue; - pix->b= pix->b*pix->m/T::maxChannelValue; - }*/ - *pix++; - } - } +pix->r= pix->r*pix->m/T::maxChannelValue; +pix->g= pix->g*pix->m/T::maxChannelValue; +pix->b= pix->b*pix->m/T::maxChannelValue; +}*/ + *pix++; + } + } } } //------------------------------------------------------------------- -void TRop::gammaCorrect(TRasterP raster, double gamma) -{ - if (gamma <= 0) - gamma = 0.01; - raster->lock(); - - if ((TRaster32P)raster) - doGammaCorrect(raster, gamma); - else if ((TRaster64P)raster) - doGammaCorrect(raster, gamma); - else { - raster->unlock(); - throw TRopException("isOpaque: unsupported pixel type"); - } - raster->unlock(); +void TRop::gammaCorrect(TRasterP raster, double gamma) { + if (gamma <= 0) gamma = 0.01; + raster->lock(); + + if ((TRaster32P)raster) + doGammaCorrect(raster, gamma); + else if ((TRaster64P)raster) + doGammaCorrect(raster, gamma); + else { + raster->unlock(); + throw TRopException("isOpaque: unsupported pixel type"); + } + raster->unlock(); } //------------------------------------------------------------------- void TRop::gammaCorrectRGBM(TRasterP raster, double gammar, double gammag, - double gammab, double gammam) -{ - if (gammar <= 0) - gammar = 0.01; - if (gammag <= 0) - gammag = 0.01; - if (gammab <= 0) - gammab = 0.01; - if (gammam <= 0) - gammam = 0.01; - - raster->lock(); - - if ((TRaster32P)raster) - doGammaCorrectRGBM(raster, gammar, gammag, gammab, gammam); - else if ((TRaster64P)raster) - doGammaCorrectRGBM(raster, gammar, gammag, gammab, gammam); - else { - raster->unlock(); - throw TRopException("isOpaque: unsupported pixel type"); - } - raster->unlock(); + double gammab, double gammam) { + if (gammar <= 0) gammar = 0.01; + if (gammag <= 0) gammag = 0.01; + if (gammab <= 0) gammab = 0.01; + if (gammam <= 0) gammam = 0.01; + + raster->lock(); + + if ((TRaster32P)raster) + doGammaCorrectRGBM(raster, gammar, gammag, gammab, gammam); + else if ((TRaster64P)raster) + doGammaCorrectRGBM(raster, gammar, gammag, gammab, + gammam); + else { + raster->unlock(); + throw TRopException("isOpaque: unsupported pixel type"); + } + raster->unlock(); } //------------------------------------------------------------------- template -void doSetChannel(const TRasterPT &rin, const TRasterPT &rout, UCHAR channel, bool greytones) -{ - - int lx = rin->getLx(); - int ly = rout->getLy(); - - int i, j; - for (i = 0; i < ly; i++) { - T *pixin = rin->pixels(i); - T *pixout = rout->pixels(i); - if (greytones || channel == TRop::MChan) { - switch (channel) { - case TRop::RChan: - for (j = 0; j < lx; j++, pixin++, pixout++) - pixout->r = pixout->g = pixout->b = pixout->m = pixin->r; - break; - case TRop::GChan: - for (j = 0; j < lx; j++, pixin++, pixout++) - pixout->r = pixout->g = pixout->b = pixout->m = pixin->g; - break; - case TRop::BChan: - for (j = 0; j < lx; j++, pixin++, pixout++) - pixout->r = pixout->g = pixout->b = pixout->m = pixin->b; - break; - case TRop::MChan: - for (j = 0; j < lx; j++, pixin++, pixout++) - pixout->r = pixout->g = pixout->b = pixout->m = pixin->m; - break; - default: - assert(false); - } - } else { - for (j = 0; j < lx; j++, pixin++, pixout++) { - pixout->r = channel & TRop::RChan ? pixin->r : 0; - pixout->b = channel & TRop::BChan ? pixin->b : 0; - pixout->g = channel & TRop::GChan ? pixin->g : 0; - } - } - } +void doSetChannel(const TRasterPT &rin, const TRasterPT &rout, + UCHAR channel, bool greytones) { + int lx = rin->getLx(); + int ly = rout->getLy(); + + int i, j; + for (i = 0; i < ly; i++) { + T *pixin = rin->pixels(i); + T *pixout = rout->pixels(i); + if (greytones || channel == TRop::MChan) { + switch (channel) { + case TRop::RChan: + for (j = 0; j < lx; j++, pixin++, pixout++) + pixout->r = pixout->g = pixout->b = pixout->m = pixin->r; + break; + case TRop::GChan: + for (j = 0; j < lx; j++, pixin++, pixout++) + pixout->r = pixout->g = pixout->b = pixout->m = pixin->g; + break; + case TRop::BChan: + for (j = 0; j < lx; j++, pixin++, pixout++) + pixout->r = pixout->g = pixout->b = pixout->m = pixin->b; + break; + case TRop::MChan: + for (j = 0; j < lx; j++, pixin++, pixout++) + pixout->r = pixout->g = pixout->b = pixout->m = pixin->m; + break; + default: + assert(false); + } + } else { + for (j = 0; j < lx; j++, pixin++, pixout++) { + pixout->r = channel & TRop::RChan ? pixin->r : 0; + pixout->b = channel & TRop::BChan ? pixin->b : 0; + pixout->g = channel & TRop::GChan ? pixin->g : 0; + } + } + } } //------------------------------------------------------------------- -void TRop::setChannel(const TRasterP &rin, TRasterP rout, UCHAR chan, bool greytones) -{ - assert(rin->getSize() == rout->getSize()); +void TRop::setChannel(const TRasterP &rin, TRasterP rout, UCHAR chan, + bool greytones) { + assert(rin->getSize() == rout->getSize()); - rout->lock(); + rout->lock(); - if ((TRaster32P)rin && (TRaster32P)rout) - doSetChannel(rin, rout, chan, greytones); - else if ((TRaster64P)rin && (TRaster64P)rout) - doSetChannel(rin, rout, chan, greytones); - else { - rout->unlock(); - throw TRopException("setChannel: unsupported pixel type"); - } + if ((TRaster32P)rin && (TRaster32P)rout) + doSetChannel(rin, rout, chan, greytones); + else if ((TRaster64P)rin && (TRaster64P)rout) + doSetChannel(rin, rout, chan, greytones); + else { + rout->unlock(); + throw TRopException("setChannel: unsupported pixel type"); + } - rout->unlock(); + rout->unlock(); } //------------------------------------------------------------------- -TRasterP TRop::shrink(TRasterP rin, int shrink) -{ - int pixelSize = rin->getPixelSize(); - - int lx = (rin->getLx() - 1) / shrink + 1; - int ly = (rin->getLy() - 1) / shrink + 1; - - TRasterP rout; - - if ((TRaster32P)rin) - rout = TRaster32P(lx, ly); - else if ((TRaster64P)rin) - rout = TRaster64P(lx, ly); - if ((TRasterCM32P)rin) - rout = TRasterCM32P(lx, ly); - if ((TRasterGR8P)rin) - rout = TRasterGR8P(lx, ly); - - int i, j; - - for (i = 0; i < ly; i++) { - UCHAR *bufin = (UCHAR *)rin->getRawData() + (i * shrink) * rin->getWrap() * pixelSize; - UCHAR *bufout = (UCHAR *)rout->getRawData() + i * rout->getWrap() * pixelSize; - for (j = 0; j < lx; j++) { - memcpy(bufout, bufin, pixelSize); - bufin += shrink * pixelSize; - bufout += pixelSize; - } - } - return rout; +TRasterP TRop::shrink(TRasterP rin, int shrink) { + int pixelSize = rin->getPixelSize(); + + int lx = (rin->getLx() - 1) / shrink + 1; + int ly = (rin->getLy() - 1) / shrink + 1; + + TRasterP rout; + + if ((TRaster32P)rin) + rout = TRaster32P(lx, ly); + else if ((TRaster64P)rin) + rout = TRaster64P(lx, ly); + if ((TRasterCM32P)rin) rout = TRasterCM32P(lx, ly); + if ((TRasterGR8P)rin) rout = TRasterGR8P(lx, ly); + + int i, j; + + for (i = 0; i < ly; i++) { + UCHAR *bufin = + (UCHAR *)rin->getRawData() + (i * shrink) * rin->getWrap() * pixelSize; + UCHAR *bufout = + (UCHAR *)rout->getRawData() + i * rout->getWrap() * pixelSize; + for (j = 0; j < lx; j++) { + memcpy(bufout, bufin, pixelSize); + bufin += shrink * pixelSize; + bufout += pixelSize; + } + } + return rout; } //------------------------------------------------------------------- template -void doMakeStereoRaster(const TRasterPT &rleft, const TRasterPT &rright) -{ - - int lx = rleft->getLx(); - int ly = rright->getLy(); - - for (int i = 0; i < ly; i++) { - T *pixl = rleft->pixels(i); - T *pixr = rright->pixels(i); - - for (int j = 0; j < lx; j++, pixl++, pixr++) { - pixl->g = pixr->g; - pixl->b = pixr->b; - } - } +void doMakeStereoRaster(const TRasterPT &rleft, const TRasterPT &rright) { + int lx = rleft->getLx(); + int ly = rright->getLy(); + + for (int i = 0; i < ly; i++) { + T *pixl = rleft->pixels(i); + T *pixr = rright->pixels(i); + + for (int j = 0; j < lx; j++, pixl++, pixr++) { + pixl->g = pixr->g; + pixl->b = pixr->b; + } + } } //--------------------------------------- -void TRop::makeStereoRaster(const TRasterP &left, const TRasterP &right) -{ - assert(left->getSize() == right->getSize()); +void TRop::makeStereoRaster(const TRasterP &left, const TRasterP &right) { + assert(left->getSize() == right->getSize()); - left->lock(); + left->lock(); - if ((TRaster32P)left && (TRaster32P)right) - doMakeStereoRaster(left, right); - else if ((TRaster64P)left && (TRaster64P)right) - doMakeStereoRaster(left, right); - else { - left->unlock(); - throw TRopException("setChannel: unsupported pixel type"); - } + if ((TRaster32P)left && (TRaster32P)right) + doMakeStereoRaster(left, right); + else if ((TRaster64P)left && (TRaster64P)right) + doMakeStereoRaster(left, right); + else { + left->unlock(); + throw TRopException("setChannel: unsupported pixel type"); + } - left->unlock(); + left->unlock(); } //------------------------------------------------------------------- #ifndef TNZCORE_LIGHT -void TTile::addInCache(const TRasterP &raster) -{ - if (!raster) { - m_rasterId = ""; - return; - } - TRasterP rin; - - m_rasterId = TImageCache::instance()->getUniqueId(); - if (raster->getParent()) { - rin = raster->getParent(); - unsigned long offs = (raster->getRawData() - raster->getParent()->getRawData()) / raster->getPixelSize(); - m_subRect = TRect(TPoint(offs % raster->getWrap(), offs / raster->getWrap()), raster->getSize()); - } else { - m_subRect = raster->getBounds(); - rin = raster; - } - - if ((TRasterCM32P)rin) - TImageCache::instance()->add(m_rasterId, TToonzImageP(rin, rin->getBounds())); - else if ((TRaster32P)rin || (TRaster64P)rin) - TImageCache::instance()->add(m_rasterId, TRasterImageP(rin)); - else if ((TRasterGR8P)rin || (TRasterGR16P)rin) - TImageCache::instance()->add(m_rasterId, TRasterImageP(rin)); - else - assert(false); +void TTile::addInCache(const TRasterP &raster) { + if (!raster) { + m_rasterId = ""; + return; + } + TRasterP rin; + + m_rasterId = TImageCache::instance()->getUniqueId(); + if (raster->getParent()) { + rin = raster->getParent(); + unsigned long offs = + (raster->getRawData() - raster->getParent()->getRawData()) / + raster->getPixelSize(); + m_subRect = + TRect(TPoint(offs % raster->getWrap(), offs / raster->getWrap()), + raster->getSize()); + } else { + m_subRect = raster->getBounds(); + rin = raster; + } + + if ((TRasterCM32P)rin) + TImageCache::instance()->add(m_rasterId, + TToonzImageP(rin, rin->getBounds())); + else if ((TRaster32P)rin || (TRaster64P)rin) + TImageCache::instance()->add(m_rasterId, TRasterImageP(rin)); + else if ((TRasterGR8P)rin || (TRasterGR16P)rin) + TImageCache::instance()->add(m_rasterId, TRasterImageP(rin)); + else + assert(false); } -TTile::TTile(const TRasterP &raster) - : m_pos(), m_subRect() -{ - addInCache(raster); +TTile::TTile(const TRasterP &raster) : m_pos(), m_subRect() { + addInCache(raster); } -TTile::TTile(const TRasterP &raster, TPointD pos) - : m_pos(pos), m_subRect() -{ - addInCache(raster); +TTile::TTile(const TRasterP &raster, TPointD pos) : m_pos(pos), m_subRect() { + addInCache(raster); } -void TTile::setRaster(const TRasterP &raster) -{ - if (m_rasterId != "") - TImageCache::instance()->remove(m_rasterId); - m_subRect = TRect(); - addInCache(raster); +void TTile::setRaster(const TRasterP &raster) { + if (m_rasterId != "") TImageCache::instance()->remove(m_rasterId); + m_subRect = TRect(); + addInCache(raster); } -TTile::~TTile() -{ - if (!m_rasterId.empty()) - TImageCache::instance()->remove(m_rasterId); +TTile::~TTile() { + if (!m_rasterId.empty()) TImageCache::instance()->remove(m_rasterId); } #endif diff --git a/toonz/sources/common/trop/trop_borders.cpp b/toonz/sources/common/trop/trop_borders.cpp index 11baa40..c98415a 100644 --- a/toonz/sources/common/trop/trop_borders.cpp +++ b/toonz/sources/common/trop/trop_borders.cpp @@ -23,320 +23,286 @@ using namespace TRop::borders; -namespace -{ +namespace { //**************************************************************** // Container Reader for Borders Reader //**************************************************************** template -class WrapperReader -{ - TRop::borders::BordersReader &m_reader; +class WrapperReader { + TRop::borders::BordersReader &m_reader; public: - WrapperReader(TRop::borders::BordersReader &reader) - : m_reader(reader) {} - - void openContainer(const RasterEdgeIterator &it) - { - m_reader.openContainer(it.pos(), it.dir(), it.rightColor(), it.leftColor()); - } - void addElement(const RasterEdgeIterator &it) - { - m_reader.addElement(it.pos(), it.dir(), it.leftColor()); - } - void closeContainer() { m_reader.closeContainer(); } + WrapperReader(TRop::borders::BordersReader &reader) : m_reader(reader) {} + + void openContainer(const RasterEdgeIterator &it) { + m_reader.openContainer(it.pos(), it.dir(), it.rightColor(), it.leftColor()); + } + void addElement(const RasterEdgeIterator &it) { + m_reader.addElement(it.pos(), it.dir(), it.leftColor()); + } + void closeContainer() { m_reader.closeContainer(); } }; -} //namespace +} // namespace //**************************************************************** // Borders Extractor instantiations //**************************************************************** -namespace TRop -{ -namespace borders -{ +namespace TRop { +namespace borders { template -void readBorders_simple(const TRasterPT &raster, BordersReader &reader, bool onlyCorners) -{ - typedef PixelSelector pixel_selector; +void readBorders_simple(const TRasterPT &raster, BordersReader &reader, + bool onlyCorners) { + typedef PixelSelector pixel_selector; - pixel_selector selector(onlyCorners); - WrapperReader wrapReader(reader); + pixel_selector selector(onlyCorners); + WrapperReader wrapReader(reader); - raster->lock(); - readBorders(raster, selector, wrapReader); - raster->unlock(); + raster->lock(); + readBorders(raster, selector, wrapReader); + raster->unlock(); } //-------------------------------------------------------------------------------- void readBorders_simple(const TRasterGR8P &raster, BordersReader &reader, - const TPixelGR8 &transparencyColor, bool onlyCorners) -{ - typedef PixelSelector pixel_selector; + const TPixelGR8 &transparencyColor, bool onlyCorners) { + typedef PixelSelector pixel_selector; - pixel_selector selector(onlyCorners, transparencyColor); - WrapperReader wrapReader(reader); + pixel_selector selector(onlyCorners, transparencyColor); + WrapperReader wrapReader(reader); - raster->lock(); - readBorders(raster, selector, wrapReader); - raster->unlock(); + raster->lock(); + readBorders(raster, selector, wrapReader); + raster->unlock(); } //-------------------------------------------------------------------------------- void readBorders_simple(const TRasterGR16P &raster, BordersReader &reader, - const TPixelGR16 &transparencyColor, bool onlyCorners) -{ - typedef PixelSelector pixel_selector; + const TPixelGR16 &transparencyColor, bool onlyCorners) { + typedef PixelSelector pixel_selector; - pixel_selector selector(onlyCorners, transparencyColor); - WrapperReader wrapReader(reader); + pixel_selector selector(onlyCorners, transparencyColor); + WrapperReader wrapReader(reader); - raster->lock(); - readBorders(raster, selector, wrapReader); - raster->unlock(); + raster->lock(); + readBorders(raster, selector, wrapReader); + raster->unlock(); } //-------------------------------------------------------------------------------- void readBorders_simple(const TRasterCM32P &raster, BordersReader &reader, - bool onlyCorners, int toneThreshold) -{ - typedef PixelSelector pixel_selector; + bool onlyCorners, int toneThreshold) { + typedef PixelSelector pixel_selector; - pixel_selector selector(onlyCorners, toneThreshold); - WrapperReader wrapReader(reader); + pixel_selector selector(onlyCorners, toneThreshold); + WrapperReader wrapReader(reader); - raster->lock(); - readBorders(raster, selector, wrapReader); - raster->unlock(); + raster->lock(); + readBorders(raster, selector, wrapReader); + raster->unlock(); } //-------------------------------------------------------------------------------- -void readBorders_simple(const TRasterP &raster, BordersReader &reader, bool onlyCorners) -{ - TRaster32P ras32(raster); - if (ras32) { - readBorders_simple(ras32, reader, onlyCorners); - return; - } - - TRaster64P ras64(raster); - if (ras64) { - readBorders_simple(ras64, reader, onlyCorners); - return; - } - - TRasterCM32P rasCM32(raster); - if (rasCM32) { - readBorders_simple(rasCM32, reader, onlyCorners); - return; - } - - TRasterGR8P rasGR8(raster); - if (rasGR8) { - readBorders_simple(rasGR8, reader, onlyCorners); - return; - } - - TRasterGR16P rasGR16(raster); - if (rasGR16) { - readBorders_simple(rasGR16, reader, onlyCorners); - return; - } +void readBorders_simple(const TRasterP &raster, BordersReader &reader, + bool onlyCorners) { + TRaster32P ras32(raster); + if (ras32) { + readBorders_simple(ras32, reader, onlyCorners); + return; + } + + TRaster64P ras64(raster); + if (ras64) { + readBorders_simple(ras64, reader, onlyCorners); + return; + } + + TRasterCM32P rasCM32(raster); + if (rasCM32) { + readBorders_simple(rasCM32, reader, onlyCorners); + return; + } + + TRasterGR8P rasGR8(raster); + if (rasGR8) { + readBorders_simple(rasGR8, reader, onlyCorners); + return; + } + + TRasterGR16P rasGR16(raster); + if (rasGR16) { + readBorders_simple(rasGR16, reader, onlyCorners); + return; + } } } -} //namespace TRop::borders +} // namespace TRop::borders //**************************************************************** // Meshes Extraction (MeshesReader::Imp) //**************************************************************** -namespace TRop -{ -namespace borders -{ +namespace TRop { +namespace borders { -class TRop::borders::ImageMeshesReader::Imp -{ +class TRop::borders::ImageMeshesReader::Imp { public: - Face m_outerFace; - tcg::list m_meshes; + Face m_outerFace; + tcg::list m_meshes; - std::stack m_facesStack; + std::stack m_facesStack; - int m_facesCount, m_edgesCount; + int m_facesCount, m_edgesCount; public: - Imp() : m_facesCount(), m_edgesCount() {} + Imp() : m_facesCount(), m_edgesCount() {} - void clear() - { - assert(m_facesStack.empty()); + void clear() { + assert(m_facesStack.empty()); - m_outerFace = Face(); - m_meshes.clear(); - m_facesCount = m_edgesCount = 0; - } + m_outerFace = Face(); + m_meshes.clear(); + m_facesCount = m_edgesCount = 0; + } }; //**************************************************************** // Meshes Extraction (MeshesReader) //**************************************************************** -ImageMeshesReader::ImageMeshesReader() - : m_imp(new Imp) -{ -} +ImageMeshesReader::ImageMeshesReader() : m_imp(new Imp) {} //-------------------------------------------------------------------------------- -ImageMeshesReader::~ImageMeshesReader() -{ -} +ImageMeshesReader::~ImageMeshesReader() {} //-------------------------------------------------------------------------------- -void ImageMeshesReader::clear() -{ - m_imp->clear(); -} +void ImageMeshesReader::clear() { m_imp->clear(); } //-------------------------------------------------------------------------------- -const Face &ImageMeshesReader::outerFace() const -{ - return m_imp->m_outerFace; -} +const Face &ImageMeshesReader::outerFace() const { return m_imp->m_outerFace; } //-------------------------------------------------------------------------------- -Face &ImageMeshesReader::outerFace() -{ - return m_imp->m_outerFace; -} +Face &ImageMeshesReader::outerFace() { return m_imp->m_outerFace; } //-------------------------------------------------------------------------------- -const tcg::list &ImageMeshesReader::meshes() const -{ - return m_imp->m_meshes; +const tcg::list &ImageMeshesReader::meshes() const { + return m_imp->m_meshes; } //-------------------------------------------------------------------------------- -tcg::list &ImageMeshesReader::meshes() -{ - return m_imp->m_meshes; -} +tcg::list &ImageMeshesReader::meshes() { return m_imp->m_meshes; } //-------------------------------------------------------------------------------- -void ImageMeshesReader::openFace(ImageMesh *mesh, int faceIdx) -{ - Face &fc = mesh ? mesh->face(faceIdx) : m_imp->m_outerFace; - fc.imageIndex() = m_imp->m_facesCount++; - m_imp->m_facesStack.push(&fc); +void ImageMeshesReader::openFace(ImageMesh *mesh, int faceIdx) { + Face &fc = mesh ? mesh->face(faceIdx) : m_imp->m_outerFace; + fc.imageIndex() = m_imp->m_facesCount++; + m_imp->m_facesStack.push(&fc); } //-------------------------------------------------------------------------------- -void ImageMeshesReader::addMesh(ImageMesh *mesh) -{ - Face &fc = *m_imp->m_facesStack.top(); - fc.meshes().push_back(m_imp->m_meshes.push_back(mesh)); +void ImageMeshesReader::addMesh(ImageMesh *mesh) { + Face &fc = *m_imp->m_facesStack.top(); + fc.meshes().push_back(m_imp->m_meshes.push_back(mesh)); } //-------------------------------------------------------------------------------- -void ImageMeshesReader::closeFace() -{ - m_imp->m_facesStack.pop(); -} +void ImageMeshesReader::closeFace() { m_imp->m_facesStack.pop(); } //-------------------------------------------------------------------------------- -void ImageMeshesReader::closeEdge(ImageMesh *mesh, int edgeIdx) -{ - mesh->edge(edgeIdx).imageIndex() = m_imp->m_edgesCount++; +void ImageMeshesReader::closeEdge(ImageMesh *mesh, int edgeIdx) { + mesh->edge(edgeIdx).imageIndex() = m_imp->m_edgesCount++; } } -} // namespace TRop::borders +} // namespace TRop::borders //**************************************************************** // Meshes Extraction (traits) //**************************************************************** -namespace tcg -{ +namespace tcg { using namespace TRop::borders; // Reader traits template -struct container_reader_traits, ImageMesh::face_type> { - typedef ImageMeshesReaderT meshes_reader_type; - typedef typename meshes_reader_type::value_type value_type; +struct container_reader_traits, + ImageMesh::face_type> { + typedef ImageMeshesReaderT meshes_reader_type; + typedef typename meshes_reader_type::value_type value_type; public: - inline static void openContainer(meshes_reader_type &reader, ImageMesh *mesh, int faceIdx, const value_type &colorValue) - { - reader.openFace(mesh, faceIdx, colorValue); - } - inline static void addElement(meshes_reader_type &reader, ImageMesh *mesh) { reader.addMesh(mesh); } - inline static void closeContainer(meshes_reader_type &reader) { reader.closeFace(); } + inline static void openContainer(meshes_reader_type &reader, ImageMesh *mesh, + int faceIdx, const value_type &colorValue) { + reader.openFace(mesh, faceIdx, colorValue); + } + inline static void addElement(meshes_reader_type &reader, ImageMesh *mesh) { + reader.addMesh(mesh); + } + inline static void closeContainer(meshes_reader_type &reader) { + reader.closeFace(); + } }; template -struct container_reader_traits, ImageMesh::edge_type> { - typedef ImageMeshesReaderT meshes_reader_type; - typedef typename meshes_reader_type::raster_edge_iterator raster_edge_iterator; +struct container_reader_traits, + ImageMesh::edge_type> { + typedef ImageMeshesReaderT meshes_reader_type; + typedef + typename meshes_reader_type::raster_edge_iterator raster_edge_iterator; public: - inline static void openContainer(meshes_reader_type &reader, const raster_edge_iterator &it) - { - reader.openEdge(it); - } - inline static void addElement(meshes_reader_type &reader, const raster_edge_iterator &it) - { - reader.addVertex(it); - } - inline static void closeContainer(meshes_reader_type &reader, ImageMesh *mesh, int edgeIdx) - { - reader.closeEdge(mesh, edgeIdx); - } + inline static void openContainer(meshes_reader_type &reader, + const raster_edge_iterator &it) { + reader.openEdge(it); + } + inline static void addElement(meshes_reader_type &reader, + const raster_edge_iterator &it) { + reader.addVertex(it); + } + inline static void closeContainer(meshes_reader_type &reader, ImageMesh *mesh, + int edgeIdx) { + reader.closeEdge(mesh, edgeIdx); + } }; -} //namespace tcg +} // namespace tcg //**************************************************************** // Meshes Extraction (functions) //**************************************************************** -namespace TRop -{ -namespace borders -{ +namespace TRop { +namespace borders { template -void readMeshes(const TRasterPT &raster, ImageMeshesReaderT &reader) -{ - typedef PixelSelector pixel_selector; +void readMeshes(const TRasterPT &raster, ImageMeshesReaderT &reader) { + typedef PixelSelector pixel_selector; - reader.clear(); + reader.clear(); - raster->lock(); - readMeshes>(raster, reader.pixelSelector(), reader); - raster->unlock(); + raster->lock(); + readMeshes>( + raster, reader.pixelSelector(), reader); + raster->unlock(); } //-------------------------------------------------------------- @@ -349,10 +315,17 @@ template DV_EXPORT_API class RasterEdgeIterator>; template DV_EXPORT_API class RasterEdgeIterator>; template DV_EXPORT_API class RasterEdgeIterator>; -template DV_EXPORT_API void readMeshes(const TRasterPT &raster, ImageMeshesReaderT &reader); -template DV_EXPORT_API void readMeshes(const TRasterPT &raster, ImageMeshesReaderT &reader); -template DV_EXPORT_API void readMeshes(const TRasterPT &raster, ImageMeshesReaderT &reader); -template DV_EXPORT_API void readMeshes(const TRasterPT &raster, ImageMeshesReaderT &reader); -template DV_EXPORT_API void readMeshes(const TRasterPT &raster, ImageMeshesReaderT &reader); +template DV_EXPORT_API void readMeshes( + const TRasterPT &raster, ImageMeshesReaderT &reader); +template DV_EXPORT_API void readMeshes( + const TRasterPT &raster, ImageMeshesReaderT &reader); +template DV_EXPORT_API void readMeshes( + const TRasterPT &raster, ImageMeshesReaderT &reader); +template DV_EXPORT_API void readMeshes( + const TRasterPT &raster, + ImageMeshesReaderT &reader); +template DV_EXPORT_API void readMeshes( + const TRasterPT &raster, + ImageMeshesReaderT &reader); } -} //namespace TRop::borders +} // namespace TRop::borders diff --git a/toonz/sources/common/trop/tropcm.cpp b/toonz/sources/common/trop/tropcm.cpp index 350b2af..1e1a803 100644 --- a/toonz/sources/common/trop/tropcm.cpp +++ b/toonz/sources/common/trop/tropcm.cpp @@ -31,838 +31,842 @@ extern "C" { //--------------------------------------------------------- -namespace -{ +namespace { -__declspec(align(16)) class TPixelFloat -{ +__declspec(align(16)) class TPixelFloat { public: - TPixelFloat() : b(0), g(0), r(0), m(0) {} + TPixelFloat() : b(0), g(0), r(0), m(0) {} - TPixelFloat(float rr, float gg, float bb, float mm) - : b(bb), g(gg), r(rr), m(mm) {} + TPixelFloat(float rr, float gg, float bb, float mm) + : b(bb), g(gg), r(rr), m(mm) {} - TPixelFloat(const TPixel32 &pix) - : b(pix.b), g(pix.g), r(pix.r), m(pix.m) {} + TPixelFloat(const TPixel32 &pix) : b(pix.b), g(pix.g), r(pix.r), m(pix.m) {} - float b, g, r, m; + float b, g, r, m; }; -} // anonymous namespace +} // anonymous namespace #endif //----------------------------------------------------------------------------- -bool renderRas32(const TTile &tileOut, const TTile &tileIn, const TPaletteP palette); +bool renderRas32(const TTile &tileOut, const TTile &tileIn, + const TPaletteP palette); //----------------------------------------------------------------------------- const TPixel32 c_transparencyCheckPaint = TPixel32(80, 80, 80, 255); -const TPixel32 c_transparencyCheckInk = TPixel32::Black; +const TPixel32 c_transparencyCheckInk = TPixel32::Black; -void TRop::convert(const TRaster32P &rasOut, - const TRasterCM32P &rasIn, - const TPaletteP palette, - bool transparencyCheck) -{ - int count = palette->getStyleCount(); - int count2 = std::max({count, TPixelCM32::getMaxInk(), TPixelCM32::getMaxPaint()}); +void TRop::convert(const TRaster32P &rasOut, const TRasterCM32P &rasIn, + const TPaletteP palette, bool transparencyCheck) { + int count = palette->getStyleCount(); + int count2 = + std::max({count, TPixelCM32::getMaxInk(), TPixelCM32::getMaxPaint()}); - // per poter utilizzare lo switch (piu' efficiente) si utilizza 255 - // anziche' TPixelCM32::getMaxTone() - assert(TPixelCM32::getMaxTone() == 255); + // per poter utilizzare lo switch (piu' efficiente) si utilizza 255 + // anziche' TPixelCM32::getMaxTone() + assert(TPixelCM32::getMaxTone() == 255); - int rasLx = rasOut->getLx(); - int rasLy = rasOut->getLy(); + int rasLx = rasOut->getLx(); + int rasLy = rasOut->getLy(); - rasOut->lock(); - rasIn->lock(); + rasOut->lock(); + rasIn->lock(); #ifdef _WIN32 - if (TSystem::getCPUExtensions() & TSystem::CpuSupportsSse2) { - __m128i zeros = _mm_setzero_si128(); - TPixelFloat *paints = (TPixelFloat *)_aligned_malloc(count2 * sizeof(TPixelFloat), 16); - TPixelFloat *inks = (TPixelFloat *)_aligned_malloc(count2 * sizeof(TPixelFloat), 16); - - std::vector paints2(count2); - std::vector inks2(count2); - if (transparencyCheck) { - for (int i = 0; i < palette->getStyleCount(); i++) { - paints2[i] = c_transparencyCheckPaint; - inks2[i] = c_transparencyCheckInk; - paints[i] = TPixelFloat(paints2[i]); - inks[i] = TPixelFloat(inks2[i]); - } - paints2[0] = TPixel32::Transparent; - paints[0] = TPixelFloat(TPixel32::Transparent); - } - /* - else if (true) - { - for(int i=0;igetStyleCount();i++) - { + if (TSystem::getCPUExtensions() & TSystem::CpuSupportsSse2) { + __m128i zeros = _mm_setzero_si128(); + TPixelFloat *paints = + (TPixelFloat *)_aligned_malloc(count2 * sizeof(TPixelFloat), 16); + TPixelFloat *inks = + (TPixelFloat *)_aligned_malloc(count2 * sizeof(TPixelFloat), 16); + + std::vector paints2(count2); + std::vector inks2(count2); + if (transparencyCheck) { + for (int i = 0; i < palette->getStyleCount(); i++) { paints2[i] = c_transparencyCheckPaint; - inks2[i] = c_transparencyCheckInk; + inks2[i] = c_transparencyCheckInk; paints[i] = TPixelFloat(paints2[i]); - inks[i] = TPixelFloat(inks2[i]); - paints2[i] = TPixel32::Transparent; - paints[i] = TPixelFloat(TPixel32::Transparent); + inks[i] = TPixelFloat(inks2[i]); + } + paints2[0] = TPixel32::Transparent; + paints[0] = TPixelFloat(TPixel32::Transparent); + } + /* +else if (true) +{ + for(int i=0;igetStyleCount();i++) +{ +paints2[i] = c_transparencyCheckPaint; + inks2[i] = c_transparencyCheckInk; +paints[i] = TPixelFloat(paints2[i]); + inks[i] = TPixelFloat(inks2[i]); + paints2[i] = TPixel32::Transparent; + paints[i] = TPixelFloat(TPixel32::Transparent); +} + paints2[0] = TPixel32::Transparent; + paints[0] = TPixelFloat(TPixel32::Transparent); +} +*/ + else + for (int i = 0; i < palette->getStyleCount(); i++) { + TPixel32 color = ::premultiply(palette->getStyle(i)->getAverageColor()); + paints[i] = inks[i] = TPixelFloat(color); + paints2[i] = inks2[i] = color; + } + + float maxTone = (float)TPixelCM32::getMaxTone(); + __m128 den_packed = _mm_load1_ps(&maxTone); + + for (int y = 0; y < rasLy; ++y) { + TPixel32 *pix32 = rasOut->pixels(y); + TPixelCM32 *pixIn = rasIn->pixels(y); + + TPixelCM32 *endPixIn = pixIn + rasLx; + + while (pixIn < endPixIn) { + int tt = pixIn->getTone(); + int p = pixIn->getPaint(); + int i = pixIn->getInk(); + switch (tt) { + case 255: + *pix32++ = paints2[p]; + break; + case 0: + *pix32++ = inks2[i]; + break; + default: { + float t = (float)tt; + __m128 a_packed = _mm_load_ps((float *)&(inks[i])); + __m128 b_packed = _mm_load_ps((float *)&(paints[p])); + + __m128 num_packed = _mm_load1_ps(&t); + __m128 diff_packed = _mm_sub_ps(den_packed, num_packed); + + // calcola in modo vettoriale out = ((den-num)*a + num*b)/den + __m128 outPix_packed = _mm_mul_ps(diff_packed, a_packed); + __m128 tmpPix_packed = _mm_mul_ps(num_packed, b_packed); + + outPix_packed = _mm_add_ps(outPix_packed, tmpPix_packed); + outPix_packed = _mm_div_ps(outPix_packed, den_packed); + + // converte i canali da float a char + __m128i outPix_packed_i = _mm_cvtps_epi32(outPix_packed); + outPix_packed_i = _mm_packs_epi32(outPix_packed_i, zeros); + outPix_packed_i = _mm_packus_epi16(outPix_packed_i, zeros); + + *(DWORD *)(pix32) = _mm_cvtsi128_si32(outPix_packed_i); + ++pix32; } - paints2[0] = TPixel32::Transparent; - paints[0] = TPixelFloat(TPixel32::Transparent); - } - */ - else - for (int i = 0; i < palette->getStyleCount(); i++) { - TPixel32 color = ::premultiply(palette->getStyle(i)->getAverageColor()); - paints[i] = inks[i] = TPixelFloat(color); - paints2[i] = inks2[i] = color; - } - - float maxTone = (float)TPixelCM32::getMaxTone(); - __m128 den_packed = _mm_load1_ps(&maxTone); - - for (int y = 0; y < rasLy; ++y) { - TPixel32 *pix32 = rasOut->pixels(y); - TPixelCM32 *pixIn = rasIn->pixels(y); - - TPixelCM32 *endPixIn = pixIn + rasLx; - - while (pixIn < endPixIn) { - int tt = pixIn->getTone(); - int p = pixIn->getPaint(); - int i = pixIn->getInk(); - switch (tt) { - case 255: - *pix32++ = paints2[p]; - break; - case 0: - *pix32++ = inks2[i]; - break; - default: { - float t = (float)tt; - __m128 a_packed = _mm_load_ps((float *)&(inks[i])); - __m128 b_packed = _mm_load_ps((float *)&(paints[p])); - - __m128 num_packed = _mm_load1_ps(&t); - __m128 diff_packed = _mm_sub_ps(den_packed, num_packed); - - // calcola in modo vettoriale out = ((den-num)*a + num*b)/den - __m128 outPix_packed = _mm_mul_ps(diff_packed, a_packed); - __m128 tmpPix_packed = _mm_mul_ps(num_packed, b_packed); - - outPix_packed = _mm_add_ps(outPix_packed, tmpPix_packed); - outPix_packed = _mm_div_ps(outPix_packed, den_packed); - - // converte i canali da float a char - __m128i outPix_packed_i = _mm_cvtps_epi32(outPix_packed); - outPix_packed_i = _mm_packs_epi32(outPix_packed_i, zeros); - outPix_packed_i = _mm_packus_epi16(outPix_packed_i, zeros); - - *(DWORD *)(pix32) = _mm_cvtsi128_si32(outPix_packed_i); - ++pix32; - } - } - ++pixIn; - } - } - - _aligned_free(paints); - _aligned_free(inks); - - } else // SSE2 not supported -#endif // _WIN32 - { - - std::vector paints(count2, TPixel32(255, 0, 0)); - std::vector inks(count2, TPixel32(255, 0, 0)); - if (transparencyCheck) { - for (int i = 0; i < palette->getStyleCount(); i++) { - paints[i] = c_transparencyCheckPaint; - inks[i] = c_transparencyCheckInk; - } - paints[0] = TPixel32::Transparent; - } else - for (int i = 0; i < palette->getStyleCount(); i++) - paints[i] = inks[i] = ::premultiply(palette->getStyle(i)->getAverageColor()); - - for (int y = 0; y < rasLy; ++y) { - TPixel32 *pix32 = rasOut->pixels(y); - TPixelCM32 *pixIn = rasIn->pixels(y); - TPixelCM32 *endPixIn = pixIn + rasLx; - - while (pixIn < endPixIn) { - int t = pixIn->getTone(); - int p = pixIn->getPaint(); - int i = pixIn->getInk(); - - if (t == TPixelCM32::getMaxTone()) - *pix32++ = paints[p]; - else if (t == 0) - *pix32++ = inks[i]; - else - *pix32++ = blend(inks[i], paints[p], t, TPixelCM32::getMaxTone()); - - ++pixIn; - } - } - } - rasOut->unlock(); - rasIn->unlock(); + } + ++pixIn; + } + } + + _aligned_free(paints); + _aligned_free(inks); + + } else // SSE2 not supported +#endif // _WIN32 + { + + std::vector paints(count2, TPixel32(255, 0, 0)); + std::vector inks(count2, TPixel32(255, 0, 0)); + if (transparencyCheck) { + for (int i = 0; i < palette->getStyleCount(); i++) { + paints[i] = c_transparencyCheckPaint; + inks[i] = c_transparencyCheckInk; + } + paints[0] = TPixel32::Transparent; + } else + for (int i = 0; i < palette->getStyleCount(); i++) + paints[i] = inks[i] = + ::premultiply(palette->getStyle(i)->getAverageColor()); + + for (int y = 0; y < rasLy; ++y) { + TPixel32 *pix32 = rasOut->pixels(y); + TPixelCM32 *pixIn = rasIn->pixels(y); + TPixelCM32 *endPixIn = pixIn + rasLx; + + while (pixIn < endPixIn) { + int t = pixIn->getTone(); + int p = pixIn->getPaint(); + int i = pixIn->getInk(); + + if (t == TPixelCM32::getMaxTone()) + *pix32++ = paints[p]; + else if (t == 0) + *pix32++ = inks[i]; + else + *pix32++ = blend(inks[i], paints[p], t, TPixelCM32::getMaxTone()); + + ++pixIn; + } + } + } + rasOut->unlock(); + rasIn->unlock(); } //----------------------------------------------------------------------------------------------- -void do_convert(const TTile &dst, const TTile &src, - const TPaletteP palette, bool transparencyCheck, - bool applyFx) -{ - - //assert(palette); - //assert(_rasOut && _rasIn); - //assert(rasOut->getSize() == rasIn->getSize()); - - if (applyFx && renderRas32(dst, src, palette)) - return; - - TRaster32P rasOut; - TRasterCM32P rasIn; - - if (dst.getRaster()->getSize() != src.getRaster()->getSize()) { - TRect rect = TRect(convert(dst.m_pos), dst.getRaster()->getSize()) * TRect(convert(src.m_pos), src.getRaster()->getSize()); - TRect rectOut = rect - convert(dst.m_pos); - rasOut = dst.getRaster()->extract(rectOut); - TRect rectIn = rect - convert(src.m_pos); - rasIn = src.getRaster()->extract(rectIn); - } else { - rasOut = dst.getRaster(); - rasIn = src.getRaster(); - } - TRop::convert(rasOut, rasIn, palette, transparencyCheck); +void do_convert(const TTile &dst, const TTile &src, const TPaletteP palette, + bool transparencyCheck, bool applyFx) { + // assert(palette); + // assert(_rasOut && _rasIn); + // assert(rasOut->getSize() == rasIn->getSize()); + + if (applyFx && renderRas32(dst, src, palette)) return; + + TRaster32P rasOut; + TRasterCM32P rasIn; + + if (dst.getRaster()->getSize() != src.getRaster()->getSize()) { + TRect rect = TRect(convert(dst.m_pos), dst.getRaster()->getSize()) * + TRect(convert(src.m_pos), src.getRaster()->getSize()); + TRect rectOut = rect - convert(dst.m_pos); + rasOut = dst.getRaster()->extract(rectOut); + TRect rectIn = rect - convert(src.m_pos); + rasIn = src.getRaster()->extract(rectIn); + } else { + rasOut = dst.getRaster(); + rasIn = src.getRaster(); + } + TRop::convert(rasOut, rasIn, palette, transparencyCheck); } //----------------------------------------------------------------------------------------------- -void TRop::convert(const TRaster32P &rasOut, - const TRasterCM32P &rasIn, - TPaletteP palette, - const TRect &theClipRect, // il rect su cui e' applicata la conversione - bool transparencyCheck, - bool applyFx) -{ - assert(palette); - assert(rasIn && rasOut); - - TRect clipRect(theClipRect); - if (clipRect.isEmpty()) - clipRect = rasIn->getBounds(); - else { - if (!clipRect.overlaps(rasIn->getBounds())) - return; - clipRect = clipRect * rasIn->getBounds(); - } - if (clipRect.isEmpty()) - return; - - TRect clipRectIn, clipRectOut; - - if (applyFx && palette->getFxRects(clipRect, clipRectIn, clipRectOut)) { - TRect rAux = clipRectIn; - TRasterP rAuxIn = rasIn->extract(clipRectIn); //la extract modifica clipRectIn - if (rAux != clipRectIn && rAux != rasIn->getBounds()) { - TRasterCM32P rNew(rAux.getSize()); - TRect tmpRect = clipRectIn - rAux.getP00(); - rNew->extract(tmpRect)->copy(rAuxIn); - rAuxIn = rNew; - clipRectIn = rAux; - } - - TTile tileIn(rAuxIn, ::convert(clipRectIn.getP00())); - - rAux = clipRectOut; - TRasterP rAuxOut = rasOut->extract(clipRectOut); //la extract modifica clipRectOut - TTile tileOut(rAuxOut, ::convert(clipRectOut.getP00())); - TRop::convert(tileOut, tileIn, palette, transparencyCheck, true); - } else { - TRect clipRectIn = clipRect; - TRect clipRectOut = clipRect; - TRasterP _rasOut = rasOut->extract(clipRectOut); - TRasterP _rasIn = rasIn->extract(clipRectIn); - - TTile t1(_rasOut, ::convert(clipRectOut.getP00())); - TTile t2(_rasIn, ::convert(clipRectIn.getP00())); - - TRop::convert(t1, t2, - palette, transparencyCheck, false); - } +void TRop::convert( + const TRaster32P &rasOut, const TRasterCM32P &rasIn, TPaletteP palette, + const TRect &theClipRect, // il rect su cui e' applicata la conversione + bool transparencyCheck, bool applyFx) { + assert(palette); + assert(rasIn && rasOut); + + TRect clipRect(theClipRect); + if (clipRect.isEmpty()) + clipRect = rasIn->getBounds(); + else { + if (!clipRect.overlaps(rasIn->getBounds())) return; + clipRect = clipRect * rasIn->getBounds(); + } + if (clipRect.isEmpty()) return; + + TRect clipRectIn, clipRectOut; + + if (applyFx && palette->getFxRects(clipRect, clipRectIn, clipRectOut)) { + TRect rAux = clipRectIn; + TRasterP rAuxIn = + rasIn->extract(clipRectIn); // la extract modifica clipRectIn + if (rAux != clipRectIn && rAux != rasIn->getBounds()) { + TRasterCM32P rNew(rAux.getSize()); + TRect tmpRect = clipRectIn - rAux.getP00(); + rNew->extract(tmpRect)->copy(rAuxIn); + rAuxIn = rNew; + clipRectIn = rAux; + } + + TTile tileIn(rAuxIn, ::convert(clipRectIn.getP00())); + + rAux = clipRectOut; + TRasterP rAuxOut = + rasOut->extract(clipRectOut); // la extract modifica clipRectOut + TTile tileOut(rAuxOut, ::convert(clipRectOut.getP00())); + TRop::convert(tileOut, tileIn, palette, transparencyCheck, true); + } else { + TRect clipRectIn = clipRect; + TRect clipRectOut = clipRect; + TRasterP _rasOut = rasOut->extract(clipRectOut); + TRasterP _rasIn = rasIn->extract(clipRectIn); + + TTile t1(_rasOut, ::convert(clipRectOut.getP00())); + TTile t2(_rasIn, ::convert(clipRectIn.getP00())); + + TRop::convert(t1, t2, palette, transparencyCheck, false); + } } //----------------------------------------------------------------------------- -void TRop::convert(const TTile &dst, const TTile &src, const TPaletteP plt, bool transparencyCheck, bool applyFxs) -{ - //if (dst->getSize() != src->getSize()) - // throw TRopException("convert: size mismatch"); - - //assert(plt); - if ((TRaster32P)dst.getRaster()) - do_convert(dst, src, plt, transparencyCheck, applyFxs); - else if ((TRaster64P)dst.getRaster()) { - TRaster32P aux(dst.getRaster()->getLx(), dst.getRaster()->getLy()); - TTile taux(aux, dst.m_pos); - do_convert(taux, src, plt, transparencyCheck, applyFxs); - TRop::convert(dst.getRaster(), aux); - } else - throw TRopException("unsupported pixel type"); +void TRop::convert(const TTile &dst, const TTile &src, const TPaletteP plt, + bool transparencyCheck, bool applyFxs) { + // if (dst->getSize() != src->getSize()) + // throw TRopException("convert: size mismatch"); + + // assert(plt); + if ((TRaster32P)dst.getRaster()) + do_convert(dst, src, plt, transparencyCheck, applyFxs); + else if ((TRaster64P)dst.getRaster()) { + TRaster32P aux(dst.getRaster()->getLx(), dst.getRaster()->getLy()); + TTile taux(aux, dst.m_pos); + do_convert(taux, src, plt, transparencyCheck, applyFxs); + TRop::convert(dst.getRaster(), aux); + } else + throw TRopException("unsupported pixel type"); } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -namespace -{ +namespace { -TRasterP putSinglePaintInRaster(TRasterCM32P &rasIn, int paintId, TPixel32 color) -{ - TRaster32P rasOut; - - for (int y = 0; y < rasIn->getLy(); y++) { - TPixelCM32 *pixIn = rasIn->pixels(y); - TPixelCM32 *endPix = pixIn + rasIn->getLx(); - TPixel32 *pixOut = 0; - - if (rasOut) - pixOut = rasOut->pixels(y); - - while (pixIn < endPix) { - if (pixIn->getPaint() == paintId) { - if (!rasOut) { - rasOut = TRaster32P(rasIn->getLx(), rasIn->getLy()); - rasOut->fill(TPixel32::Transparent); - pixOut = rasOut->pixels(y) + (pixIn - rasIn->pixels(y)); - } - - if (!pixIn->isPureInk()) - *pixOut = color; - /*else if (!pixIn->isPureInk()) - { - assert(TPixelCM32::getMaxTone()==0xff); - pixOut->m = pixIn->getTone(); - pixOut->r = 255*color.r/pixOut->m; - pixOut->g = 255*color.g/pixOut->m; - pixOut->b = 255*color.b/pixOut->m; - }*/ - pixIn->setPaint(0); - //pixIn->setTone(0); - } - pixIn++; - pixOut++; - } - } - return rasOut; +TRasterP putSinglePaintInRaster(TRasterCM32P &rasIn, int paintId, + TPixel32 color) { + TRaster32P rasOut; + + for (int y = 0; y < rasIn->getLy(); y++) { + TPixelCM32 *pixIn = rasIn->pixels(y); + TPixelCM32 *endPix = pixIn + rasIn->getLx(); + TPixel32 *pixOut = 0; + + if (rasOut) pixOut = rasOut->pixels(y); + + while (pixIn < endPix) { + if (pixIn->getPaint() == paintId) { + if (!rasOut) { + rasOut = TRaster32P(rasIn->getLx(), rasIn->getLy()); + rasOut->fill(TPixel32::Transparent); + pixOut = rasOut->pixels(y) + (pixIn - rasIn->pixels(y)); + } + + if (!pixIn->isPureInk()) *pixOut = color; + /*else if (!pixIn->isPureInk()) + { + assert(TPixelCM32::getMaxTone()==0xff); + pixOut->m = pixIn->getTone(); + pixOut->r = 255*color.r/pixOut->m; + pixOut->g = 255*color.g/pixOut->m; + pixOut->b = 255*color.b/pixOut->m; +}*/ + pixIn->setPaint(0); + // pixIn->setTone(0); + } + pixIn++; + pixOut++; + } + } + return rasOut; } /*------------------------------------------------------------------------*/ -TRasterP putSingleInkInRasterGR8(TRasterCM32P &rasIn, int inkId) -{ - TRasterGR8P rasOut; - - for (int y = 0; y < rasIn->getLy(); y++) { - TPixelCM32 *pixIn = rasIn->pixels(y); - TPixelCM32 *endPix = pixIn + rasIn->getLx(); - TPixelGR8 *pixOut; - - if (rasOut) - pixOut = rasOut->pixels(y); - - while (pixIn < endPix) { - if (pixIn->getInk() == inkId) { - assert(TPixelCM32::getMaxTone() == 0xff); - if (!rasOut) { - rasOut = TRasterGR8P(rasIn->getLx(), rasIn->getLy()); - rasOut->fill(0); - pixOut = rasOut->pixels(y) + (pixIn - rasIn->pixels(y)); - } - - *pixOut = 255 - pixIn->getTone(); - //pixIn->setInk(0); - pixIn->setTone(TPixelCM32::getMaxTone()); - } - - pixIn++; - pixOut++; - } - } - return rasOut; +TRasterP putSingleInkInRasterGR8(TRasterCM32P &rasIn, int inkId) { + TRasterGR8P rasOut; + + for (int y = 0; y < rasIn->getLy(); y++) { + TPixelCM32 *pixIn = rasIn->pixels(y); + TPixelCM32 *endPix = pixIn + rasIn->getLx(); + TPixelGR8 *pixOut; + + if (rasOut) pixOut = rasOut->pixels(y); + + while (pixIn < endPix) { + if (pixIn->getInk() == inkId) { + assert(TPixelCM32::getMaxTone() == 0xff); + if (!rasOut) { + rasOut = TRasterGR8P(rasIn->getLx(), rasIn->getLy()); + rasOut->fill(0); + pixOut = rasOut->pixels(y) + (pixIn - rasIn->pixels(y)); + } + + *pixOut = 255 - pixIn->getTone(); + // pixIn->setInk(0); + pixIn->setTone(TPixelCM32::getMaxTone()); + } + + pixIn++; + pixOut++; + } + } + return rasOut; } /*------------------------------------------------------------------------*/ -TRasterP putSingleInkInRasterRGBM(TRasterCM32P &rasIn, int inkId) -{ - TRaster32P rasOut; - - for (int y = 0; y < rasIn->getLy(); y++) { - TPixelCM32 *pixIn = rasIn->pixels(y); - TPixelCM32 *endPix = pixIn + rasIn->getLx(); - TPixel *pixOut; - - if (rasOut) - pixOut = rasOut->pixels(y); - - while (pixIn < endPix) { - if (pixIn->getInk() == inkId) { - assert(TPixelCM32::getMaxTone() == 0xff); - if (!rasOut) { - rasOut = TRaster32P(rasIn->getLx(), rasIn->getLy()); - rasOut->fill(TPixel32::Transparent); - pixOut = rasOut->pixels(y) + (pixIn - rasIn->pixels(y)); - } - - pixOut->r = pixOut->g = pixOut->b = pixOut->m = 255 - pixIn->getTone(); - //pixIn->setInk(0); - pixIn->setTone(TPixelCM32::getMaxTone()); - } - pixIn++; - if (rasOut) - pixOut++; - } - } - return rasOut; +TRasterP putSingleInkInRasterRGBM(TRasterCM32P &rasIn, int inkId) { + TRaster32P rasOut; + + for (int y = 0; y < rasIn->getLy(); y++) { + TPixelCM32 *pixIn = rasIn->pixels(y); + TPixelCM32 *endPix = pixIn + rasIn->getLx(); + TPixel *pixOut; + + if (rasOut) pixOut = rasOut->pixels(y); + + while (pixIn < endPix) { + if (pixIn->getInk() == inkId) { + assert(TPixelCM32::getMaxTone() == 0xff); + if (!rasOut) { + rasOut = TRaster32P(rasIn->getLx(), rasIn->getLy()); + rasOut->fill(TPixel32::Transparent); + pixOut = rasOut->pixels(y) + (pixIn - rasIn->pixels(y)); + } + + pixOut->r = pixOut->g = pixOut->b = pixOut->m = 255 - pixIn->getTone(); + // pixIn->setInk(0); + pixIn->setTone(TPixelCM32::getMaxTone()); + } + pixIn++; + if (rasOut) pixOut++; + } + } + return rasOut; } /*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/ -//filename!! -//interactive!! +// filename!! +// interactive!! bool computePaletteFx(const std::vector> &fx, - const TTile &tileOut, const TTile &tileIn, const TPaletteP plt) -{ - int i; - TRasterCM32P rasIn = tileIn.getRaster(); - TRaster32P rAux32, rasOut = tileOut.getRaster(); - TRasterGR8P rAuxGR; - - int frame = plt->getFrame(); - - std::vector paintLayers(fx.size()); - std::vector inkLayers(fx.size()); - - //tolgo dal raster d'ingresso gli ink e i paint con gli effetti, mettendoli in dei raster layer - for (i = 0; i < (int)fx.size(); i++) { - TRasterStyleFx *rfx = fx[i].first->getRasterStyleFx(); - - if (rfx->isPaintStyle()) - paintLayers[i] = putSinglePaintInRaster(rasIn, fx[i].second, fx[i].first->getMainColor()); - if (rfx->isInkStyle()) { - if (rfx->inkFxNeedRGBMRaster()) - inkLayers[i] = putSingleInkInRasterRGBM(rasIn, fx[i].second); - else - inkLayers[i] = putSingleInkInRasterGR8(rasIn, fx[i].second); - } - } - - //raster d'ingresso senza i colori fx, viene renderizzato nel raster d'uscita - - do_convert(tileOut, tileIn, plt, false, false); - - //ogni layer viene "effettato".; se il risultato e' non nullo, viene sovrapposto sul raster d'uscita - //prima vengono messi tutti i layer di paint, poi quelli di ink - - TRect rectOut = TRect(convert(tileOut.m_pos), tileOut.getRaster()->getSize()) - convert(tileIn.m_pos); - - for (i = 0; i < (int)fx.size(); i++) - if (paintLayers[i]) { - TRasterStyleFx::Params params(paintLayers[i], convert(tileIn.m_pos), rasIn, fx[i].second, frame); - if (fx[i].first->getRasterStyleFx()->compute(params)) - TRop::over(rasOut, paintLayers[i]->extract(rectOut), rasOut); - } - - for (i = 0; i < (int)fx.size(); i++) - if (inkLayers[i]) { - TRasterStyleFx *rfx = fx[i].first->getRasterStyleFx(); - - TRasterStyleFx::Params params(inkLayers[i], convert(tileIn.m_pos), rasIn, fx[i].second, frame); - if (rfx->compute(params)) { - if (rfx->inkFxNeedRGBMRaster()) - TRop::over(rasOut, rasOut, inkLayers[i]->extract(rectOut)); - else - TRop::over(rasOut, inkLayers[i]->extract(rectOut), fx[i].first->getMainColor()); - } - } - - return true; + const TTile &tileOut, const TTile &tileIn, + const TPaletteP plt) { + int i; + TRasterCM32P rasIn = tileIn.getRaster(); + TRaster32P rAux32, rasOut = tileOut.getRaster(); + TRasterGR8P rAuxGR; + + int frame = plt->getFrame(); + + std::vector paintLayers(fx.size()); + std::vector inkLayers(fx.size()); + + // tolgo dal raster d'ingresso gli ink e i paint con gli effetti, mettendoli + // in dei raster layer + for (i = 0; i < (int)fx.size(); i++) { + TRasterStyleFx *rfx = fx[i].first->getRasterStyleFx(); + + if (rfx->isPaintStyle()) + paintLayers[i] = putSinglePaintInRaster(rasIn, fx[i].second, + fx[i].first->getMainColor()); + if (rfx->isInkStyle()) { + if (rfx->inkFxNeedRGBMRaster()) + inkLayers[i] = putSingleInkInRasterRGBM(rasIn, fx[i].second); + else + inkLayers[i] = putSingleInkInRasterGR8(rasIn, fx[i].second); + } + } + + // raster d'ingresso senza i colori fx, viene renderizzato nel raster d'uscita + + do_convert(tileOut, tileIn, plt, false, false); + + // ogni layer viene "effettato".; se il risultato e' non nullo, viene + // sovrapposto sul raster d'uscita + // prima vengono messi tutti i layer di paint, poi quelli di ink + + TRect rectOut = + TRect(convert(tileOut.m_pos), tileOut.getRaster()->getSize()) - + convert(tileIn.m_pos); + + for (i = 0; i < (int)fx.size(); i++) + if (paintLayers[i]) { + TRasterStyleFx::Params params(paintLayers[i], convert(tileIn.m_pos), + rasIn, fx[i].second, frame); + if (fx[i].first->getRasterStyleFx()->compute(params)) + TRop::over(rasOut, paintLayers[i]->extract(rectOut), rasOut); + } + + for (i = 0; i < (int)fx.size(); i++) + if (inkLayers[i]) { + TRasterStyleFx *rfx = fx[i].first->getRasterStyleFx(); + + TRasterStyleFx::Params params(inkLayers[i], convert(tileIn.m_pos), rasIn, + fx[i].second, frame); + if (rfx->compute(params)) { + if (rfx->inkFxNeedRGBMRaster()) + TRop::over(rasOut, rasOut, inkLayers[i]->extract(rectOut)); + else + TRop::over(rasOut, inkLayers[i]->extract(rectOut), + fx[i].first->getMainColor()); + } + } + + return true; } /*------------------------------------------------------------------------*/ -} //namespace +} // namespace /*------------------------------------------------------------------------*/ -bool renderRas32(const TTile &tileOut, const TTile &tileIn, const TPaletteP palette) -{ - assert(TRect(convert(tileIn.m_pos), tileIn.getRaster()->getSize()).contains(TRect(convert(tileOut.m_pos), tileOut.getRaster()->getSize()))); - assert((TRasterCM32P)tileIn.getRaster()); +bool renderRas32(const TTile &tileOut, const TTile &tileIn, + const TPaletteP palette) { + assert(TRect(convert(tileIn.m_pos), tileIn.getRaster()->getSize()) + .contains(TRect(convert(tileOut.m_pos), + tileOut.getRaster()->getSize()))); + assert((TRasterCM32P)tileIn.getRaster()); - //Shrink = shrink; - //INIT_TCM(rin) + // Shrink = shrink; + // INIT_TCM(rin) - /* mark up are made apart */ - //computeMarkup(rasIn, palette); + /* mark up are made apart */ + // computeMarkup(rasIn, palette); - std::vector> fxArray; + std::vector> fxArray; - for (int i = 0; i < palette->getStyleCount(); i++) - if (palette->getStyle(i)->isRasterStyle()) - fxArray.push_back(std::pair(palette->getStyle(i), i)); + for (int i = 0; i < palette->getStyleCount(); i++) + if (palette->getStyle(i)->isRasterStyle()) + fxArray.push_back(std::pair(palette->getStyle(i), i)); - if (fxArray.empty()) - return false; + if (fxArray.empty()) return false; - TTile _tileIn(tileIn.getRaster()->clone(), tileIn.m_pos); + TTile _tileIn(tileIn.getRaster()->clone(), tileIn.m_pos); - tileIn.getRaster()->lock(); - tileOut.getRaster()->lock(); - computePaletteFx(fxArray, tileOut, _tileIn, palette); - tileIn.getRaster()->unlock(); - tileOut.getRaster()->unlock(); + tileIn.getRaster()->lock(); + tileOut.getRaster()->lock(); + computePaletteFx(fxArray, tileOut, _tileIn, palette); + tileIn.getRaster()->unlock(); + tileOut.getRaster()->unlock(); - return true; + return true; } /*------------------------------------------------------------------------*/ //-------------------------------------------------------------------------------------------- -namespace -{ +namespace { -void addColor(TPaletteP plt, int index, const TPaletteP &upPlt, std::map &usedInks) -{ - TColorStyle *cs = upPlt->getStyle(index); - if (cs && cs->getMainColor() == plt->getStyle(index)->getMainColor()) { - usedInks[index] = index; - return; - } - int firstStyleId = plt->getFirstUnpagedStyle(); - if (firstStyleId == -1) - firstStyleId = plt->getStyleCount(); - usedInks[index] = firstStyleId; - plt->getPage(0)->addStyle(TPixel32::Red); +void addColor(TPaletteP plt, int index, const TPaletteP &upPlt, + std::map &usedInks) { + TColorStyle *cs = upPlt->getStyle(index); + if (cs && cs->getMainColor() == plt->getStyle(index)->getMainColor()) { + usedInks[index] = index; + return; + } + int firstStyleId = plt->getFirstUnpagedStyle(); + if (firstStyleId == -1) firstStyleId = plt->getStyleCount(); + usedInks[index] = firstStyleId; + plt->getPage(0)->addStyle(TPixel32::Red); } -void addColor(TPaletteP plt, int index, std::map &usedInks) -{ - int firstStyleId = plt->getFirstUnpagedStyle(); - if (firstStyleId == -1) - firstStyleId = plt->getStyleCount(); - usedInks[index] = firstStyleId; - plt->getPage(0)->addStyle(TPixel32::Red); +void addColor(TPaletteP plt, int index, std::map &usedInks) { + int firstStyleId = plt->getFirstUnpagedStyle(); + if (firstStyleId == -1) firstStyleId = plt->getStyleCount(); + usedInks[index] = firstStyleId; + plt->getPage(0)->addStyle(TPixel32::Red); } //------------------------------------------------------------ -//std::map& usedInk upInkId -> downInkId -void doMergeCmapped(TRasterCM32P rasOut, const TRasterCM32P &rasUp, const TPaletteP &pltOut, bool onlyInks, - int matchlinePrevalence, std::map &usedInks) -{ - double val = matchlinePrevalence / 100.0; //matchlinePrevalence ==0 always ink down; matchlinePrevalence == 100 always ink up; - assert(rasOut && rasUp); - assert(rasOut->getSize() == rasUp->getSize()); - - TPaletteP downPlt = pltOut->clone(); - std::map::iterator it; - for (it = usedInks.begin(); it != usedInks.end(); it++) - downPlt->getPage(0)->addStyle(TPixel32::Red); - for (int y = 0; y < rasOut->getLy(); y++) { - TPixelCM32 *pixDown = rasOut->pixels(y), *endPix = pixDown + rasOut->getLx(); - TPixelCM32 *pixUp = rasUp->pixels(y); - - while (pixDown < endPix) { - //there is lines in matchline - if (!pixUp->isPurePaint()) { - int toneDown = pixDown->getTone(); - int toneUp = pixUp->getTone(); - if (usedInks.find(pixUp->getInk()) == usedInks.end()) - addColor(downPlt, pixUp->getInk(), usedInks); - - if (val == 1) { //Matchline is on top, with gap - pixDown->setTone(toneUp); - pixDown->setInk(usedInks[pixUp->getInk()]); - } else if (val == 0) { //Matchline is on bottom, with gap - if (pixDown->isPurePaint()) { - pixDown->setTone(toneUp); - pixDown->setInk(usedInks[pixUp->getInk()]); - } else { - //*pixOut = *pixDown; - } - } else { - if ((val > 0 && toneUp < toneDown) || (val == 0 && toneDown == 255)) //(toneUpsetTone(toneUp); - - if ((255 - toneDown) * (1 - val) <= val * (255 - toneUp - 1)) //val==0 -> if (toneDown== 255).... - //val==0.5 -> if (toneup if (toneup<255)... - pixDown->setInk(usedInks[pixUp->getInk()]); - } - } - int paintIndex; - if (!onlyInks && (paintIndex = pixUp->getPaint()) > 0) { - if (usedInks.find(paintIndex) == usedInks.end()) - addColor(downPlt, paintIndex, usedInks); - pixDown->setPaint(usedInks[paintIndex]); - } - pixUp++; - pixDown++; - //pixOut++; - } - } +// std::map& usedInk upInkId -> downInkId +void doMergeCmapped(TRasterCM32P rasOut, const TRasterCM32P &rasUp, + const TPaletteP &pltOut, bool onlyInks, + int matchlinePrevalence, std::map &usedInks) { + double val = matchlinePrevalence / 100.0; // matchlinePrevalence ==0 always + // ink down; matchlinePrevalence == + // 100 always ink up; + assert(rasOut && rasUp); + assert(rasOut->getSize() == rasUp->getSize()); + + TPaletteP downPlt = pltOut->clone(); + std::map::iterator it; + for (it = usedInks.begin(); it != usedInks.end(); it++) + downPlt->getPage(0)->addStyle(TPixel32::Red); + for (int y = 0; y < rasOut->getLy(); y++) { + TPixelCM32 *pixDown = rasOut->pixels(y), + *endPix = pixDown + rasOut->getLx(); + TPixelCM32 *pixUp = rasUp->pixels(y); + + while (pixDown < endPix) { + // there is lines in matchline + if (!pixUp->isPurePaint()) { + int toneDown = pixDown->getTone(); + int toneUp = pixUp->getTone(); + if (usedInks.find(pixUp->getInk()) == usedInks.end()) + addColor(downPlt, pixUp->getInk(), usedInks); + + if (val == 1) { // Matchline is on top, with gap + pixDown->setTone(toneUp); + pixDown->setInk(usedInks[pixUp->getInk()]); + } else if (val == 0) { // Matchline is on bottom, with gap + if (pixDown->isPurePaint()) { + pixDown->setTone(toneUp); + pixDown->setInk(usedInks[pixUp->getInk()]); + } else { + //*pixOut = *pixDown; + } + } else { + if ((val > 0 && toneUp < toneDown) || + (val == 0 && toneDown == 255)) //(toneUpsetTone(toneUp); + + if ((255 - toneDown) * (1 - val) <= + val * (255 - toneUp - 1)) // val==0 -> if (toneDown== 255).... + // val==0.5 -> if (toneup if (toneup<255)... + pixDown->setInk(usedInks[pixUp->getInk()]); + } + } + int paintIndex; + if (!onlyInks && (paintIndex = pixUp->getPaint()) > 0) { + if (usedInks.find(paintIndex) == usedInks.end()) + addColor(downPlt, paintIndex, usedInks); + pixDown->setPaint(usedInks[paintIndex]); + } + pixUp++; + pixDown++; + // pixOut++; + } + } } /*------------------------------------------------------------------------*/ -void addColors(const TPixelCM32 &color, TPaletteP plt, const TPaletteP &upPlt, std::map &usedColors) -{ - if (usedColors.find(color.getInk()) == usedColors.end()) - addColor(plt, color.getInk(), upPlt, usedColors); - if (usedColors.find(color.getPaint()) == usedColors.end()) - addColor(plt, color.getPaint(), upPlt, usedColors); +void addColors(const TPixelCM32 &color, TPaletteP plt, const TPaletteP &upPlt, + std::map &usedColors) { + if (usedColors.find(color.getInk()) == usedColors.end()) + addColor(plt, color.getInk(), upPlt, usedColors); + if (usedColors.find(color.getPaint()) == usedColors.end()) + addColor(plt, color.getPaint(), upPlt, usedColors); } //--------------------------------------------------------------------------- -void addColors(const TPixelCM32 &color, TPaletteP plt, std::map &usedColors) -{ - if (usedColors.find(color.getInk()) == usedColors.end()) - addColor(plt, color.getInk(), usedColors); - if (usedColors.find(color.getPaint()) == usedColors.end()) - addColor(plt, color.getPaint(), usedColors); +void addColors(const TPixelCM32 &color, TPaletteP plt, + std::map &usedColors) { + if (usedColors.find(color.getInk()) == usedColors.end()) + addColor(plt, color.getInk(), usedColors); + if (usedColors.find(color.getPaint()) == usedColors.end()) + addColor(plt, color.getPaint(), usedColors); } /*------------------------------------------------------------------------*/ -void doApplyMatchLines(TRasterCM32P rasOut, const TRasterCM32P &rasUp, int inkIndex, int matchlinePrevalence) -{ - double val = matchlinePrevalence / 100.0; //matchlinePrevalence ==0->always ink down; matchlinePrevalence == 100 always ink up; - - assert(rasOut && rasUp); - assert(rasOut->getSize() == rasUp->getSize()); - - for (int y = 0; y < rasOut->getLy(); y++) { - TPixelCM32 *pixDown = rasOut->pixels(y), *endPix = pixDown + rasOut->getLx(); - TPixelCM32 *pixUp = rasUp->pixels(y); - - while (pixDown < endPix) { - if (!pixUp->isPurePaint()) { - int toneDown = pixDown->getTone(); - int toneUp = pixUp->getTone(); - if (val == 1) { //Matchline is on top, with gap - pixDown->setTone(toneUp); - pixDown->setInk(inkIndex); - } else if (val == 0) { //Matchline is on bottom, with gap - if (pixDown->isPurePaint()) { - pixDown->setTone(toneUp); - pixDown->setInk(inkIndex); - } else { - } - //*pixOut = *pixDown; - } - if ((val > 0 && toneUp < toneDown) || (val == 0 && toneDown == 255)) - pixDown->setTone(toneUp); - - if ((255 - toneDown) * (1 - val) <= val * (255 - toneUp - 1)) //val==0 -> if (toneDown == 255).... - //val==0.5 -> if (toneup if (toneup<255)... - pixDown->setInk(inkIndex); - } - - pixUp++; - pixDown++; - } - } +void doApplyMatchLines(TRasterCM32P rasOut, const TRasterCM32P &rasUp, + int inkIndex, int matchlinePrevalence) { + double val = matchlinePrevalence / 100.0; // matchlinePrevalence ==0->always + // ink down; matchlinePrevalence == + // 100 always ink up; + + assert(rasOut && rasUp); + assert(rasOut->getSize() == rasUp->getSize()); + + for (int y = 0; y < rasOut->getLy(); y++) { + TPixelCM32 *pixDown = rasOut->pixels(y), + *endPix = pixDown + rasOut->getLx(); + TPixelCM32 *pixUp = rasUp->pixels(y); + + while (pixDown < endPix) { + if (!pixUp->isPurePaint()) { + int toneDown = pixDown->getTone(); + int toneUp = pixUp->getTone(); + if (val == 1) { // Matchline is on top, with gap + pixDown->setTone(toneUp); + pixDown->setInk(inkIndex); + } else if (val == 0) { // Matchline is on bottom, with gap + if (pixDown->isPurePaint()) { + pixDown->setTone(toneUp); + pixDown->setInk(inkIndex); + } else { + } + //*pixOut = *pixDown; + } + if ((val > 0 && toneUp < toneDown) || (val == 0 && toneDown == 255)) + pixDown->setTone(toneUp); + + if ((255 - toneDown) * (1 - val) <= + val * (255 - toneUp - 1)) // val==0 -> if (toneDown == 255).... + // val==0.5 -> if (toneup if (toneup<255)... + pixDown->setInk(inkIndex); + } + + pixUp++; + pixDown++; + } + } } /*------------------------------------------------------------------------*/ -} //namespace +} // namespace #ifdef LEVO -void TRop::eraseColors(TRasterCM32P ras, vector &colorIds, bool eraseInks, bool keepColor) -{ - assert(ras); - - vector curColorIds; - std::sort(colorIds.begin(), colorIds.end()); - - if (!keepColor) - curColorIds = colorIds; - else { - //prendo tutti i colori ECCETTO quelli nel vettore colorIds - unsigned int count1 = 0, count2 = 0; - int size = eraseInks ? TPixelCM32::getMaxInk() : TPixelCM32::getMaxPaint(); - - curColorIds.resize(size + 1 - colorIds.size()); - for (int i = 0; i < size; i++) - if (count1 < colorIds.size() && colorIds[count1] == i) - count1++; - else - curColorIds[count2++] = i; - } - - for (int y = 0; y < ras->getLy(); y++) { - TPixelCM32 *pix = ras->pixels(y), *endPix = pix + ras->getLx(); - - while (pix < endPix) { - unsigned int i; - int color = eraseInks ? pix->getInk() : pix->getPaint(); - - if (color != 0) - for (i = 0; i < curColorIds.size() && curColorIds[i] <= color; i++) - if (color == curColorIds[i]) { - *pix = eraseInks ? TPixelCM32(0, pix->getPaint(), TPixelCM32::getMaxTone()) : TPixelCM32(pix->getInk(), 0, pix->getTone()); - break; - } - pix++; - } - } +void TRop::eraseColors(TRasterCM32P ras, vector &colorIds, bool eraseInks, + bool keepColor) { + assert(ras); + + vector curColorIds; + std::sort(colorIds.begin(), colorIds.end()); + + if (!keepColor) + curColorIds = colorIds; + else { + // prendo tutti i colori ECCETTO quelli nel vettore colorIds + unsigned int count1 = 0, count2 = 0; + int size = eraseInks ? TPixelCM32::getMaxInk() : TPixelCM32::getMaxPaint(); + + curColorIds.resize(size + 1 - colorIds.size()); + for (int i = 0; i < size; i++) + if (count1 < colorIds.size() && colorIds[count1] == i) + count1++; + else + curColorIds[count2++] = i; + } + + for (int y = 0; y < ras->getLy(); y++) { + TPixelCM32 *pix = ras->pixels(y), *endPix = pix + ras->getLx(); + + while (pix < endPix) { + unsigned int i; + int color = eraseInks ? pix->getInk() : pix->getPaint(); + + if (color != 0) + for (i = 0; i < curColorIds.size() && curColorIds[i] <= color; i++) + if (color == curColorIds[i]) { + *pix = eraseInks ? TPixelCM32(0, pix->getPaint(), + TPixelCM32::getMaxTone()) + : TPixelCM32(pix->getInk(), 0, pix->getTone()); + break; + } + pix++; + } + } } #endif /*------------------------------------------------------------------------*/ -void TRop::eraseColors(TRasterCM32P ras, std::vector *colorIds, bool eraseInks) -{ - if (colorIds) - std::sort(colorIds->begin(), colorIds->end()); - - for (int y = 0; y < ras->getLy(); y++) { - TPixelCM32 *pix = ras->pixels(y), *endPix = pix + ras->getLx(); - - for (; pix < endPix; pix++) { - unsigned int i = 0; - int color = eraseInks ? pix->getInk() : pix->getPaint(); - - if (color == 0) - continue; - - if (colorIds) { - while (i < colorIds->size() && (*colorIds)[i] < color) - i++; - if (i == colorIds->size() || color != (*colorIds)[i]) - continue; - } - - if (eraseInks) { - pix->setInk(0); - pix->setTone(TPixelCM32::getMaxTone()); - } else - pix->setPaint(0); - } - } +void TRop::eraseColors(TRasterCM32P ras, std::vector *colorIds, + bool eraseInks) { + if (colorIds) std::sort(colorIds->begin(), colorIds->end()); + + for (int y = 0; y < ras->getLy(); y++) { + TPixelCM32 *pix = ras->pixels(y), *endPix = pix + ras->getLx(); + + for (; pix < endPix; pix++) { + unsigned int i = 0; + int color = eraseInks ? pix->getInk() : pix->getPaint(); + + if (color == 0) continue; + + if (colorIds) { + while (i < colorIds->size() && (*colorIds)[i] < color) i++; + if (i == colorIds->size() || color != (*colorIds)[i]) continue; + } + + if (eraseInks) { + pix->setInk(0); + pix->setTone(TPixelCM32::getMaxTone()); + } else + pix->setPaint(0); + } + } } //-------------------------------- /* -void TRop::overaCmapped(TRasterCM32P rasOut, const TRasterCM32P& rasUp, const TPaletteP &pltOut, int matchlinePrevalence, std::map& usedColors) +void TRop::overaCmapped(TRasterCM32P rasOut, const TRasterCM32P& rasUp, const +TPaletteP &pltOut, int matchlinePrevalence, std::map& usedColors) { doMergeCmapped(rasOut, rasUp, pltOut, false, matchlinePrevalence, usedColors); } */ //----------------------------------------------------------------- -void TRop::applyMatchLines(TRasterCM32P rasOut, const TRasterCM32P &rasUp, const TPaletteP &pltOut, int inkIndex, int matchlinePrevalence, std::map &usedInks) -{ - assert(matchlinePrevalence >= 0); - if (inkIndex == -1) - doMergeCmapped(rasOut, rasUp, pltOut, true, matchlinePrevalence, usedInks); - else - doApplyMatchLines(rasOut, rasUp, inkIndex, matchlinePrevalence); +void TRop::applyMatchLines(TRasterCM32P rasOut, const TRasterCM32P &rasUp, + const TPaletteP &pltOut, int inkIndex, + int matchlinePrevalence, + std::map &usedInks) { + assert(matchlinePrevalence >= 0); + if (inkIndex == -1) + doMergeCmapped(rasOut, rasUp, pltOut, true, matchlinePrevalence, usedInks); + else + doApplyMatchLines(rasOut, rasUp, inkIndex, matchlinePrevalence); } /*------------------------------------------------------------------------*/ -void TRop::eraseStyleIds(TToonzImage *image, const std::vector styleIds) -{ - assert(image); - TRasterCM32P ras = image->getRaster(); - - int i; - for (i = 0; i < (int)styleIds.size(); i++) { - int styleId = styleIds[i]; - ras->lock(); - for (int y = 0; y < ras->getLy(); y++) { - TPixelCM32 *pix = ras->pixels(y), *endPix = pix + ras->getLx(); - while (pix < endPix) { - bool isPaint = (pix->getPaint() == styleId); - bool isInk = (pix->getInk() == styleId); - if (!isPaint && !isInk) { - pix++; - continue; - } else if (isPaint && !isInk) - *pix = TPixelCM32(pix->getInk(), 0, pix->getTone()); - else if (!isPaint && isInk) - *pix = TPixelCM32(0, pix->getPaint(), TPixelCM32::getMaxTone()); - else if (isPaint && isInk) - *pix = TPixelCM32(0, 0, pix->getTone()); - else - assert(0); - pix++; - } - } - ras->unlock(); - } +void TRop::eraseStyleIds(TToonzImage *image, const std::vector styleIds) { + assert(image); + TRasterCM32P ras = image->getRaster(); + + int i; + for (i = 0; i < (int)styleIds.size(); i++) { + int styleId = styleIds[i]; + ras->lock(); + for (int y = 0; y < ras->getLy(); y++) { + TPixelCM32 *pix = ras->pixels(y), *endPix = pix + ras->getLx(); + while (pix < endPix) { + bool isPaint = (pix->getPaint() == styleId); + bool isInk = (pix->getInk() == styleId); + if (!isPaint && !isInk) { + pix++; + continue; + } else if (isPaint && !isInk) + *pix = TPixelCM32(pix->getInk(), 0, pix->getTone()); + else if (!isPaint && isInk) + *pix = TPixelCM32(0, pix->getPaint(), TPixelCM32::getMaxTone()); + else if (isPaint && isInk) + *pix = TPixelCM32(0, 0, pix->getTone()); + else + assert(0); + pix++; + } + } + ras->unlock(); + } } /*------------------------------------------------------------------------*/ -inline bool isTransparent(TPixelCM32 *pix) -{ - return (((*((ULONG *)pix)) & 0x000fffff) == 0xff); +inline bool isTransparent(TPixelCM32 *pix) { + return (((*((ULONG *)pix)) & 0x000fffff) == 0xff); } -void TRop::overlayCmapped(TRasterCM32P rasOut, const TRasterCM32P &rasUp, const TPaletteP &pltOut, const TPaletteP &upPlt, std::map &usedColors) -{ - - assert(rasOut && rasUp); - assert(rasOut->getSize() == rasUp->getSize()); - - TPaletteP downPlt = pltOut->clone(); - std::map::iterator it; - for (it = usedColors.begin(); it != usedColors.end(); it++) - downPlt->getPage(0)->addStyle(TPixel32::Red); - - for (int y = 0; y < rasOut->getLy(); y++) { - TPixelCM32 *pixDown = rasOut->pixels(y); - TPixelCM32 *pixUp = rasUp->pixels(y); - - for (int x = 0; x < rasOut->getLx(); x++, pixUp++, pixDown++) { - if (isTransparent(pixUp)) //WARNING! cannot check transparent pixels with *pixup==TPixelCM32() since also 0x183000ff i.e., is a valid transparent value - continue; - int tone = pixUp->getTone(); - if (isTransparent(pixDown) || tone == 255 || tone == 0 || pixUp->getPaint() != 0) //up e' punto interno, o esterno non antialiasato - { - addColors(*pixUp, downPlt, upPlt, usedColors); - pixDown->setInk(usedColors[pixUp->getInk()]); - pixDown->setPaint(usedColors[pixUp->getPaint()]); - pixDown->setTone(tone); - } else if (tone <= pixDown->getTone() || tone < 128) //up e' bordo esterno antialiasato piu' opaco di down - { - int ink = pixUp->getInk(); - if (usedColors.find(ink) == usedColors.end()) - addColor(downPlt, ink, upPlt, usedColors); - pixDown->setInk(usedColors[ink]); - pixDown->setTone(tone < 128 ? 0 : tone); - } - } - } +void TRop::overlayCmapped(TRasterCM32P rasOut, const TRasterCM32P &rasUp, + const TPaletteP &pltOut, const TPaletteP &upPlt, + std::map &usedColors) { + assert(rasOut && rasUp); + assert(rasOut->getSize() == rasUp->getSize()); + + TPaletteP downPlt = pltOut->clone(); + std::map::iterator it; + for (it = usedColors.begin(); it != usedColors.end(); it++) + downPlt->getPage(0)->addStyle(TPixel32::Red); + + for (int y = 0; y < rasOut->getLy(); y++) { + TPixelCM32 *pixDown = rasOut->pixels(y); + TPixelCM32 *pixUp = rasUp->pixels(y); + + for (int x = 0; x < rasOut->getLx(); x++, pixUp++, pixDown++) { + if (isTransparent(pixUp)) // WARNING! cannot check transparent pixels + // with *pixup==TPixelCM32() since also + // 0x183000ff i.e., is a valid transparent + // value + continue; + int tone = pixUp->getTone(); + if (isTransparent(pixDown) || tone == 255 || tone == 0 || + pixUp->getPaint() != + 0) // up e' punto interno, o esterno non antialiasato + { + addColors(*pixUp, downPlt, upPlt, usedColors); + pixDown->setInk(usedColors[pixUp->getInk()]); + pixDown->setPaint(usedColors[pixUp->getPaint()]); + pixDown->setTone(tone); + } else if (tone <= pixDown->getTone() || tone < 128) // up e' bordo + // esterno + // antialiasato piu' + // opaco di down + { + int ink = pixUp->getInk(); + if (usedColors.find(ink) == usedColors.end()) + addColor(downPlt, ink, upPlt, usedColors); + pixDown->setInk(usedColors[ink]); + pixDown->setTone(tone < 128 ? 0 : tone); + } + } + } } //----------------------------------------------------- -namespace -{ +namespace { #define MAGICFAC (257U * 256U + 1U) /* @@ -886,10 +890,10 @@ index = index << cmap.info.tone_bits; int xedni = index + cmap.info.n_tones-1; TPixel32 _color=color; - UINT fac = MAGICFAC * _color.m; - _color.r=(UINT)(_color.r * fac + (1U<<23))>>24; - _color.b=(UINT)(_color.b * fac + (1U<<23))>>24; - _color.g=(UINT)(_color.g * fac + (1U<<23))>>24; + UINT fac = MAGICFAC * _color.m; + _color.r=(UINT)(_color.r * fac + (1U<<23))>>24; + _color.b=(UINT)(_color.b * fac + (1U<<23))>>24; + _color.g=(UINT)(_color.g * fac + (1U<<23))>>24; for (int tone = 0; tone < cmap.info.n_tones; tone++) { @@ -908,18 +912,24 @@ for (int tone = 0; tone < cmap.info.n_tones; tone++) /*---------------------------------------------------------------------------*/ -} //namespace +} // namespace /*---------------------------------------------------------------------------*/ // \b NOTE: Starting from Toonz 6.1, some important improvements are introduced: -// a) The passed raster is now referenced by the returned _RASTER*, just the same way +// a) The passed raster is now referenced by the returned _RASTER*, just the +// same way // smartpointer to rasters do. -// b) The cache is made aware of the passed raster, mainly because these old 4.6 raster -// structures are essentially used for memory-consuming operations with tlv fxs and may -// need to be shipped to hard disk on critical situations (a matter handled by the cache). -// c) The lockRaster and unlockRaster functions are provided. They are meant to specify whether -// the raster is actively referenced by the raster pointer, or is rather in a lazy state - +// b) The cache is made aware of the passed raster, mainly because these old 4.6 +// raster +// structures are essentially used for memory-consuming operations with tlv +// fxs and may +// need to be shipped to hard disk on critical situations (a matter handled +// by the cache). +// c) The lockRaster and unlockRaster functions are provided. They are meant to +// specify whether +// the raster is actively referenced by the raster pointer, or is rather in a +// lazy state - // so that the cache may move it to hard disk if necessary. /* @@ -930,330 +940,325 @@ static const TCM_INFO Tcm_my_default_info = { 8, 8, 12, 20, 12, /*---------------------------------------------------------------------------*/ -inline LPIXEL premultiplyLPIXEL(const TPixel32 &pix) -{ - //int MAGICFAC = (257U * 256U + 1U); - UINT fac = MAGICFAC * pix.m; - LPIXEL out; - out.r = ((UINT)(pix.r * fac + (1U << 23)) >> 24); - out.g = ((UINT)(pix.g * fac + (1U << 23)) >> 24); - out.b = ((UINT)(pix.b * fac + (1U << 23)) >> 24); - out.m = pix.m; - return out; +inline LPIXEL premultiplyLPIXEL(const TPixel32 &pix) { + // int MAGICFAC = (257U * 256U + 1U); + UINT fac = MAGICFAC * pix.m; + LPIXEL out; + out.r = ((UINT)(pix.r * fac + (1U << 23)) >> 24); + out.g = ((UINT)(pix.g * fac + (1U << 23)) >> 24); + out.b = ((UINT)(pix.b * fac + (1U << 23)) >> 24); + out.m = pix.m; + return out; } -_RASTER *TRop::convertRaster50to46(const TRasterP &inRas, const TPaletteP &inPalette) -{ +_RASTER *TRop::convertRaster50to46(const TRasterP &inRas, + const TPaletteP &inPalette) { + int lx = inRas->getLx(); + int ly = inRas->getLy(); + int wrap = inRas->getWrap(); + + assert(lx > 0 && ly > 0); + assert(inRas->getRawData()); + TRasterGR8P rgr8 = (TRasterGR8P)inRas; + TRasterGR16P rgr16 = (TRasterGR16P)inRas; + TRaster32P r32 = (TRaster32P)inRas; + TRaster64P r64 = (TRaster64P)inRas; + TRasterCM32P rcm = (TRasterCM32P)inRas; + + RASTER *rout = new RASTER; + memset(rout, 0, sizeof(RASTER)); + + std::string id(TImageCache::instance()->getUniqueId()); + rout->cacheIdLength = id.size(); + rout->cacheId = new char[rout->cacheIdLength]; + memcpy(rout->cacheId, id.data(), sizeof(char) * rout->cacheIdLength); + { + TImageP img; + if (rcm) + img = TToonzImageP(rcm, rcm->getBounds()); // saveBox is not considered + // in RASTER struct anyway + else + img = TRasterImageP(inRas); + TImageCache::instance()->add(id, img); + } + inRas->addRef(); + + rout->buffer = inRas->getRawData(); + TRasterP parent = inRas->getParent(); + rout->native_buffer = (parent) ? parent->getRawData() : inRas->getRawData(); + rout->lx = lx; + rout->ly = ly; + rout->wrap = wrap; + + if (rgr8) + rout->type = RAS_GR8; + else if (rgr16) + rout->type = RAS_GR16; + else if (r32) + rout->type = RAS_RGBM; + else if (r64) + rout->type = RAS_RGBM64; + else if (rcm) + rout->type = RAS_CM32; + else + assert(!"raster type not convertible!"); + + if (rout->type != RAS_CM32) return rout; + + if (!inPalette) { + assert(!"missing palette!"); + return NULL; + } + + rout->cmap.info = Tcm_32_default_info; + rout->cmap.buffer = new LPIXEL[TCM_CMAP_PENBUFFER_SIZE(rout->cmap.info)]; + // rout->cmap.penbuffer = new LPIXEL[TCM_CMAP_PENBUFFER_SIZE + // (rout->cmap.info)]; + // rout->cmap.colbuffer = new LPIXEL[TCM_CMAP_COLBUFFER_SIZE + // (rout->cmap.info)]; + + for (int i = 0; i < inPalette->getStyleCount(); i++) + rout->cmap.buffer[i] = + ::premultiplyLPIXEL(inPalette->getStyle(i)->getAverageColor()); + // fillCmapRamp (rout->cmap, inPalette->getStyle(i)->getMainColor(), i); - int lx = inRas->getLx(); - int ly = inRas->getLy(); - int wrap = inRas->getWrap(); - - assert(lx > 0 && ly > 0); - assert(inRas->getRawData()); - TRasterGR8P rgr8 = (TRasterGR8P)inRas; - TRasterGR16P rgr16 = (TRasterGR16P)inRas; - TRaster32P r32 = (TRaster32P)inRas; - TRaster64P r64 = (TRaster64P)inRas; - TRasterCM32P rcm = (TRasterCM32P)inRas; - - RASTER *rout = new RASTER; - memset(rout, 0, sizeof(RASTER)); - - std::string id(TImageCache::instance()->getUniqueId()); - rout->cacheIdLength = id.size(); - rout->cacheId = new char[rout->cacheIdLength]; - memcpy(rout->cacheId, id.data(), sizeof(char) * rout->cacheIdLength); - { - TImageP img; - if (rcm) - img = TToonzImageP(rcm, rcm->getBounds()); //saveBox is not considered in RASTER struct anyway - else - img = TRasterImageP(inRas); - TImageCache::instance()->add(id, img); - } - inRas->addRef(); - - rout->buffer = inRas->getRawData(); - TRasterP parent = inRas->getParent(); - rout->native_buffer = (parent) ? parent->getRawData() : inRas->getRawData(); - rout->lx = lx; - rout->ly = ly; - rout->wrap = wrap; - - if (rgr8) - rout->type = RAS_GR8; - else if (rgr16) - rout->type = RAS_GR16; - else if (r32) - rout->type = RAS_RGBM; - else if (r64) - rout->type = RAS_RGBM64; - else if (rcm) - rout->type = RAS_CM32; - else - assert(!"raster type not convertible!"); - - if (rout->type != RAS_CM32) - return rout; - - if (!inPalette) { - assert(!"missing palette!"); - return NULL; - } - - rout->cmap.info = Tcm_32_default_info; - rout->cmap.buffer = new LPIXEL[TCM_CMAP_PENBUFFER_SIZE(rout->cmap.info)]; - //rout->cmap.penbuffer = new LPIXEL[TCM_CMAP_PENBUFFER_SIZE (rout->cmap.info)]; - //rout->cmap.colbuffer = new LPIXEL[TCM_CMAP_COLBUFFER_SIZE (rout->cmap.info)]; - - for (int i = 0; i < inPalette->getStyleCount(); i++) - rout->cmap.buffer[i] = ::premultiplyLPIXEL(inPalette->getStyle(i)->getAverageColor()); - //fillCmapRamp (rout->cmap, inPalette->getStyle(i)->getMainColor(), i); - - return rout; + return rout; } /*------------------------------------------------------------------------*/ -void TRop::releaseRaster46(_RASTER *&r, bool doReleaseBuffer) -{ - //Buffer release no more supported. These are now intended as smart - //pointers to rasters - they release themselves on their own. - assert(!doReleaseBuffer); - - if (r->type == RAS_CM32) { - delete[] r->cmap.buffer; - //delete [] r->cmap.penbuffer; - //delete [] r->cmap.colbuffer; - } - - if (doReleaseBuffer && r->native_buffer == r->buffer) - delete r->buffer; //Should not happen - - //Unlock if locked, and remove the cache reference - if (r->buffer) - unlockRaster(r); - TImageCache::instance()->remove(std::string(r->cacheId, r->cacheIdLength)); - delete[] r->cacheId; - - delete r; - r = 0; +void TRop::releaseRaster46(_RASTER *&r, bool doReleaseBuffer) { + // Buffer release no more supported. These are now intended as smart + // pointers to rasters - they release themselves on their own. + assert(!doReleaseBuffer); + + if (r->type == RAS_CM32) { + delete[] r->cmap.buffer; + // delete [] r->cmap.penbuffer; + // delete [] r->cmap.colbuffer; + } + + if (doReleaseBuffer && r->native_buffer == r->buffer) + delete r->buffer; // Should not happen + + // Unlock if locked, and remove the cache reference + if (r->buffer) unlockRaster(r); + TImageCache::instance()->remove(std::string(r->cacheId, r->cacheIdLength)); + delete[] r->cacheId; + + delete r; + r = 0; } /*------------------------------------------------------------------------*/ -void TRop::lockRaster(RASTER *raster) -{ - TImageP img(TImageCache::instance()->get(std::string(raster->cacheId, raster->cacheIdLength), true)); - TRasterP cacheRas; - if (raster->type == RAS_CM32) - cacheRas = TToonzImageP(img)->getRaster(); - else - cacheRas = TRasterImageP(img)->getRaster(); - cacheRas->addRef(); - raster->buffer = cacheRas->getRawData(); - TRasterP parent = cacheRas->getParent(); - raster->native_buffer = (parent) ? parent->getRawData() : cacheRas->getRawData(); +void TRop::lockRaster(RASTER *raster) { + TImageP img(TImageCache::instance()->get( + std::string(raster->cacheId, raster->cacheIdLength), true)); + TRasterP cacheRas; + if (raster->type == RAS_CM32) + cacheRas = TToonzImageP(img)->getRaster(); + else + cacheRas = TRasterImageP(img)->getRaster(); + cacheRas->addRef(); + raster->buffer = cacheRas->getRawData(); + TRasterP parent = cacheRas->getParent(); + raster->native_buffer = + (parent) ? parent->getRawData() : cacheRas->getRawData(); } /*------------------------------------------------------------------------*/ -void TRop::unlockRaster(RASTER *raster) -{ - TImageP img(TImageCache::instance()->get(std::string(raster->cacheId, raster->cacheIdLength), true)); - TRasterP cacheRas; - if (raster->type == RAS_CM32) - cacheRas = TToonzImageP(img)->getRaster(); - else - cacheRas = TRasterImageP(img)->getRaster(); - cacheRas->release(); - raster->buffer = 0; - raster->native_buffer = 0; +void TRop::unlockRaster(RASTER *raster) { + TImageP img(TImageCache::instance()->get( + std::string(raster->cacheId, raster->cacheIdLength), true)); + TRasterP cacheRas; + if (raster->type == RAS_CM32) + cacheRas = TToonzImageP(img)->getRaster(); + else + cacheRas = TRasterImageP(img)->getRaster(); + cacheRas->release(); + raster->buffer = 0; + raster->native_buffer = 0; } /*------------------------------------------------------------------------*/ -_RASTER *TRop::readRaster46(const char *filename) -{ - //No more called in Toonz... +_RASTER *TRop::readRaster46(const char *filename) { + // No more called in Toonz... - TImageP img; + TImageP img; - TImageReader::load(TFilePath(filename), img); + TImageReader::load(TFilePath(filename), img); - if ((TToonzImageP)img) - return 0; + if ((TToonzImageP)img) return 0; - TRasterImageP rimg = (TRasterImageP)img; + TRasterImageP rimg = (TRasterImageP)img; - if (!rimg) - return 0; - TRasterP ras = rimg->getRaster(); + if (!rimg) return 0; + TRasterP ras = rimg->getRaster(); - return TRop::convertRaster50to46(ras, 0); + return TRop::convertRaster50to46(ras, 0); } -namespace -{ +namespace { inline TPixel32 getPix32(const TPixelCM32 &pixcm, - const std::vector &colors) -{ - int t = pixcm.getTone(); - int p = pixcm.getPaint(); - int i = pixcm.getInk(); - - if (t == TPixelCM32::getMaxTone()) - return colors[p]; - else if (t == 0) - return colors[i]; - else - return blend(colors[i], colors[p], t, TPixelCM32::getMaxTone()); + const std::vector &colors) { + int t = pixcm.getTone(); + int p = pixcm.getPaint(); + int i = pixcm.getInk(); + + if (t == TPixelCM32::getMaxTone()) + return colors[p]; + else if (t == 0) + return colors[i]; + else + return blend(colors[i], colors[p], t, TPixelCM32::getMaxTone()); } -} //namespace +} // namespace -//from 4.6 +// from 4.6 #ifdef LEVO -void TRop::zoomOutCm32Rgbm(const TRasterCM32P &rin, TRaster32P &rout, const TPalette &plt, - int x1, int y1, int x2, int y2, - int newx, int newy, int absZoomLevel) -{ - TPixelCM32 *rowin, *pixin, *in, win; - TPixel32 *rowout, *pixout, valin, valout; - int tmp_r, tmp_g, tmp_b, tmp_m; - int wrapin, wrapout; - int x, y, lx, ly, xlast, ylast, xrest, yrest, i, j; - int factor, fac_fac_2_bits; - int fac_fac, yrest_fac, fac_xrest, yrest_xrest; - int fac_fac_2, yrest_fac_2, fac_xrest_2, yrest_xrest_2; - int fac_fac_4; - - int count = plt.getStyleCount(); - int count2 = std::max(count, TPixelCM32::getMaxInk(), TPixelCM32::getMaxPaint()); - std::vector colors(count2); - for (i = 0; i < plt.getStyleCount(); i++) - colors[i] = ::premultiply(plt.getStyle(i)->getAverageColor()); - - lx = x2 - x1 + 1; - ly = y2 - y1 + 1; - factor = 1 << absZoomLevel; - xrest = lx & (factor - 1); - yrest = ly & (factor - 1); - xlast = x2 - xrest + 1; - ylast = y2 - yrest + 1; - fac_fac = factor * factor; - fac_fac_2 = fac_fac >> 1; - fac_fac_4 = fac_fac >> 2; - fac_fac_2_bits = 2 * absZoomLevel - 1; - yrest_fac = yrest * factor; - yrest_fac_2 = yrest_fac >> 1; - fac_xrest = factor * xrest; - fac_xrest_2 = fac_xrest >> 1; - yrest_xrest = yrest * xrest; - yrest_xrest_2 = yrest_xrest >> 1; - wrapin = rin->getWrap(); - wrapout = rout->getWrap(); - valout.m = 0xff; - - rowin = (TPixelCM32 *)rin->getRawData() + wrapin * y1 + x1; - rowout = (TPixel32 *)rout->getRawData() + wrapout * newy + newx; - for (y = y1; y < ylast; y += factor) { - pixin = rowin; - pixout = rowout; - for (x = x1; x < xlast; x += factor) { - tmp_r = tmp_g = tmp_b = tmp_m = 0; - in = pixin; - for (j = 0; j < factor; j += 2) { - for (i = 0; i < factor; i += 2) { - win = *in; - valin = getPix32(win, colors); - tmp_r += valin.r; - tmp_g += valin.g; - tmp_b += valin.b; - tmp_m += valin.m; - in += wrapin; - in++; - win = *in; - valin = getPix32(win, colors); - tmp_r += valin.r; - tmp_g += valin.g; - tmp_b += valin.b; - tmp_m += valin.m; - in -= wrapin; - in++; - } - in += 2 * wrapin - factor; - } - valout.r = (tmp_r + fac_fac_4) >> fac_fac_2_bits; - valout.g = (tmp_g + fac_fac_4) >> fac_fac_2_bits; - valout.b = (tmp_b + fac_fac_4) >> fac_fac_2_bits; - valout.m = (tmp_m + fac_fac_4) >> fac_fac_2_bits; - *pixout++ = valout; - pixin += factor; - } - if (xrest) { - tmp_r = tmp_g = tmp_b = tmp_m = 0; - for (j = 0; j < factor; j++) - for (i = 0; i < xrest; i++) { - win = pixin[i + j * wrapin]; - valin = getPix32(win, colors); - tmp_r += valin.r; - tmp_g += valin.g; - tmp_b += valin.b; - tmp_m += valin.m; - } - valout.r = (tmp_r + fac_xrest_2) / fac_xrest; - valout.g = (tmp_g + fac_xrest_2) / fac_xrest; - valout.b = (tmp_b + fac_xrest_2) / fac_xrest; - valout.m = (tmp_m + fac_xrest_2) / fac_xrest; - *pixout = valout; - } - rowin += wrapin * factor; - rowout += wrapout; - } - if (yrest) { - pixin = rowin; - pixout = rowout; - for (x = x1; x < xlast; x += factor) { - tmp_r = tmp_g = tmp_b = tmp_m = 0; - for (j = 0; j < yrest; j++) - for (i = 0; i < factor; i++) { - win = pixin[i + j * wrapin]; - valin = getPix32(win, colors); - tmp_r += valin.r; - tmp_g += valin.g; - tmp_b += valin.b; - tmp_m += valin.m; - } - valout.r = (tmp_r + yrest_fac_2) / yrest_fac; - valout.g = (tmp_g + yrest_fac_2) / yrest_fac; - valout.b = (tmp_b + yrest_fac_2) / yrest_fac; - valout.m = (tmp_m + yrest_fac_2) / yrest_fac; - *pixout++ = valout; - pixin += factor; - } - if (xrest) { - tmp_r = tmp_g = tmp_b = tmp_m = 0; - for (j = 0; j < yrest; j++) - for (i = 0; i < xrest; i++) { - win = pixin[i + j * wrapin]; - valin = getPix32(win, colors); - tmp_r += valin.r; - tmp_g += valin.g; - tmp_b += valin.b; - tmp_m += valin.m; - } - valout.r = (tmp_r + yrest_xrest_2) / yrest_xrest; - valout.g = (tmp_g + yrest_xrest_2) / yrest_xrest; - valout.b = (tmp_b + yrest_xrest_2) / yrest_xrest; - valout.m = (tmp_m + yrest_xrest_2) / yrest_xrest; - *pixout = valout; - } - } +void TRop::zoomOutCm32Rgbm(const TRasterCM32P &rin, TRaster32P &rout, + const TPalette &plt, int x1, int y1, int x2, int y2, + int newx, int newy, int absZoomLevel) { + TPixelCM32 *rowin, *pixin, *in, win; + TPixel32 *rowout, *pixout, valin, valout; + int tmp_r, tmp_g, tmp_b, tmp_m; + int wrapin, wrapout; + int x, y, lx, ly, xlast, ylast, xrest, yrest, i, j; + int factor, fac_fac_2_bits; + int fac_fac, yrest_fac, fac_xrest, yrest_xrest; + int fac_fac_2, yrest_fac_2, fac_xrest_2, yrest_xrest_2; + int fac_fac_4; + + int count = plt.getStyleCount(); + int count2 = + std::max(count, TPixelCM32::getMaxInk(), TPixelCM32::getMaxPaint()); + std::vector colors(count2); + for (i = 0; i < plt.getStyleCount(); i++) + colors[i] = ::premultiply(plt.getStyle(i)->getAverageColor()); + + lx = x2 - x1 + 1; + ly = y2 - y1 + 1; + factor = 1 << absZoomLevel; + xrest = lx & (factor - 1); + yrest = ly & (factor - 1); + xlast = x2 - xrest + 1; + ylast = y2 - yrest + 1; + fac_fac = factor * factor; + fac_fac_2 = fac_fac >> 1; + fac_fac_4 = fac_fac >> 2; + fac_fac_2_bits = 2 * absZoomLevel - 1; + yrest_fac = yrest * factor; + yrest_fac_2 = yrest_fac >> 1; + fac_xrest = factor * xrest; + fac_xrest_2 = fac_xrest >> 1; + yrest_xrest = yrest * xrest; + yrest_xrest_2 = yrest_xrest >> 1; + wrapin = rin->getWrap(); + wrapout = rout->getWrap(); + valout.m = 0xff; + + rowin = (TPixelCM32 *)rin->getRawData() + wrapin * y1 + x1; + rowout = (TPixel32 *)rout->getRawData() + wrapout * newy + newx; + for (y = y1; y < ylast; y += factor) { + pixin = rowin; + pixout = rowout; + for (x = x1; x < xlast; x += factor) { + tmp_r = tmp_g = tmp_b = tmp_m = 0; + in = pixin; + for (j = 0; j < factor; j += 2) { + for (i = 0; i < factor; i += 2) { + win = *in; + valin = getPix32(win, colors); + tmp_r += valin.r; + tmp_g += valin.g; + tmp_b += valin.b; + tmp_m += valin.m; + in += wrapin; + in++; + win = *in; + valin = getPix32(win, colors); + tmp_r += valin.r; + tmp_g += valin.g; + tmp_b += valin.b; + tmp_m += valin.m; + in -= wrapin; + in++; + } + in += 2 * wrapin - factor; + } + valout.r = (tmp_r + fac_fac_4) >> fac_fac_2_bits; + valout.g = (tmp_g + fac_fac_4) >> fac_fac_2_bits; + valout.b = (tmp_b + fac_fac_4) >> fac_fac_2_bits; + valout.m = (tmp_m + fac_fac_4) >> fac_fac_2_bits; + *pixout++ = valout; + pixin += factor; + } + if (xrest) { + tmp_r = tmp_g = tmp_b = tmp_m = 0; + for (j = 0; j < factor; j++) + for (i = 0; i < xrest; i++) { + win = pixin[i + j * wrapin]; + valin = getPix32(win, colors); + tmp_r += valin.r; + tmp_g += valin.g; + tmp_b += valin.b; + tmp_m += valin.m; + } + valout.r = (tmp_r + fac_xrest_2) / fac_xrest; + valout.g = (tmp_g + fac_xrest_2) / fac_xrest; + valout.b = (tmp_b + fac_xrest_2) / fac_xrest; + valout.m = (tmp_m + fac_xrest_2) / fac_xrest; + *pixout = valout; + } + rowin += wrapin * factor; + rowout += wrapout; + } + if (yrest) { + pixin = rowin; + pixout = rowout; + for (x = x1; x < xlast; x += factor) { + tmp_r = tmp_g = tmp_b = tmp_m = 0; + for (j = 0; j < yrest; j++) + for (i = 0; i < factor; i++) { + win = pixin[i + j * wrapin]; + valin = getPix32(win, colors); + tmp_r += valin.r; + tmp_g += valin.g; + tmp_b += valin.b; + tmp_m += valin.m; + } + valout.r = (tmp_r + yrest_fac_2) / yrest_fac; + valout.g = (tmp_g + yrest_fac_2) / yrest_fac; + valout.b = (tmp_b + yrest_fac_2) / yrest_fac; + valout.m = (tmp_m + yrest_fac_2) / yrest_fac; + *pixout++ = valout; + pixin += factor; + } + if (xrest) { + tmp_r = tmp_g = tmp_b = tmp_m = 0; + for (j = 0; j < yrest; j++) + for (i = 0; i < xrest; i++) { + win = pixin[i + j * wrapin]; + valin = getPix32(win, colors); + tmp_r += valin.r; + tmp_g += valin.g; + tmp_b += valin.b; + tmp_m += valin.m; + } + valout.r = (tmp_r + yrest_xrest_2) / yrest_xrest; + valout.g = (tmp_g + yrest_xrest_2) / yrest_xrest; + valout.b = (tmp_b + yrest_xrest_2) / yrest_xrest; + valout.m = (tmp_m + yrest_xrest_2) / yrest_xrest; + *pixout = valout; + } + } } #endif @@ -1262,126 +1267,129 @@ void TRop::zoomOutCm32Rgbm(const TRasterCM32P &rin, TRaster32P &rout, const TPal #ifdef LEVO -void TRop::makeIcon(TRaster32P &_rout, const TRasterCM32P &rin, const TPaletteP &palette, bool onBlackBg) -{ - int i, j; - int lx = rin->getLx(); - int ly = rin->getLy(); - - int count = palette->getStyleCount(); - int count2 = std::max(count, TPixelCM32::getMaxInk(), TPixelCM32::getMaxPaint()); - std::vector colors(count2); - for (i = 0; i < palette->getStyleCount(); i++) - colors[i] = /*::premultiply(*/ palette->getStyle(i)->getAverageColor(); //); - - TDimension dim(_rout->getSize()); - TRaster32P rout; - - double arIn = (double)lx / ly; - double arOut = (double)dim.lx / dim.ly; - if (!areAlmostEqual(arIn, arOut, 1e-2)) //do not want a stretched icon! I extract a subraster with same aspect ration of rin - { - int newlx, newly; - if (arOut < arIn) { - newlx = dim.lx; - newly = dim.lx / arIn; - } else { - newly = dim.ly; - newlx = dim.ly * arIn; - } - _rout->clear(); - rout = _rout->extract((dim.lx - newlx) / 2, (dim.ly - newly) / 2, - (dim.lx - newlx) / 2 + newlx - 1, (dim.ly - newly) / 2 + newly - 1); - dim = rout->getSize(); - } else - rout = _rout; - - TPixel32 *pixOut0 = (TPixel32 *)rout->getRawData(); - - int countY = 0; - bool newRow = true; - int currTone = TPixelCM32::getMaxTone(); - - for (i = 0; i < ly; i++) { - TPixelCM32 *pixIn = (TPixelCM32 *)rin->pixels(i); - TPixel32 *pixOut = pixOut0; - int countX = 0; - for (j = 0; j < lx; j++) { - if (newRow || currTone > pixIn->getTone()) { - currTone = pixIn->getTone(); - if (onBlackBg) - *pixOut = overPixOnBlack(getPix32(*pixIn, colors)); - else - *pixOut = overPixOnWhite(getPix32(*pixIn, colors)); - } - pixIn++; - countX += dim.lx; - if (countX >= lx) - countX -= lx, pixOut++, currTone = TPixelCM32::getMaxTone(); - } - - countY += dim.ly; - if (countY >= ly) { - countY -= ly; - pixOut0 += rout->getWrap(); - currTone = TPixelCM32::getMaxTone(); - newRow = true; - } else - newRow = false; - } +void TRop::makeIcon(TRaster32P &_rout, const TRasterCM32P &rin, + const TPaletteP &palette, bool onBlackBg) { + int i, j; + int lx = rin->getLx(); + int ly = rin->getLy(); + + int count = palette->getStyleCount(); + int count2 = + std::max(count, TPixelCM32::getMaxInk(), TPixelCM32::getMaxPaint()); + std::vector colors(count2); + for (i = 0; i < palette->getStyleCount(); i++) + colors[i] = + /*::premultiply(*/ palette->getStyle(i)->getAverageColor(); //); + + TDimension dim(_rout->getSize()); + TRaster32P rout; + + double arIn = (double)lx / ly; + double arOut = (double)dim.lx / dim.ly; + if (!areAlmostEqual(arIn, arOut, 1e-2)) // do not want a stretched icon! I + // extract a subraster with same + // aspect ration of rin + { + int newlx, newly; + if (arOut < arIn) { + newlx = dim.lx; + newly = dim.lx / arIn; + } else { + newly = dim.ly; + newlx = dim.ly * arIn; + } + _rout->clear(); + rout = _rout->extract((dim.lx - newlx) / 2, (dim.ly - newly) / 2, + (dim.lx - newlx) / 2 + newlx - 1, + (dim.ly - newly) / 2 + newly - 1); + dim = rout->getSize(); + } else + rout = _rout; + + TPixel32 *pixOut0 = (TPixel32 *)rout->getRawData(); + + int countY = 0; + bool newRow = true; + int currTone = TPixelCM32::getMaxTone(); + + for (i = 0; i < ly; i++) { + TPixelCM32 *pixIn = (TPixelCM32 *)rin->pixels(i); + TPixel32 *pixOut = pixOut0; + int countX = 0; + for (j = 0; j < lx; j++) { + if (newRow || currTone > pixIn->getTone()) { + currTone = pixIn->getTone(); + if (onBlackBg) + *pixOut = overPixOnBlack(getPix32(*pixIn, colors)); + else + *pixOut = overPixOnWhite(getPix32(*pixIn, colors)); + } + pixIn++; + countX += dim.lx; + if (countX >= lx) + countX -= lx, pixOut++, currTone = TPixelCM32::getMaxTone(); + } + + countY += dim.ly; + if (countY >= ly) { + countY -= ly; + pixOut0 += rout->getWrap(); + currTone = TPixelCM32::getMaxTone(); + newRow = true; + } else + newRow = false; + } } #endif /*-----------------------------------------------------------------------------*/ -void TRop::makeIcon(TRasterCM32P &_rout, const TRasterCM32P &rin) -{ - int i, j; - int lx = rin->getLx(); - int ly = rin->getLy(); - - TDimension dim(_rout->getSize()); - TRasterCM32P rout; - - rout = _rout; - - rout->lock(); - rin->lock(); - TPixelCM32 *pixOut0 = (TPixelCM32 *)rout->getRawData(); - - int countY = 0; - bool newRow = true; - - for (i = 0; i < ly; i++) { - TPixelCM32 *pixIn = (TPixelCM32 *)rin->pixels(i); - TPixelCM32 *pixOut = pixOut0; - int countX = 0; - bool newColumn = true; - for (j = 0; j < lx; j++) { - if ((newRow && newColumn) || - pixOut->getTone() > pixIn->getTone()) - *pixOut = *pixIn; - - pixIn++; - countX += dim.lx; - if (countX >= lx) { - countX -= lx, pixOut++; - newColumn = true; - } else - newColumn = false; - } - - countY += dim.ly; - if (countY >= ly) { - countY -= ly; - pixOut0 += rout->getWrap(); - newRow = true; - } else - newRow = false; - } - rout->unlock(); - rin->unlock(); +void TRop::makeIcon(TRasterCM32P &_rout, const TRasterCM32P &rin) { + int i, j; + int lx = rin->getLx(); + int ly = rin->getLy(); + + TDimension dim(_rout->getSize()); + TRasterCM32P rout; + + rout = _rout; + + rout->lock(); + rin->lock(); + TPixelCM32 *pixOut0 = (TPixelCM32 *)rout->getRawData(); + + int countY = 0; + bool newRow = true; + + for (i = 0; i < ly; i++) { + TPixelCM32 *pixIn = (TPixelCM32 *)rin->pixels(i); + TPixelCM32 *pixOut = pixOut0; + int countX = 0; + bool newColumn = true; + for (j = 0; j < lx; j++) { + if ((newRow && newColumn) || pixOut->getTone() > pixIn->getTone()) + *pixOut = *pixIn; + + pixIn++; + countX += dim.lx; + if (countX >= lx) { + countX -= lx, pixOut++; + newColumn = true; + } else + newColumn = false; + } + + countY += dim.ly; + if (countY >= ly) { + countY -= ly; + pixOut0 += rout->getWrap(); + newRow = true; + } else + newRow = false; + } + rout->unlock(); + rin->unlock(); } /*-----------------------------------------------------------------------------*/ diff --git a/toonz/sources/common/tsound/tsop.cpp b/toonz/sources/common/tsound/tsop.cpp index 0d30987..8403dfc 100644 --- a/toonz/sources/common/tsound/tsop.cpp +++ b/toonz/sources/common/tsound/tsop.cpp @@ -5,1432 +5,1309 @@ #include "tsop.h" #include "tsound_t.h" -//TRop::ResampleFilterType Tau_resample_filter = Hamming3; +// TRop::ResampleFilterType Tau_resample_filter = Hamming3; //--------------------------------------------------------- typedef enum { - FLT_NONE, - - FLT_TRIANGLE, /* triangle filter */ - FLT_MITCHELL, /* Mitchell-Netravali filter */ - FLT_CUBIC_5, /* cubic convolution, a = .5 */ - FLT_CUBIC_75, /* cubic convolution, a = .75 */ - FLT_CUBIC_1, /* cubic convolution, a = 1 */ - FLT_HANN2, /* Hann window, rad = 2 */ - FLT_HANN3, /* Hann window, rad = 3 */ - FLT_HAMMING2, /* Hamming window, rad = 2 */ - FLT_HAMMING3, /* Hamming window, rad = 3 */ - FLT_LANCZOS2, /* Lanczos window, rad = 2 */ - FLT_LANCZOS3, /* Lanczos window, rad = 3 */ - FLT_GAUSS, /* Gaussian convolution */ - - FLT_HOW_MANY + FLT_NONE, + + FLT_TRIANGLE, /* triangle filter */ + FLT_MITCHELL, /* Mitchell-Netravali filter */ + FLT_CUBIC_5, /* cubic convolution, a = .5 */ + FLT_CUBIC_75, /* cubic convolution, a = .75 */ + FLT_CUBIC_1, /* cubic convolution, a = 1 */ + FLT_HANN2, /* Hann window, rad = 2 */ + FLT_HANN3, /* Hann window, rad = 3 */ + FLT_HAMMING2, /* Hamming window, rad = 2 */ + FLT_HAMMING3, /* Hamming window, rad = 3 */ + FLT_LANCZOS2, /* Lanczos window, rad = 2 */ + FLT_LANCZOS3, /* Lanczos window, rad = 3 */ + FLT_GAUSS, /* Gaussian convolution */ + + FLT_HOW_MANY } FLT_TYPE; //--------------------------------------------------------- typedef enum { - RESORDER_NONE, - RESORDER_BITS_RATE_CHANS, - RESORDER_CHANS_RATE_BITS, - RESORDER_RATE_BITS_CHANS, - RESORDER_CHANS_BITS_RATE, - RESORDER_BITS_RATE, - RESORDER_RATE_BITS, - RESORDER_CHANS_RATE, - RESORDER_RATE_CHANS, - RESORDER_RATE, - RESORDER_SIGN, - RESORDER_HOW_MANY + RESORDER_NONE, + RESORDER_BITS_RATE_CHANS, + RESORDER_CHANS_RATE_BITS, + RESORDER_RATE_BITS_CHANS, + RESORDER_CHANS_BITS_RATE, + RESORDER_BITS_RATE, + RESORDER_RATE_BITS, + RESORDER_CHANS_RATE, + RESORDER_RATE_CHANS, + RESORDER_RATE, + RESORDER_SIGN, + RESORDER_HOW_MANY } RESORDER_TYPE; //--------------------------------------------------------- -typedef struct - { - int src_offset; /* of weight[0] relative to start of period */ - int n_weights; - double *weight; /* [n_weights], -1.0 <= weight <= 1.0 */ +typedef struct { + int src_offset; /* of weight[0] relative to start of period */ + int n_weights; + double *weight; /* [n_weights], -1.0 <= weight <= 1.0 */ } WEIGHTSET; //--------------------------------------------------------- -typedef struct - { - int src_period; /* after a period src and dst are in step again */ - int dst_period; - WEIGHTSET *weightset; /* [dst_period] */ +typedef struct { + int src_period; /* after a period src and dst are in step again */ + int dst_period; + WEIGHTSET *weightset; /* [dst_period] */ } FILTER; //--------------------------------------------------------- -#define M_PIF ((float)TConsts::pi) -#define SINC0(x, a) (sin((TConsts::pi / (a)) * (x)) / ((TConsts::pi / (a)) * (x))) +#define M_PIF float(M_PI) +#define SINC0(x, a) (sin((M_PI / (a)) * (x)) / ((M_PI / (a)) * (x))) #define SINC0F(x, a) (sinf((M_PIF / (a)) * (x)) / ((M_PIF / (a)) * (x))) #define SINC(x, a) ((x) == 0.0 ? 1.0 : SINC0(x, a)) #define SINCF(x, a) ((x) == 0.0F ? 1.0F : SINC0F(x, a)) #define FULL_INT_MUL_DIV(X, Y, Z) ((int)(((double)(X) * (Y) + ((Z)-1)) / (Z))) -//prototipi +// prototipi void convert(TSoundTrackP &dst, const TSoundTrackP &src); -namespace -{ +namespace { //--------------------------------------------------------- -void simplifyRatio(int *p_a, int *p_b) -{ - int a = *p_a, b = *p_b; - - while (a != b) - if (a > b) - a -= b; - else - b -= a; - if (a != 1) { - *p_a /= a; - *p_b /= a; - } +void simplifyRatio(int *p_a, int *p_b) { + int a = *p_a, b = *p_b; + + while (a != b) + if (a > b) + a -= b; + else + b -= a; + if (a != 1) { + *p_a /= a; + *p_b /= a; + } } //--------------------------------------------------------- -int getFilterRadius(FLT_TYPE flt_type) -{ - int result = 0; - switch (flt_type) { - case FLT_TRIANGLE: result = 1; break; - case FLT_MITCHELL: result = 2; break; - case FLT_CUBIC_5 : result = 2; break; - case FLT_CUBIC_75: result = 2; break; - case FLT_CUBIC_1 : result = 2; break; - case FLT_HANN2 : result = 2; break; - case FLT_HANN3 : result = 3; break; - case FLT_HAMMING2: result = 2; break; - case FLT_HAMMING3: result = 3; break; - case FLT_LANCZOS2: result = 2; break; - case FLT_LANCZOS3: result = 3; break; - case FLT_GAUSS : result = 2; break; - default: - assert(!"bad filter type"); - break; - } - return result; +int getFilterRadius(FLT_TYPE flt_type) { + int result = 0; + switch (flt_type) { + case FLT_TRIANGLE: + result = 1; + break; + case FLT_MITCHELL: + result = 2; + break; + case FLT_CUBIC_5: + result = 2; + break; + case FLT_CUBIC_75: + result = 2; + break; + case FLT_CUBIC_1: + result = 2; + break; + case FLT_HANN2: + result = 2; + break; + case FLT_HANN3: + result = 3; + break; + case FLT_HAMMING2: + result = 2; + break; + case FLT_HAMMING3: + result = 3; + break; + case FLT_LANCZOS2: + result = 2; + break; + case FLT_LANCZOS3: + result = 3; + break; + case FLT_GAUSS: + result = 2; + break; + default: + assert(!"bad filter type"); + break; + } + return result; } //--------------------------------------------------------- -double filterValue(FLT_TYPE flt_type, double x) -{ - if (!x) - return 1.0; - double result; - switch (flt_type) { - case FLT_TRIANGLE: - if (x < -1.0) - result = 0.0; - else if (x < 0.0) - result = 1.0 + x; - else if (x < 1.0) - result = 1.0 - x; - else - result = 0.0; - break; - - case FLT_MITCHELL: - { - static double p0, p2, p3, q0, q1, q2, q3; - - if (!p0) { - const double b = 1.0 / 3.0; - const double c = 1.0 / 3.0; - - p0 = (6.0 - 2.0 * b) / 6.0; - p2 = (-18.0 + 12.0 * b + 6.0 * c) / 6.0; - p3 = (12.0 - 9.0 * b - 6.0 * c) / 6.0; - q0 = (8.0 * b + 24.0 * c) / 6.0; - q1 = (-12.0 * b - 48.0 * c) / 6.0; - q2 = (6.0 * b + 30.0 * c) / 6.0; - q3 = (-b - 6.0 * c) / 6.0; - } - if (x < -2.0) - result = 0.0; - else if (x < -1.0) - result = (q0 - x * (q1 - x * (q2 - x * q3))); - else if (x < 0.0) - result = (p0 + x * x * (p2 - x * p3)); - else if (x < 1.0) - result = (p0 + x * x * (p2 + x * p3)); - else if (x < 2.0) - result = (q0 + x * (q1 + x * (q2 + x * q3))); - - break; - } - - case FLT_CUBIC_5: - if (x < 0.0) x = -x; - else if (x < 1.0) result = 2.5 * x * x * x - 3.5 * x * x + 1; - else if (x < 2.0) result = 0.5 * x * x * x - 2.5 * x * x + 4 * x - 2; - break; - - case FLT_CUBIC_75: - if (x < 0.0) x = -x; - else if (x < 1.0) result = 2.75 * x * x * x - 3.75 * x * x + 1; - else if (x < 2.0) result = 0.75 * x * x * x - 3.75 * x * x + 6 * x - 3; - break; - - case FLT_CUBIC_1: - if (x < 0.0) x = -x; - else if (x < 1.0) result = 3 * x * x * x - 4 * x * x + 1; - else if (x < 2.0) result = x * x * x - 5 * x * x + 8 * x - 4; - break; - - case FLT_HANN2: - if (x <= -2.0) result = 0.0; - else if (x < 2.0) result = SINC0(x, 1) * (0.5 + 0.5 * cos((TConsts::pi_2)*x)); - break; - - case FLT_HANN3: - if (x <= -3.0) result = 0.0; - else if (x < 3.0) result = SINC0(x, 1) * (0.5 + 0.5 * cos((TConsts::pi / 3) * x)); - break; - - case FLT_HAMMING2: - if (x <= -2.0) result = 0.0; - else if (x < 2.0) result = SINC0(x, 1) * (0.54 + 0.46 * cos((TConsts::pi_2)*x)); - break; - - case FLT_HAMMING3: - if (x <= -3.0) result = 0.0; - else if (x < 3.0) result = SINC0(x, 1) * (0.54 + 0.46 * cos((TConsts::pi / 3) * x)); - break; - - case FLT_LANCZOS2: - if (x <= -2.0) result = 0.0; - else if (x < 2.0) result = SINC0(x, 1) * SINC0(x, 2); - break; - - case FLT_LANCZOS3: - if (x <= -3.0) result = 0.0; - else if (x < 3.0) result = SINC0(x, 1) * SINC0(x, 3); - break; - - case FLT_GAUSS: - if (x <= -2.0) result = 0.0; - else if (x < 2.0) result = exp((-TConsts::pi) * x * x); - /* exp(-M_PI*2*2)~=3.5*10^-6 */ - break; - - default: - assert(!"bad filter type"); - } - return result; +double filterValue(FLT_TYPE flt_type, double x) { + if (!x) return 1.0; + double result; + switch (flt_type) { + case FLT_TRIANGLE: + if (x < -1.0) + result = 0.0; + else if (x < 0.0) + result = 1.0 + x; + else if (x < 1.0) + result = 1.0 - x; + else + result = 0.0; + break; + + case FLT_MITCHELL: { + static double p0, p2, p3, q0, q1, q2, q3; + + if (!p0) { + const double b = 1.0 / 3.0; + const double c = 1.0 / 3.0; + + p0 = (6.0 - 2.0 * b) / 6.0; + p2 = (-18.0 + 12.0 * b + 6.0 * c) / 6.0; + p3 = (12.0 - 9.0 * b - 6.0 * c) / 6.0; + q0 = (8.0 * b + 24.0 * c) / 6.0; + q1 = (-12.0 * b - 48.0 * c) / 6.0; + q2 = (6.0 * b + 30.0 * c) / 6.0; + q3 = (-b - 6.0 * c) / 6.0; + } + if (x < -2.0) + result = 0.0; + else if (x < -1.0) + result = (q0 - x * (q1 - x * (q2 - x * q3))); + else if (x < 0.0) + result = (p0 + x * x * (p2 - x * p3)); + else if (x < 1.0) + result = (p0 + x * x * (p2 + x * p3)); + else if (x < 2.0) + result = (q0 + x * (q1 + x * (q2 + x * q3))); + + break; + } + + case FLT_CUBIC_5: + if (x < 0.0) + x = -x; + else if (x < 1.0) + result = 2.5 * x * x * x - 3.5 * x * x + 1; + else if (x < 2.0) + result = 0.5 * x * x * x - 2.5 * x * x + 4 * x - 2; + break; + + case FLT_CUBIC_75: + if (x < 0.0) + x = -x; + else if (x < 1.0) + result = 2.75 * x * x * x - 3.75 * x * x + 1; + else if (x < 2.0) + result = 0.75 * x * x * x - 3.75 * x * x + 6 * x - 3; + break; + + case FLT_CUBIC_1: + if (x < 0.0) + x = -x; + else if (x < 1.0) + result = 3 * x * x * x - 4 * x * x + 1; + else if (x < 2.0) + result = x * x * x - 5 * x * x + 8 * x - 4; + break; + + case FLT_HANN2: + if (x <= -2.0) + result = 0.0; + else if (x < 2.0) + result = SINC0(x, 1) * (0.5 + 0.5 * cos(M_PI_2 * x)); + break; + + case FLT_HANN3: + if (x <= -3.0) + result = 0.0; + else if (x < 3.0) + result = SINC0(x, 1) * (0.5 + 0.5 * cos((M_PI / 3) * x)); + break; + + case FLT_HAMMING2: + if (x <= -2.0) + result = 0.0; + else if (x < 2.0) + result = SINC0(x, 1) * (0.54 + 0.46 * cos(M_PI_2 * x)); + break; + + case FLT_HAMMING3: + if (x <= -3.0) + result = 0.0; + else if (x < 3.0) + result = SINC0(x, 1) * (0.54 + 0.46 * cos((M_PI / 3) * x)); + break; + + case FLT_LANCZOS2: + if (x <= -2.0) + result = 0.0; + else if (x < 2.0) + result = SINC0(x, 1) * SINC0(x, 2); + break; + + case FLT_LANCZOS3: + if (x <= -3.0) + result = 0.0; + else if (x < 3.0) + result = SINC0(x, 1) * SINC0(x, 3); + break; + + case FLT_GAUSS: + if (x <= -2.0) + result = 0.0; + else if (x < 2.0) + result = exp((-M_PI) * x * x); + /* exp(-M_PI*2*2)~=3.5*10^-6 */ + break; + + default: + assert(!"bad filter type"); + } + return result; } //--------------------------------------------------------- -} //namespace +} // namespace //============================================================================== template -void convertSamplesT(TSoundTrackT &dst, const TSoundTrackT &src) -{ - const T2 *srcSample = src.samples(); - T1 *dstSample = dst.samples(); - - const T2 *srcEndSample = srcSample + std::min(src.getSampleCount(), dst.getSampleCount()); - while (srcSample < srcEndSample) { - *dstSample = T1::from(*srcSample); - ++dstSample; - ++srcSample; - } +void convertSamplesT(TSoundTrackT &dst, const TSoundTrackT &src) { + const T2 *srcSample = src.samples(); + T1 *dstSample = dst.samples(); + + const T2 *srcEndSample = + srcSample + std::min(src.getSampleCount(), dst.getSampleCount()); + while (srcSample < srcEndSample) { + *dstSample = T1::from(*srcSample); + ++dstSample; + ++srcSample; + } } //============================================================================== template -T *resampleT(T &src, TINT32 sampleRate, FLT_TYPE flt_type) -{ - typedef typename T::SampleType SampleType; - typedef typename T::SampleType::ChannelValueType ChannelValueType; - T *dst = new TSoundTrackT( - sampleRate, - src.getChannelCount(), - (TINT32)(src.getSampleCount() * (sampleRate / (double)src.getSampleRate()))); - - double src_rad, f, src_f0, src_to_f; - double weight, weightsum; - int iw, is, s0, ip, first, last; - - FILTER filter; - filter.src_period = (int)src.getSampleRate(); - filter.dst_period = (int)dst->getSampleRate(); - simplifyRatio(&filter.src_period, &filter.dst_period); - filter.weightset = new WEIGHTSET[filter.dst_period]; - if (!filter.weightset) - return 0; - - int flt_rad = getFilterRadius(flt_type); - double dstRate = (double)dst->getSampleRate(); - double srcRate = (double)src.getSampleRate(); - double dst_to_src = srcRate / dstRate; - if (srcRate > dstRate) { - src_rad = flt_rad * dst_to_src; - src_to_f = dstRate / srcRate; - } else { - src_rad = flt_rad; - src_to_f = 1.0; - } - - for (ip = 0; ip < filter.dst_period; ip++) { - src_f0 = ip * dst_to_src; - if (ip == 0 && srcRate < dstRate) - first = last = 0; - else { - first = intGT(src_f0 - src_rad); - last = intLT(src_f0 + src_rad); - } - - filter.weightset[ip].src_offset = first; - filter.weightset[ip].n_weights = last - first + 1; - filter.weightset[ip].weight = new double[filter.weightset[ip].n_weights]; - - if (!filter.weightset[ip].weight) - return 0; - - weightsum = 0.0; - for (is = first; is <= last; is++) { - f = (is - src_f0) * src_to_f; - weight = filterValue(flt_type, f); - filter.weightset[ip].weight[is - first] = weight; - weightsum += weight; - } - assert(weightsum); - for (is = first; is <= last; is++) - filter.weightset[ip].weight[is - first] /= weightsum; - } - - ip = 0; - s0 = 0; - - for (TINT32 id = 0; id < dst->getSampleCount(); id++) { - SampleType dstSample; - SampleType srcSample; - - is = s0 + filter.weightset[ip].src_offset; - - int iwFirst, iwLast; - if (is > 0) { - iwFirst = 0; - iwLast = std::min(filter.weightset[ip].n_weights, src.getSampleCount() - is); - } else { - iwFirst = -is; - is = 0; - iwLast = std::min(filter.weightset[ip].n_weights, src.getSampleCount()); - } - - double dstChannel[2]; - - dstChannel[0] = 0; - dstChannel[1] = 0; - - dstSample = SampleType(); - - for (iw = iwFirst; iw < iwLast; iw++, is++) { - weight = filter.weightset[ip].weight[iw]; - - srcSample = *(src.samples() + is); - - /* - T::SampleType tmp = srcSample*weight; - dstSample += tmp; - */ - - for (int i = 0; i < src.getChannelCount(); i++) - dstChannel[i] += (double)(srcSample.getValue(i) * weight); - - //assert(dstSample.getValue(0) == dstChannel[0]); - } - - for (int i = 0; i < src.getChannelCount(); i++) - dstSample.setValue(i, (ChannelValueType)(tround(dstChannel[i]))); - - *(dst->samples() + id) = dstSample; - - ip++; - if (ip == filter.dst_period) { - ip = 0; - s0 += filter.src_period; - } - } - - for (ip = 0; ip < filter.dst_period; ip++) - delete[] filter.weightset[ip].weight; - - delete[] filter.weightset; - return dst; +T *resampleT(T &src, TINT32 sampleRate, FLT_TYPE flt_type) { + typedef typename T::SampleType SampleType; + typedef typename T::SampleType::ChannelValueType ChannelValueType; + T *dst = new TSoundTrackT( + sampleRate, src.getChannelCount(), + (TINT32)(src.getSampleCount() * + (sampleRate / (double)src.getSampleRate()))); + + double src_rad, f, src_f0, src_to_f; + double weight, weightsum; + int iw, is, s0, ip, first, last; + + FILTER filter; + filter.src_period = (int)src.getSampleRate(); + filter.dst_period = (int)dst->getSampleRate(); + simplifyRatio(&filter.src_period, &filter.dst_period); + filter.weightset = new WEIGHTSET[filter.dst_period]; + if (!filter.weightset) return 0; + + int flt_rad = getFilterRadius(flt_type); + double dstRate = (double)dst->getSampleRate(); + double srcRate = (double)src.getSampleRate(); + double dst_to_src = srcRate / dstRate; + if (srcRate > dstRate) { + src_rad = flt_rad * dst_to_src; + src_to_f = dstRate / srcRate; + } else { + src_rad = flt_rad; + src_to_f = 1.0; + } + + for (ip = 0; ip < filter.dst_period; ip++) { + src_f0 = ip * dst_to_src; + if (ip == 0 && srcRate < dstRate) + first = last = 0; + else { + first = intGT(src_f0 - src_rad); + last = intLT(src_f0 + src_rad); + } + + filter.weightset[ip].src_offset = first; + filter.weightset[ip].n_weights = last - first + 1; + filter.weightset[ip].weight = new double[filter.weightset[ip].n_weights]; + + if (!filter.weightset[ip].weight) return 0; + + weightsum = 0.0; + for (is = first; is <= last; is++) { + f = (is - src_f0) * src_to_f; + weight = filterValue(flt_type, f); + filter.weightset[ip].weight[is - first] = weight; + weightsum += weight; + } + assert(weightsum); + for (is = first; is <= last; is++) + filter.weightset[ip].weight[is - first] /= weightsum; + } + + ip = 0; + s0 = 0; + + for (TINT32 id = 0; id < dst->getSampleCount(); id++) { + SampleType dstSample; + SampleType srcSample; + + is = s0 + filter.weightset[ip].src_offset; + + int iwFirst, iwLast; + if (is > 0) { + iwFirst = 0; + iwLast = std::min(filter.weightset[ip].n_weights, + src.getSampleCount() - is); + } else { + iwFirst = -is; + is = 0; + iwLast = + std::min(filter.weightset[ip].n_weights, src.getSampleCount()); + } + + double dstChannel[2]; + + dstChannel[0] = 0; + dstChannel[1] = 0; + + dstSample = SampleType(); + + for (iw = iwFirst; iw < iwLast; iw++, is++) { + weight = filter.weightset[ip].weight[iw]; + + srcSample = *(src.samples() + is); + + /* +T::SampleType tmp = srcSample*weight; +dstSample += tmp; +*/ + + for (int i = 0; i < src.getChannelCount(); i++) + dstChannel[i] += (double)(srcSample.getValue(i) * weight); + + // assert(dstSample.getValue(0) == dstChannel[0]); + } + + for (int i = 0; i < src.getChannelCount(); i++) + dstSample.setValue(i, (ChannelValueType)(tround(dstChannel[i]))); + + *(dst->samples() + id) = dstSample; + + ip++; + if (ip == filter.dst_period) { + ip = 0; + s0 += filter.src_period; + } + } + + for (ip = 0; ip < filter.dst_period; ip++) + delete[] filter.weightset[ip].weight; + + delete[] filter.weightset; + return dst; } //============================================================================= -class TSoundTrackResample : public TSoundTransform -{ - TINT32 m_sampleRate; - FLT_TYPE m_filterType; +class TSoundTrackResample : public TSoundTransform { + TINT32 m_sampleRate; + FLT_TYPE m_filterType; public: - TSoundTrackResample(TINT32 sampleRate, FLT_TYPE filterType) - : TSoundTransform(), m_sampleRate(sampleRate), m_filterType(filterType) - { - } - - ~TSoundTrackResample(){}; - - TSoundTrackP compute(const TSoundTrackMono8Signed &src) - { - TSoundTrackMono8Signed *dst = resampleT( - const_cast(src), - m_sampleRate, m_filterType); - - return TSoundTrackP(dst); - } - - TSoundTrackP compute(const TSoundTrackMono8Unsigned &src) - { - - TSoundTrackMono8Unsigned *dst = resampleT( - const_cast(src), - m_sampleRate, m_filterType); - - return TSoundTrackP(dst); - } - - TSoundTrackP compute(const TSoundTrackStereo8Signed &src) - { - TSoundTrackStereo8Signed *dst = resampleT( - const_cast(src), - m_sampleRate, m_filterType); - - return TSoundTrackP(dst); - } - - TSoundTrackP compute(const TSoundTrackStereo8Unsigned &src) - { - TSoundTrackStereo8Unsigned *dst = resampleT( - const_cast(src), - m_sampleRate, m_filterType); - - return TSoundTrackP(dst); - } - - TSoundTrackP compute(const TSoundTrackMono16 &src) - { - TSoundTrackMono16 *dst = resampleT( - const_cast(src), - m_sampleRate, m_filterType); - - return TSoundTrackP(dst); - } - - TSoundTrackP compute(const TSoundTrackStereo16 &src) - { - TSoundTrackStereo16 *dst = resampleT( - const_cast(src), - m_sampleRate, m_filterType); - - return TSoundTrackP(dst); - } - - TSoundTrackP compute(const TSoundTrackMono24 &src) - { - TSoundTrackMono24 *dst = resampleT( - const_cast(src), - m_sampleRate, m_filterType); - - return TSoundTrackP(dst); - } - - TSoundTrackP compute(const TSoundTrackStereo24 &src) - { - TSoundTrackStereo24 *dst = resampleT( - const_cast(src), - m_sampleRate, m_filterType); - - return TSoundTrackP(dst); - } + TSoundTrackResample(TINT32 sampleRate, FLT_TYPE filterType) + : TSoundTransform(), m_sampleRate(sampleRate), m_filterType(filterType) {} + + ~TSoundTrackResample(){}; + + TSoundTrackP compute(const TSoundTrackMono8Signed &src) { + TSoundTrackMono8Signed *dst = resampleT( + const_cast(src), m_sampleRate, m_filterType); + + return TSoundTrackP(dst); + } + + TSoundTrackP compute(const TSoundTrackMono8Unsigned &src) { + TSoundTrackMono8Unsigned *dst = + resampleT(const_cast(src), m_sampleRate, + m_filterType); + + return TSoundTrackP(dst); + } + + TSoundTrackP compute(const TSoundTrackStereo8Signed &src) { + TSoundTrackStereo8Signed *dst = + resampleT(const_cast(src), m_sampleRate, + m_filterType); + + return TSoundTrackP(dst); + } + + TSoundTrackP compute(const TSoundTrackStereo8Unsigned &src) { + TSoundTrackStereo8Unsigned *dst = + resampleT(const_cast(src), m_sampleRate, + m_filterType); + + return TSoundTrackP(dst); + } + + TSoundTrackP compute(const TSoundTrackMono16 &src) { + TSoundTrackMono16 *dst = resampleT(const_cast(src), + m_sampleRate, m_filterType); + + return TSoundTrackP(dst); + } + + TSoundTrackP compute(const TSoundTrackStereo16 &src) { + TSoundTrackStereo16 *dst = resampleT(const_cast(src), + m_sampleRate, m_filterType); + + return TSoundTrackP(dst); + } + + TSoundTrackP compute(const TSoundTrackMono24 &src) { + TSoundTrackMono24 *dst = resampleT(const_cast(src), + m_sampleRate, m_filterType); + + return TSoundTrackP(dst); + } + + TSoundTrackP compute(const TSoundTrackStereo24 &src) { + TSoundTrackStereo24 *dst = resampleT(const_cast(src), + m_sampleRate, m_filterType); + + return TSoundTrackP(dst); + } }; //============================================================================== -TSoundTrackP TSop::resample(TSoundTrackP src, TINT32 sampleRate) -{ - TSoundTrackResample *resample = new TSoundTrackResample(sampleRate, FLT_HAMMING3); - TSoundTrackP dst = src->apply(resample); - delete resample; - return dst; +TSoundTrackP TSop::resample(TSoundTrackP src, TINT32 sampleRate) { + TSoundTrackResample *resample = + new TSoundTrackResample(sampleRate, FLT_HAMMING3); + TSoundTrackP dst = src->apply(resample); + delete resample; + return dst; } //============================================================================== template -TSoundTrackP doConvertWithoutResamplingT( - SRC *src, const TSoundTrackFormat &dstFormat) -{ - TSoundTrackP dst = TSoundTrack::create(dstFormat, src->getSampleCount()); - if (!dst) - return 0; - - TSoundTrackMono8Unsigned *dstM8U = - dynamic_cast(dst.getPointer()); - if (dstM8U) { - convertSamplesT(*dstM8U, *src); - return dstM8U; - } - - TSoundTrackMono8Signed *dstM8S = - dynamic_cast(dst.getPointer()); - if (dstM8S) { - convertSamplesT(*dstM8S, *src); - return dstM8S; - } - - TSoundTrackStereo8Signed *dstS8S = - dynamic_cast(dst.getPointer()); - if (dstS8S) { - convertSamplesT(*dstS8S, *src); - return dstS8S; - } - - TSoundTrackStereo8Unsigned *dstS8U = - dynamic_cast(dst.getPointer()); - if (dstS8U) { - convertSamplesT(*dstS8U, *src); - return dstS8U; - } - - TSoundTrackMono16 *dstM16 = - dynamic_cast(dst.getPointer()); - if (dstM16) { - convertSamplesT(*dstM16, *src); - return dstM16; - } - - TSoundTrackStereo16 *dstS16 = - dynamic_cast(dst.getPointer()); - if (dstS16) { - convertSamplesT(*dstS16, *src); - return dstS16; - } - - TSoundTrackMono24 *dstM24 = - dynamic_cast(dst.getPointer()); - if (dstM24) { - convertSamplesT(*dstM24, *src); - return dstM24; - } - - TSoundTrackStereo24 *dstS24 = - dynamic_cast(dst.getPointer()); - if (dstS24) { - convertSamplesT(*dstS24, *src); - return dstS24; - } - - return 0; +TSoundTrackP doConvertWithoutResamplingT(SRC *src, + const TSoundTrackFormat &dstFormat) { + TSoundTrackP dst = TSoundTrack::create(dstFormat, src->getSampleCount()); + if (!dst) return 0; + + TSoundTrackMono8Unsigned *dstM8U = + dynamic_cast(dst.getPointer()); + if (dstM8U) { + convertSamplesT(*dstM8U, *src); + return dstM8U; + } + + TSoundTrackMono8Signed *dstM8S = + dynamic_cast(dst.getPointer()); + if (dstM8S) { + convertSamplesT(*dstM8S, *src); + return dstM8S; + } + + TSoundTrackStereo8Signed *dstS8S = + dynamic_cast(dst.getPointer()); + if (dstS8S) { + convertSamplesT(*dstS8S, *src); + return dstS8S; + } + + TSoundTrackStereo8Unsigned *dstS8U = + dynamic_cast(dst.getPointer()); + if (dstS8U) { + convertSamplesT(*dstS8U, *src); + return dstS8U; + } + + TSoundTrackMono16 *dstM16 = + dynamic_cast(dst.getPointer()); + if (dstM16) { + convertSamplesT(*dstM16, *src); + return dstM16; + } + + TSoundTrackStereo16 *dstS16 = + dynamic_cast(dst.getPointer()); + if (dstS16) { + convertSamplesT(*dstS16, *src); + return dstS16; + } + + TSoundTrackMono24 *dstM24 = + dynamic_cast(dst.getPointer()); + if (dstM24) { + convertSamplesT(*dstM24, *src); + return dstM24; + } + + TSoundTrackStereo24 *dstS24 = + dynamic_cast(dst.getPointer()); + if (dstS24) { + convertSamplesT(*dstS24, *src); + return dstS24; + } + + return 0; } //------------------------------------------------------------------------------ -class TSoundTrackConverterWithoutResampling : public TSoundTransform -{ - - TSoundTrackFormat m_format; +class TSoundTrackConverterWithoutResampling : public TSoundTransform { + TSoundTrackFormat m_format; public: - TSoundTrackConverterWithoutResampling(const TSoundTrackFormat &format) - : m_format(format) {} - - ~TSoundTrackConverterWithoutResampling(){}; - - TSoundTrackP compute(const TSoundTrackMono8Signed &src) - { - return doConvertWithoutResamplingT(&src, m_format); - } - - TSoundTrackP compute(const TSoundTrackMono8Unsigned &src) - { - return doConvertWithoutResamplingT(&src, m_format); - } - - TSoundTrackP compute(const TSoundTrackStereo8Signed &src) - { - return doConvertWithoutResamplingT(&src, m_format); - } - - TSoundTrackP compute(const TSoundTrackStereo8Unsigned &src) - { - return doConvertWithoutResamplingT(&src, m_format); - } - - TSoundTrackP compute(const TSoundTrackMono16 &src) - { - return doConvertWithoutResamplingT(&src, m_format); - } - - TSoundTrackP compute(const TSoundTrackStereo16 &src) - { - return doConvertWithoutResamplingT(&src, m_format); - } - TSoundTrackP compute(const TSoundTrackMono24 &src) - { - return doConvertWithoutResamplingT(&src, m_format); - } - - TSoundTrackP compute(const TSoundTrackStereo24 &src) - { - return doConvertWithoutResamplingT(&src, m_format); - } + TSoundTrackConverterWithoutResampling(const TSoundTrackFormat &format) + : m_format(format) {} + + ~TSoundTrackConverterWithoutResampling(){}; + + TSoundTrackP compute(const TSoundTrackMono8Signed &src) { + return doConvertWithoutResamplingT(&src, m_format); + } + + TSoundTrackP compute(const TSoundTrackMono8Unsigned &src) { + return doConvertWithoutResamplingT(&src, m_format); + } + + TSoundTrackP compute(const TSoundTrackStereo8Signed &src) { + return doConvertWithoutResamplingT(&src, m_format); + } + + TSoundTrackP compute(const TSoundTrackStereo8Unsigned &src) { + return doConvertWithoutResamplingT(&src, m_format); + } + + TSoundTrackP compute(const TSoundTrackMono16 &src) { + return doConvertWithoutResamplingT(&src, m_format); + } + + TSoundTrackP compute(const TSoundTrackStereo16 &src) { + return doConvertWithoutResamplingT(&src, m_format); + } + TSoundTrackP compute(const TSoundTrackMono24 &src) { + return doConvertWithoutResamplingT(&src, m_format); + } + + TSoundTrackP compute(const TSoundTrackStereo24 &src) { + return doConvertWithoutResamplingT(&src, m_format); + } }; //----------------------------------------------------------------------------- -namespace -{ - -void convertWithoutResampling(TSoundTrackP &dst, const TSoundTrackP &src) -{ - TSoundTrackConverterWithoutResampling *converter; - converter = new TSoundTrackConverterWithoutResampling(dst->getFormat()); - dst = src->apply(converter); - delete converter; +namespace { + +void convertWithoutResampling(TSoundTrackP &dst, const TSoundTrackP &src) { + TSoundTrackConverterWithoutResampling *converter; + converter = new TSoundTrackConverterWithoutResampling(dst->getFormat()); + dst = src->apply(converter); + delete converter; } -} // namespace +} // namespace //============================================================================== -TSoundTrackP TSop::convert( - const TSoundTrackP &src, - const TSoundTrackFormat &dstFormat) -{ - TINT32 dstSampleCount = - (TINT32)(src->getSampleCount() * (dstFormat.m_sampleRate / (double)src->getSampleRate())); +TSoundTrackP TSop::convert(const TSoundTrackP &src, + const TSoundTrackFormat &dstFormat) { + TINT32 dstSampleCount = + (TINT32)(src->getSampleCount() * + (dstFormat.m_sampleRate / (double)src->getSampleRate())); - TSoundTrackP dst = TSoundTrack::create(dstFormat, dstSampleCount); - TSop::convert(dst, src); - return dst; + TSoundTrackP dst = TSoundTrack::create(dstFormat, dstSampleCount); + TSop::convert(dst, src); + return dst; } //------------------------------------------------------------------------------ -void TSop::convert(TSoundTrackP &dst, const TSoundTrackP &src) -{ - int src_reslen, dst_reslen; - int src_bits, dst_bits; - int src_chans, dst_chans; - TSoundTrackP tmp, tmq; - RESORDER_TYPE order; - - assert(src->getSampleCount() >= 0 && dst->getSampleCount() >= 0); - if (!dst->getSampleCount()) - return; - - if (!src->getSampleCount()) { - dst->blank(0L, (TINT32)(dst->getSampleCount() - 1)); - return; - } - - if (src->getSampleRate() == dst->getSampleRate()) { - src_reslen = dst->getSampleCount(); - notMoreThan((int)src->getSampleCount(), src_reslen); - dst_reslen = src_reslen; - convertWithoutResampling(dst, src); - } else { - src_reslen = FULL_INT_MUL_DIV( - dst->getSampleCount(), - src->getSampleRate(), - dst->getSampleRate()); - - if (src_reslen > src->getSampleCount()) { - src_reslen = src->getSampleCount(); - dst_reslen = FULL_INT_MUL_DIV( - src_reslen, dst->getSampleRate(), src->getSampleRate()); - } else - dst_reslen = dst->getSampleCount(); - - src_chans = src->getChannelCount(); - dst_chans = dst->getChannelCount(); - src_bits = src->getBitPerSample(); - dst_bits = dst->getBitPerSample(); - - if (src_chans == dst_chans && src_bits == dst_bits) - if (src->isSampleSigned() == dst->isSampleSigned()) - order = RESORDER_RATE; - else - order = RESORDER_SIGN; - else if (src_chans < dst_chans) { - if (src_bits < dst_bits) - order = RESORDER_BITS_RATE_CHANS; - else - order = RESORDER_RATE_BITS_CHANS; - } else if (src_chans > dst_chans) { - if (src_bits > dst_bits) - order = RESORDER_CHANS_RATE_BITS; - else - order = RESORDER_CHANS_BITS_RATE; - } else { - if (src_bits > dst_bits) - order = RESORDER_RATE_BITS; - else - order = RESORDER_BITS_RATE; - } - - switch (order) { - case RESORDER_CHANS_RATE_BITS: - case RESORDER_BITS_RATE_CHANS: - int chans, bitPerSample; - if (src->getChannelCount() <= dst->getChannelCount()) - chans = src->getChannelCount(); - else - chans = dst->getChannelCount(); - - if (src->getBitPerSample() >= dst->getBitPerSample()) - bitPerSample = src->getBitPerSample(); - else - bitPerSample = dst->getBitPerSample(); - - tmp = TSoundTrack::create( - (int)src->getSampleRate(), - bitPerSample, - chans, - src_reslen * src->getSampleSize()); - - convertWithoutResampling(tmp, src); - tmq = TSop::resample(tmp, (TINT32)dst->getSampleRate()); - convertWithoutResampling(dst, tmq); - break; - - case RESORDER_RATE_BITS_CHANS: - case RESORDER_RATE_BITS: - case RESORDER_RATE_CHANS: - tmp = TSop::resample(src, (TINT32)dst->getSampleRate()); - convertWithoutResampling(dst, tmp); - break; - - case RESORDER_CHANS_BITS_RATE: - case RESORDER_BITS_RATE: - case RESORDER_CHANS_RATE: - case RESORDER_SIGN: - tmp = TSoundTrack::create( - (int)src->getSampleRate(), - dst->getBitPerSample(), - dst->getChannelCount(), - src_reslen * dst->getSampleSize(), - dst->isSampleSigned()); - - convertWithoutResampling(tmp, src); - dst = TSop::resample(tmp, (TINT32)dst->getSampleRate()); - break; - - case RESORDER_RATE: - dst = TSop::resample(src, (TINT32)dst->getSampleRate()); - break; - - default: - assert(false); - break; - } - } - - if (dst_reslen < dst->getSampleCount()) - dst->blank((TINT32)dst_reslen, (TINT32)(dst->getSampleCount() - 1)); +void TSop::convert(TSoundTrackP &dst, const TSoundTrackP &src) { + int src_reslen, dst_reslen; + int src_bits, dst_bits; + int src_chans, dst_chans; + TSoundTrackP tmp, tmq; + RESORDER_TYPE order; + + assert(src->getSampleCount() >= 0 && dst->getSampleCount() >= 0); + if (!dst->getSampleCount()) return; + + if (!src->getSampleCount()) { + dst->blank(0L, (TINT32)(dst->getSampleCount() - 1)); + return; + } + + if (src->getSampleRate() == dst->getSampleRate()) { + src_reslen = dst->getSampleCount(); + notMoreThan((int)src->getSampleCount(), src_reslen); + dst_reslen = src_reslen; + convertWithoutResampling(dst, src); + } else { + src_reslen = FULL_INT_MUL_DIV(dst->getSampleCount(), src->getSampleRate(), + dst->getSampleRate()); + + if (src_reslen > src->getSampleCount()) { + src_reslen = src->getSampleCount(); + dst_reslen = FULL_INT_MUL_DIV(src_reslen, dst->getSampleRate(), + src->getSampleRate()); + } else + dst_reslen = dst->getSampleCount(); + + src_chans = src->getChannelCount(); + dst_chans = dst->getChannelCount(); + src_bits = src->getBitPerSample(); + dst_bits = dst->getBitPerSample(); + + if (src_chans == dst_chans && src_bits == dst_bits) + if (src->isSampleSigned() == dst->isSampleSigned()) + order = RESORDER_RATE; + else + order = RESORDER_SIGN; + else if (src_chans < dst_chans) { + if (src_bits < dst_bits) + order = RESORDER_BITS_RATE_CHANS; + else + order = RESORDER_RATE_BITS_CHANS; + } else if (src_chans > dst_chans) { + if (src_bits > dst_bits) + order = RESORDER_CHANS_RATE_BITS; + else + order = RESORDER_CHANS_BITS_RATE; + } else { + if (src_bits > dst_bits) + order = RESORDER_RATE_BITS; + else + order = RESORDER_BITS_RATE; + } + + switch (order) { + case RESORDER_CHANS_RATE_BITS: + case RESORDER_BITS_RATE_CHANS: + int chans, bitPerSample; + if (src->getChannelCount() <= dst->getChannelCount()) + chans = src->getChannelCount(); + else + chans = dst->getChannelCount(); + + if (src->getBitPerSample() >= dst->getBitPerSample()) + bitPerSample = src->getBitPerSample(); + else + bitPerSample = dst->getBitPerSample(); + + tmp = TSoundTrack::create((int)src->getSampleRate(), bitPerSample, chans, + src_reslen * src->getSampleSize()); + + convertWithoutResampling(tmp, src); + tmq = TSop::resample(tmp, (TINT32)dst->getSampleRate()); + convertWithoutResampling(dst, tmq); + break; + + case RESORDER_RATE_BITS_CHANS: + case RESORDER_RATE_BITS: + case RESORDER_RATE_CHANS: + tmp = TSop::resample(src, (TINT32)dst->getSampleRate()); + convertWithoutResampling(dst, tmp); + break; + + case RESORDER_CHANS_BITS_RATE: + case RESORDER_BITS_RATE: + case RESORDER_CHANS_RATE: + case RESORDER_SIGN: + tmp = TSoundTrack::create((int)src->getSampleRate(), + dst->getBitPerSample(), dst->getChannelCount(), + src_reslen * dst->getSampleSize(), + dst->isSampleSigned()); + + convertWithoutResampling(tmp, src); + dst = TSop::resample(tmp, (TINT32)dst->getSampleRate()); + break; + + case RESORDER_RATE: + dst = TSop::resample(src, (TINT32)dst->getSampleRate()); + break; + + default: + assert(false); + break; + } + } + + if (dst_reslen < dst->getSampleCount()) + dst->blank((TINT32)dst_reslen, (TINT32)(dst->getSampleCount() - 1)); } //============================================================================== template -TSoundTrackP doReverb( - TSoundTrackT *src, - double delayTime, - double decayFactor, - double extendTime) -{ - TINT32 dstSampleCount = src->getSampleCount() + (TINT32)(src->getSampleRate() * extendTime); - - TSoundTrackT *dst = new TSoundTrackT( - src->getSampleRate(), - src->getChannelCount(), - dstSampleCount); - - TINT32 sampleRate = (TINT32)src->getSampleRate(); - TINT32 k = (TINT32)(sampleRate * delayTime); - - T *srcSample = src->samples(); - T *dstSample = dst->samples(); - T *endDstSample = dst->samples() + k; - - while (dstSample < endDstSample) - *dstSample++ = *srcSample++; - - // la formula del reverb e' - // out(i) = in(i) + decayFactor * out(i - k) - - // int channelCount = src->getChannelCount(); - - endDstSample = dst->samples() + std::min(dstSampleCount, (TINT32)src->getSampleCount()); - while (dstSample < endDstSample) { - //*dstSample = *srcSample + *(dstSample - k)*decayFactor; - *dstSample = T::mix(*srcSample, 1, *(dstSample - k), decayFactor); - ++dstSample; - ++srcSample; - } - - endDstSample = dst->samples() + dstSampleCount; - while (dstSample < endDstSample) { - //*dstSample = *(dstSample - k)*decayFactor; - *dstSample = T::mix(T(), 0, *(dstSample - k), decayFactor); - ++dstSample; - } - - return TSoundTrackP(dst); +TSoundTrackP doReverb(TSoundTrackT *src, double delayTime, + double decayFactor, double extendTime) { + TINT32 dstSampleCount = + src->getSampleCount() + (TINT32)(src->getSampleRate() * extendTime); + + TSoundTrackT *dst = new TSoundTrackT( + src->getSampleRate(), src->getChannelCount(), dstSampleCount); + + TINT32 sampleRate = (TINT32)src->getSampleRate(); + TINT32 k = (TINT32)(sampleRate * delayTime); + + T *srcSample = src->samples(); + T *dstSample = dst->samples(); + T *endDstSample = dst->samples() + k; + + while (dstSample < endDstSample) *dstSample++ = *srcSample++; + + // la formula del reverb e' + // out(i) = in(i) + decayFactor * out(i - k) + + // int channelCount = src->getChannelCount(); + + endDstSample = + dst->samples() + std::min(dstSampleCount, (TINT32)src->getSampleCount()); + while (dstSample < endDstSample) { + //*dstSample = *srcSample + *(dstSample - k)*decayFactor; + *dstSample = T::mix(*srcSample, 1, *(dstSample - k), decayFactor); + ++dstSample; + ++srcSample; + } + + endDstSample = dst->samples() + dstSampleCount; + while (dstSample < endDstSample) { + //*dstSample = *(dstSample - k)*decayFactor; + *dstSample = T::mix(T(), 0, *(dstSample - k), decayFactor); + ++dstSample; + } + + return TSoundTrackP(dst); } //============================================================================== -class TSoundReverb : public TSoundTransform -{ - double m_delayTime; - double m_decayFactor; - double m_extendTime; +class TSoundReverb : public TSoundTransform { + double m_delayTime; + double m_decayFactor; + double m_extendTime; public: - TSoundReverb( - double delayTime, - double decayFactor, - double extendTime) - : m_delayTime(delayTime), m_decayFactor(decayFactor), m_extendTime(extendTime) - { - } - - ~TSoundReverb() {} - - virtual TSoundTrackP compute(const TSoundTrackMono8Signed &src) - { - return doReverb( - const_cast(&src), - m_delayTime, - m_decayFactor, - m_extendTime); - } - - virtual TSoundTrackP compute(const TSoundTrackMono8Unsigned &src) - { - return doReverb( - const_cast(&src), - m_delayTime, - m_decayFactor, - m_extendTime); - } - - virtual TSoundTrackP compute(const TSoundTrackStereo8Signed &src) - { - return doReverb( - const_cast(&src), - m_delayTime, - m_decayFactor, - m_extendTime); - } - - virtual TSoundTrackP compute(const TSoundTrackStereo8Unsigned &src) - { - return doReverb( - const_cast(&src), - m_delayTime, - m_decayFactor, - m_extendTime); - } - - virtual TSoundTrackP compute(const TSoundTrackMono16 &src) - { - return doReverb( - const_cast(&src), - m_delayTime, - m_decayFactor, - m_extendTime); - } - - virtual TSoundTrackP compute(const TSoundTrackStereo16 &src) - { - return doReverb( - const_cast(&src), - m_delayTime, - m_decayFactor, - m_extendTime); - } - - virtual TSoundTrackP compute(const TSoundTrackMono24 &src) - { - return doReverb( - const_cast(&src), - m_delayTime, - m_decayFactor, - m_extendTime); - } - - virtual TSoundTrackP compute(const TSoundTrackStereo24 &src) - { - return doReverb( - const_cast(&src), - m_delayTime, - m_decayFactor, - m_extendTime); - } + TSoundReverb(double delayTime, double decayFactor, double extendTime) + : m_delayTime(delayTime) + , m_decayFactor(decayFactor) + , m_extendTime(extendTime) {} + + ~TSoundReverb() {} + + virtual TSoundTrackP compute(const TSoundTrackMono8Signed &src) { + return doReverb(const_cast(&src), m_delayTime, + m_decayFactor, m_extendTime); + } + + virtual TSoundTrackP compute(const TSoundTrackMono8Unsigned &src) { + return doReverb(const_cast(&src), m_delayTime, + m_decayFactor, m_extendTime); + } + + virtual TSoundTrackP compute(const TSoundTrackStereo8Signed &src) { + return doReverb(const_cast(&src), m_delayTime, + m_decayFactor, m_extendTime); + } + + virtual TSoundTrackP compute(const TSoundTrackStereo8Unsigned &src) { + return doReverb(const_cast(&src), m_delayTime, + m_decayFactor, m_extendTime); + } + + virtual TSoundTrackP compute(const TSoundTrackMono16 &src) { + return doReverb(const_cast(&src), m_delayTime, + m_decayFactor, m_extendTime); + } + + virtual TSoundTrackP compute(const TSoundTrackStereo16 &src) { + return doReverb(const_cast(&src), m_delayTime, + m_decayFactor, m_extendTime); + } + + virtual TSoundTrackP compute(const TSoundTrackMono24 &src) { + return doReverb(const_cast(&src), m_delayTime, + m_decayFactor, m_extendTime); + } + + virtual TSoundTrackP compute(const TSoundTrackStereo24 &src) { + return doReverb(const_cast(&src), m_delayTime, + m_decayFactor, m_extendTime); + } }; //============================================================================== -TSoundTrackP TSop::reverb( - TSoundTrackP src, - double delayTime, - double decayFactor, - double extendTime) -{ - TSoundReverb *reverb = new TSoundReverb(delayTime, decayFactor, extendTime); - assert(reverb); - if (!reverb) - return TSoundTrackP(); - TSoundTrackP dst = src->apply(reverb); - delete reverb; - return dst; +TSoundTrackP TSop::reverb(TSoundTrackP src, double delayTime, + double decayFactor, double extendTime) { + TSoundReverb *reverb = new TSoundReverb(delayTime, decayFactor, extendTime); + assert(reverb); + if (!reverb) return TSoundTrackP(); + TSoundTrackP dst = src->apply(reverb); + delete reverb; + return dst; } //============================================================================== template -TSoundTrackP doGate( - TSoundTrackT *src, - double threshold, - double holdTime, - double /*releaseTime*/) -{ - - TSoundTrackT *dst = new TSoundTrackT( - src->getSampleRate(), - src->getChannelCount(), - src->getSampleCount()); - - double sampleExcursion_inv = - 1.0 / (double)(src->getMaxPressure(0, src->getSampleCount() - 1, 0) - src->getMinPressure(0, src->getSampleCount() - 1, 0)); - - TINT32 holdTimeSamples = src->secondsToSamples(holdTime); - TINT32 time = 0; - - const T *srcSample = src->samples(); - const T *srcEndSample = srcSample + src->getSampleCount(); - T *dstSample = dst->samples(); - - while (srcSample < srcEndSample) { - if (fabs(srcSample->getValue(0) * sampleExcursion_inv) < threshold) { - if (time >= holdTimeSamples) - *dstSample = T(); - else - *dstSample = *srcSample; - - ++time; - } else { - time = 0; - *dstSample = *srcSample; - } - - ++srcSample; - ++dstSample; - } - - return dst; +TSoundTrackP doGate(TSoundTrackT *src, double threshold, double holdTime, + double /*releaseTime*/) { + TSoundTrackT *dst = new TSoundTrackT( + src->getSampleRate(), src->getChannelCount(), src->getSampleCount()); + + double sampleExcursion_inv = + 1.0 / (double)(src->getMaxPressure(0, src->getSampleCount() - 1, 0) - + src->getMinPressure(0, src->getSampleCount() - 1, 0)); + + TINT32 holdTimeSamples = src->secondsToSamples(holdTime); + TINT32 time = 0; + + const T *srcSample = src->samples(); + const T *srcEndSample = srcSample + src->getSampleCount(); + T *dstSample = dst->samples(); + + while (srcSample < srcEndSample) { + if (fabs(srcSample->getValue(0) * sampleExcursion_inv) < threshold) { + if (time >= holdTimeSamples) + *dstSample = T(); + else + *dstSample = *srcSample; + + ++time; + } else { + time = 0; + *dstSample = *srcSample; + } + + ++srcSample; + ++dstSample; + } + + return dst; } //============================================================================== -class TSoundGate : public TSoundTransform -{ - double m_threshold; - double m_holdTime; - double m_releaseTime; +class TSoundGate : public TSoundTransform { + double m_threshold; + double m_holdTime; + double m_releaseTime; public: - TSoundGate( - double threshold, - double holdTime, - double releaseTime) - : m_threshold(threshold), m_holdTime(holdTime), m_releaseTime(releaseTime) - { - } - - ~TSoundGate() {} - - TSoundTrackP compute(const TSoundTrackMono8Signed &src) - { - return doGate( - const_cast(&src), - m_threshold, - m_holdTime, - m_releaseTime); - } - - TSoundTrackP compute(const TSoundTrackMono8Unsigned &src) - { - return doGate( - const_cast(&src), - m_threshold, - m_holdTime, - m_releaseTime); - } - - TSoundTrackP compute(const TSoundTrackStereo8Signed &src) - { - return doGate( - const_cast(&src), - m_threshold, - m_holdTime, - m_releaseTime); - } - - TSoundTrackP compute(const TSoundTrackStereo8Unsigned &src) - { - return doGate( - const_cast(&src), - m_threshold, - m_holdTime, - m_releaseTime); - } - - TSoundTrackP compute(const TSoundTrackMono16 &src) - { - return doGate( - const_cast(&src), - m_threshold, - m_holdTime, - m_releaseTime); - } - - TSoundTrackP compute(const TSoundTrackStereo16 &src) - { - return doGate( - const_cast(&src), - m_threshold, - m_holdTime, - m_releaseTime); - } - - TSoundTrackP compute(const TSoundTrackMono24 &src) - { - return doGate( - const_cast(&src), - m_threshold, - m_holdTime, - m_releaseTime); - } - - TSoundTrackP compute(const TSoundTrackStereo24 &src) - { - return doGate( - const_cast(&src), - m_threshold, - m_holdTime, - m_releaseTime); - } + TSoundGate(double threshold, double holdTime, double releaseTime) + : m_threshold(threshold) + , m_holdTime(holdTime) + , m_releaseTime(releaseTime) {} + + ~TSoundGate() {} + + TSoundTrackP compute(const TSoundTrackMono8Signed &src) { + return doGate(const_cast(&src), m_threshold, + m_holdTime, m_releaseTime); + } + + TSoundTrackP compute(const TSoundTrackMono8Unsigned &src) { + return doGate(const_cast(&src), m_threshold, + m_holdTime, m_releaseTime); + } + + TSoundTrackP compute(const TSoundTrackStereo8Signed &src) { + return doGate(const_cast(&src), m_threshold, + m_holdTime, m_releaseTime); + } + + TSoundTrackP compute(const TSoundTrackStereo8Unsigned &src) { + return doGate(const_cast(&src), m_threshold, + m_holdTime, m_releaseTime); + } + + TSoundTrackP compute(const TSoundTrackMono16 &src) { + return doGate(const_cast(&src), m_threshold, + m_holdTime, m_releaseTime); + } + + TSoundTrackP compute(const TSoundTrackStereo16 &src) { + return doGate(const_cast(&src), m_threshold, + m_holdTime, m_releaseTime); + } + + TSoundTrackP compute(const TSoundTrackMono24 &src) { + return doGate(const_cast(&src), m_threshold, + m_holdTime, m_releaseTime); + } + + TSoundTrackP compute(const TSoundTrackStereo24 &src) { + return doGate(const_cast(&src), m_threshold, + m_holdTime, m_releaseTime); + } }; //============================================================================== -TSoundTrackP TSop::gate( - TSoundTrackP src, - double threshold, - double holdTime, - double releaseTime) -{ - TSoundGate *gate = new TSoundGate(threshold, holdTime, releaseTime); - assert(gate); - if (!gate) - return TSoundTrackP(); - TSoundTrackP dst = src->apply(gate); - delete gate; - return dst; +TSoundTrackP TSop::gate(TSoundTrackP src, double threshold, double holdTime, + double releaseTime) { + TSoundGate *gate = new TSoundGate(threshold, holdTime, releaseTime); + assert(gate); + if (!gate) return TSoundTrackP(); + TSoundTrackP dst = src->apply(gate); + delete gate; + return dst; } //============================================================================== -TSoundTrackP TSop::timeStrech(TSoundTrackP src, double ratio) -{ - TINT32 sampleRate = (TINT32)(src->getSampleRate() * ratio); +TSoundTrackP TSop::timeStrech(TSoundTrackP src, double ratio) { + TINT32 sampleRate = (TINT32)(src->getSampleRate() * ratio); - if (sampleRate > 100000) - sampleRate = 100000; + if (sampleRate > 100000) sampleRate = 100000; - TSoundTrackP st; + TSoundTrackP st; - if (sampleRate > 0) { - TSoundTrackResample *resample = new TSoundTrackResample(sampleRate, FLT_TRIANGLE); - st = src->apply(resample); - delete resample; - st->setSampleRate(src->getSampleRate()); - } + if (sampleRate > 0) { + TSoundTrackResample *resample = + new TSoundTrackResample(sampleRate, FLT_TRIANGLE); + st = src->apply(resample); + delete resample; + st->setSampleRate(src->getSampleRate()); + } - return st; + return st; } //======================================================================================== template -TSoundTrackP doEcho( - TSoundTrackT *src, - double delayTime, - double decayFactor, - double extendTime) -{ - typedef typename T::ChannelValueType ChannelValueType; - - TINT32 dstSampleCount = src->getSampleCount() + (TINT32)(src->getSampleRate() * extendTime); - - TSoundTrackT *dst = new TSoundTrackT( - src->getSampleRate(), - src->getChannelCount(), - dstSampleCount); - - TINT32 sampleRate = (TINT32)src->getSampleRate(); - TINT32 k = (TINT32)(sampleRate * delayTime); - - T *srcSample = src->samples(); - T *dstSample = dst->samples(); - T *endDstSample = dst->samples() + k; - - while (dstSample < endDstSample) - *dstSample++ = *srcSample++; - - // la formula dell'echo e' - // out(i) = in(i) + decayFactor * in(i - k) - - bool chans = src->getChannelCount() == 2; - endDstSample = dst->samples() + std::min(dstSampleCount, (TINT32)src->getSampleCount()); - while (dstSample < endDstSample) { - //*dstSample = *srcSample + *(srcSample - k)*decayFactor; - ChannelValueType val = - (ChannelValueType)((srcSample - k)->getValue(TSound::MONO) * decayFactor); - dstSample->setValue(TSound::MONO, srcSample->getValue(TSound::MONO) + val); - if (chans) { - ChannelValueType val = - (ChannelValueType)((srcSample - k)->getValue(TSound::RIGHT) * decayFactor); - dstSample->setValue(TSound::RIGHT, srcSample->getValue(TSound::RIGHT) + val); - } - ++dstSample; - ++srcSample; - } - - endDstSample = dstSample + k; - while (dstSample < endDstSample) { - //*dstSample = *(srcSample - k)*decayFactor; - ChannelValueType val = - (ChannelValueType)((srcSample - k)->getValue(TSound::MONO) * decayFactor); - dstSample->setValue(TSound::MONO, val); - if (chans) { - ChannelValueType val = - (ChannelValueType)((srcSample - k)->getValue(TSound::RIGHT) * decayFactor); - dstSample->setValue(TSound::RIGHT, val); - } - ++dstSample; - ++srcSample; - } - - srcSample = src->samples() + src->getSampleCount() - 1; - endDstSample = dst->samples() + dstSampleCount; - while (dstSample < endDstSample) { - //*dstSample = *(srcSample)*decayFactor; - ChannelValueType val = - (ChannelValueType)(srcSample->getValue(TSound::MONO) * decayFactor); - dstSample->setValue(TSound::MONO, val); - if (chans) { - ChannelValueType val = - (ChannelValueType)(srcSample->getValue(TSound::RIGHT) * decayFactor); - dstSample->setValue(TSound::RIGHT, val); - } - ++dstSample; - } - - return TSoundTrackP(dst); +TSoundTrackP doEcho(TSoundTrackT *src, double delayTime, double decayFactor, + double extendTime) { + typedef typename T::ChannelValueType ChannelValueType; + + TINT32 dstSampleCount = + src->getSampleCount() + (TINT32)(src->getSampleRate() * extendTime); + + TSoundTrackT *dst = new TSoundTrackT( + src->getSampleRate(), src->getChannelCount(), dstSampleCount); + + TINT32 sampleRate = (TINT32)src->getSampleRate(); + TINT32 k = (TINT32)(sampleRate * delayTime); + + T *srcSample = src->samples(); + T *dstSample = dst->samples(); + T *endDstSample = dst->samples() + k; + + while (dstSample < endDstSample) *dstSample++ = *srcSample++; + + // la formula dell'echo e' + // out(i) = in(i) + decayFactor * in(i - k) + + bool chans = src->getChannelCount() == 2; + endDstSample = + dst->samples() + std::min(dstSampleCount, (TINT32)src->getSampleCount()); + while (dstSample < endDstSample) { + //*dstSample = *srcSample + *(srcSample - k)*decayFactor; + ChannelValueType val = (ChannelValueType)( + (srcSample - k)->getValue(TSound::MONO) * decayFactor); + dstSample->setValue(TSound::MONO, srcSample->getValue(TSound::MONO) + val); + if (chans) { + ChannelValueType val = (ChannelValueType)( + (srcSample - k)->getValue(TSound::RIGHT) * decayFactor); + dstSample->setValue(TSound::RIGHT, + srcSample->getValue(TSound::RIGHT) + val); + } + ++dstSample; + ++srcSample; + } + + endDstSample = dstSample + k; + while (dstSample < endDstSample) { + //*dstSample = *(srcSample - k)*decayFactor; + ChannelValueType val = (ChannelValueType)( + (srcSample - k)->getValue(TSound::MONO) * decayFactor); + dstSample->setValue(TSound::MONO, val); + if (chans) { + ChannelValueType val = (ChannelValueType)( + (srcSample - k)->getValue(TSound::RIGHT) * decayFactor); + dstSample->setValue(TSound::RIGHT, val); + } + ++dstSample; + ++srcSample; + } + + srcSample = src->samples() + src->getSampleCount() - 1; + endDstSample = dst->samples() + dstSampleCount; + while (dstSample < endDstSample) { + //*dstSample = *(srcSample)*decayFactor; + ChannelValueType val = + (ChannelValueType)(srcSample->getValue(TSound::MONO) * decayFactor); + dstSample->setValue(TSound::MONO, val); + if (chans) { + ChannelValueType val = + (ChannelValueType)(srcSample->getValue(TSound::RIGHT) * decayFactor); + dstSample->setValue(TSound::RIGHT, val); + } + ++dstSample; + } + + return TSoundTrackP(dst); } //------------------------------------------------------------------------------ -void TSop::echo( - TSoundTrackP &dst, - const TSoundTrackP &src, - double delayTime, - double decayFactor, - double extendTime) -{ - TSoundTrackMono8Signed *srcM8S; - srcM8S = dynamic_cast(src.getPointer()); - if (srcM8S) - dst = doEcho(srcM8S, delayTime, decayFactor, extendTime); - else { - TSoundTrackMono8Unsigned *srcM8U; - srcM8U = dynamic_cast(src.getPointer()); - if (srcM8U) - dst = doEcho(srcM8U, delayTime, decayFactor, extendTime); - else { - TSoundTrackStereo8Signed *srcS8S; - srcS8S = dynamic_cast(src.getPointer()); - if (srcS8S) - dst = doEcho(srcS8S, delayTime, decayFactor, extendTime); - else { - TSoundTrackStereo8Unsigned *srcS8U; - srcS8U = dynamic_cast(src.getPointer()); - if (srcS8U) - dst = doEcho(srcS8U, delayTime, decayFactor, extendTime); - else { - TSoundTrackMono16 *srcM16; - srcM16 = dynamic_cast(src.getPointer()); - if (srcM16) - dst = doEcho(srcM16, delayTime, decayFactor, extendTime); - else { - TSoundTrackStereo16 *srcS16; - srcS16 = dynamic_cast(src.getPointer()); - if (srcS16) - dst = doEcho(srcS16, delayTime, decayFactor, extendTime); - else { - TSoundTrackMono24 *srcM24; - srcM24 = dynamic_cast(src.getPointer()); - if (srcM24) - dst = doEcho(srcM24, delayTime, decayFactor, extendTime); - else { - TSoundTrackStereo24 *srcS24; - srcS24 = dynamic_cast(src.getPointer()); - if (srcS24) - dst = doEcho(srcS24, delayTime, decayFactor, extendTime); - } - } - } - } - } - } - } +void TSop::echo(TSoundTrackP &dst, const TSoundTrackP &src, double delayTime, + double decayFactor, double extendTime) { + TSoundTrackMono8Signed *srcM8S; + srcM8S = dynamic_cast(src.getPointer()); + if (srcM8S) + dst = doEcho(srcM8S, delayTime, decayFactor, extendTime); + else { + TSoundTrackMono8Unsigned *srcM8U; + srcM8U = dynamic_cast(src.getPointer()); + if (srcM8U) + dst = doEcho(srcM8U, delayTime, decayFactor, extendTime); + else { + TSoundTrackStereo8Signed *srcS8S; + srcS8S = dynamic_cast(src.getPointer()); + if (srcS8S) + dst = doEcho(srcS8S, delayTime, decayFactor, extendTime); + else { + TSoundTrackStereo8Unsigned *srcS8U; + srcS8U = dynamic_cast(src.getPointer()); + if (srcS8U) + dst = doEcho(srcS8U, delayTime, decayFactor, extendTime); + else { + TSoundTrackMono16 *srcM16; + srcM16 = dynamic_cast(src.getPointer()); + if (srcM16) + dst = doEcho(srcM16, delayTime, decayFactor, extendTime); + else { + TSoundTrackStereo16 *srcS16; + srcS16 = dynamic_cast(src.getPointer()); + if (srcS16) + dst = doEcho(srcS16, delayTime, decayFactor, extendTime); + else { + TSoundTrackMono24 *srcM24; + srcM24 = dynamic_cast(src.getPointer()); + if (srcM24) + dst = doEcho(srcM24, delayTime, decayFactor, extendTime); + else { + TSoundTrackStereo24 *srcS24; + srcS24 = dynamic_cast(src.getPointer()); + if (srcS24) + dst = doEcho(srcS24, delayTime, decayFactor, extendTime); + } + } + } + } + } + } + } } //------------------------------------------------------------------------------ -TSoundTrackP TSop::insertBlank(TSoundTrackP src, TINT32 s0, TINT32 len) -{ - assert(len >= 0); - if (len == 0) - return src; - - TINT32 ss0 = tcrop(s0, 0, src->getSampleCount()); - - TSoundTrackFormat format = src->getFormat(); - TSoundTrackP dst = TSoundTrack::create( - format, (src->getSampleCount() + len)); - - UCHAR *dstRawData = (UCHAR *)dst->getRawData(); - UCHAR *srcRawData = (UCHAR *)src->getRawData(); - - int bytePerSample = dst->getSampleSize(); - memcpy(dstRawData, srcRawData, ss0 * bytePerSample); - if (format.m_signedSample) - memset(dstRawData + ss0 * bytePerSample, 0, len * bytePerSample); - else - memset(dstRawData + ss0 * bytePerSample, 127, len * bytePerSample); - memcpy( - dstRawData + (ss0 + len) * bytePerSample, - srcRawData + ss0 * bytePerSample, - (src->getSampleCount() - ss0) * bytePerSample); - - return dst; +TSoundTrackP TSop::insertBlank(TSoundTrackP src, TINT32 s0, TINT32 len) { + assert(len >= 0); + if (len == 0) return src; + + TINT32 ss0 = tcrop(s0, 0, src->getSampleCount()); + + TSoundTrackFormat format = src->getFormat(); + TSoundTrackP dst = TSoundTrack::create(format, (src->getSampleCount() + len)); + + UCHAR *dstRawData = (UCHAR *)dst->getRawData(); + UCHAR *srcRawData = (UCHAR *)src->getRawData(); + + int bytePerSample = dst->getSampleSize(); + memcpy(dstRawData, srcRawData, ss0 * bytePerSample); + if (format.m_signedSample) + memset(dstRawData + ss0 * bytePerSample, 0, len * bytePerSample); + else + memset(dstRawData + ss0 * bytePerSample, 127, len * bytePerSample); + memcpy(dstRawData + (ss0 + len) * bytePerSample, + srcRawData + ss0 * bytePerSample, + (src->getSampleCount() - ss0) * bytePerSample); + + return dst; } //------------------------------------------------------------------------------ -TSoundTrackP TSop::insertBlank(TSoundTrackP src, double t0, double len) -{ - return insertBlank(src, src->secondsToSamples(t0), src->secondsToSamples(len)); +TSoundTrackP TSop::insertBlank(TSoundTrackP src, double t0, double len) { + return insertBlank(src, src->secondsToSamples(t0), + src->secondsToSamples(len)); } //------------------------------------------------------------------------------ -TSoundTrackP TSop::remove(TSoundTrackP src, TINT32 s0, TINT32 s1, TSoundTrackP &paste) -{ - TINT32 ss0, ss1; - - ss0 = std::max((TINT32)0, s0); - ss1 = std::min(s1, (TINT32)(src->getSampleCount() - 1)); - TSoundTrackP soundTrackSlice; - if (ss0 <= ss1) - soundTrackSlice = src->extract(ss0, ss1); - if (!soundTrackSlice) { - paste = TSoundTrackP(); - return src; - } - paste = soundTrackSlice->clone(); - - TSoundTrackFormat format = src->getFormat(); - TSoundTrackP dst = TSoundTrack::create(format, (src->getSampleCount() - (ss1 - ss0 + 1))); - - TINT32 dstSampleSize = dst->getSampleSize(); - UCHAR *newRowData = (UCHAR *)dst->getRawData(); - UCHAR *srcRowData = (UCHAR *)src->getRawData(); - - memcpy(newRowData, srcRowData, ss0 * dstSampleSize); - memcpy( - newRowData + (ss0 * dstSampleSize), - srcRowData + (ss1 + 1) * dstSampleSize, - (src->getSampleCount() - ss1 - 1) * dst->getSampleSize()); - - return dst; +TSoundTrackP TSop::remove(TSoundTrackP src, TINT32 s0, TINT32 s1, + TSoundTrackP &paste) { + TINT32 ss0, ss1; + + ss0 = std::max((TINT32)0, s0); + ss1 = std::min(s1, (TINT32)(src->getSampleCount() - 1)); + TSoundTrackP soundTrackSlice; + if (ss0 <= ss1) soundTrackSlice = src->extract(ss0, ss1); + if (!soundTrackSlice) { + paste = TSoundTrackP(); + return src; + } + paste = soundTrackSlice->clone(); + + TSoundTrackFormat format = src->getFormat(); + TSoundTrackP dst = + TSoundTrack::create(format, (src->getSampleCount() - (ss1 - ss0 + 1))); + + TINT32 dstSampleSize = dst->getSampleSize(); + UCHAR *newRowData = (UCHAR *)dst->getRawData(); + UCHAR *srcRowData = (UCHAR *)src->getRawData(); + + memcpy(newRowData, srcRowData, ss0 * dstSampleSize); + memcpy(newRowData + (ss0 * dstSampleSize), + srcRowData + (ss1 + 1) * dstSampleSize, + (src->getSampleCount() - ss1 - 1) * dst->getSampleSize()); + + return dst; } //------------------------------------------------------------------------------ -TSoundTrackP TSop::remove(TSoundTrackP src, double t0, double t1, TSoundTrackP &paste) -{ - return remove(src, src->secondsToSamples(t0), src->secondsToSamples(t1), paste); +TSoundTrackP TSop::remove(TSoundTrackP src, double t0, double t1, + TSoundTrackP &paste) { + return remove(src, src->secondsToSamples(t0), src->secondsToSamples(t1), + paste); } //------------------------------------------------------------------------------ template -TSoundTrackP mixT( - TSoundTrackT *st1, double a1, TSoundTrackT *st2, double a2) -{ - TINT32 sampleCount = std::max(st1->getSampleCount(), st2->getSampleCount()); - - TSoundTrackT *dst = new TSoundTrackT( - st1->getSampleRate(), - st1->getChannelCount(), - sampleCount); - - T *dstSample = dst->samples(); - T *endDstSample = dstSample + std::min(st1->getSampleCount(), st2->getSampleCount()); - - T *st1Sample = st1->samples(); - T *st2Sample = st2->samples(); - - while (dstSample < endDstSample) { - *dstSample++ = T::mix(*st1Sample, a1, *st2Sample, a2); - ++st1Sample; - ++st2Sample; - } - - T *srcSample = st1->getSampleCount() > st2->getSampleCount() ? st1Sample : st2Sample; - endDstSample = dst->samples() + sampleCount; - while (dstSample < endDstSample) - *dstSample++ = *srcSample++; - - return TSoundTrackP(dst); +TSoundTrackP mixT(TSoundTrackT *st1, double a1, TSoundTrackT *st2, + double a2) { + TINT32 sampleCount = std::max(st1->getSampleCount(), st2->getSampleCount()); + + TSoundTrackT *dst = new TSoundTrackT( + st1->getSampleRate(), st1->getChannelCount(), sampleCount); + + T *dstSample = dst->samples(); + T *endDstSample = + dstSample + std::min(st1->getSampleCount(), st2->getSampleCount()); + + T *st1Sample = st1->samples(); + T *st2Sample = st2->samples(); + + while (dstSample < endDstSample) { + *dstSample++ = T::mix(*st1Sample, a1, *st2Sample, a2); + ++st1Sample; + ++st2Sample; + } + + T *srcSample = + st1->getSampleCount() > st2->getSampleCount() ? st1Sample : st2Sample; + endDstSample = dst->samples() + sampleCount; + while (dstSample < endDstSample) *dstSample++ = *srcSample++; + + return TSoundTrackP(dst); } //============================================================================= -class TSoundTrackMixer : public TSoundTransform -{ - double m_alpha1, m_alpha2; - TSoundTrackP m_sndtrack; +class TSoundTrackMixer : public TSoundTransform { + double m_alpha1, m_alpha2; + TSoundTrackP m_sndtrack; public: - TSoundTrackMixer(double a1, double a2, const TSoundTrackP &st2) - : TSoundTransform(), m_alpha1(a1), m_alpha2(a2), m_sndtrack(st2) - { - } - - ~TSoundTrackMixer(){}; - - TSoundTrackP compute(const TSoundTrackMono8Signed &src) - { - assert(src.getFormat() == m_sndtrack->getFormat()); - - return (mixT( - const_cast(&src), m_alpha1, - dynamic_cast(m_sndtrack.getPointer()), m_alpha2)); - } - - TSoundTrackP compute(const TSoundTrackMono8Unsigned &src) - { - assert(src.getFormat() == m_sndtrack->getFormat()); - - return (mixT( - const_cast(&src), m_alpha1, - dynamic_cast(m_sndtrack.getPointer()), m_alpha2)); - } - - TSoundTrackP compute(const TSoundTrackStereo8Signed &src) - { - assert(src.getFormat() == m_sndtrack->getFormat()); - - return (mixT( - const_cast(&src), m_alpha1, - dynamic_cast(m_sndtrack.getPointer()), m_alpha2)); - } - - TSoundTrackP compute(const TSoundTrackStereo8Unsigned &src) - { - assert(src.getFormat() == m_sndtrack->getFormat()); - - return (mixT( - const_cast(&src), m_alpha1, - dynamic_cast(m_sndtrack.getPointer()), m_alpha2)); - } - - TSoundTrackP compute(const TSoundTrackMono16 &src) - { - assert(src.getFormat() == m_sndtrack->getFormat()); - - return (mixT( - const_cast(&src), m_alpha1, - dynamic_cast(m_sndtrack.getPointer()), m_alpha2)); - } - - TSoundTrackP compute(const TSoundTrackStereo16 &src) - { - assert(src.getFormat() == m_sndtrack->getFormat()); - - return (mixT( - const_cast(&src), m_alpha1, - dynamic_cast(m_sndtrack.getPointer()), m_alpha2)); - } - - TSoundTrackP compute(const TSoundTrackMono24 &src) - { - assert(src.getFormat() == m_sndtrack->getFormat()); - - return (mixT( - const_cast(&src), m_alpha1, - dynamic_cast(m_sndtrack.getPointer()), m_alpha2)); - } - - TSoundTrackP compute(const TSoundTrackStereo24 &src) - { - assert(src.getFormat() == m_sndtrack->getFormat()); - - return (mixT( - const_cast(&src), m_alpha1, - dynamic_cast(m_sndtrack.getPointer()), m_alpha2)); - } + TSoundTrackMixer(double a1, double a2, const TSoundTrackP &st2) + : TSoundTransform(), m_alpha1(a1), m_alpha2(a2), m_sndtrack(st2) {} + + ~TSoundTrackMixer(){}; + + TSoundTrackP compute(const TSoundTrackMono8Signed &src) { + assert(src.getFormat() == m_sndtrack->getFormat()); + + return ( + mixT(const_cast(&src), m_alpha1, + dynamic_cast(m_sndtrack.getPointer()), + m_alpha2)); + } + + TSoundTrackP compute(const TSoundTrackMono8Unsigned &src) { + assert(src.getFormat() == m_sndtrack->getFormat()); + + return ( + mixT(const_cast(&src), m_alpha1, + dynamic_cast(m_sndtrack.getPointer()), + m_alpha2)); + } + + TSoundTrackP compute(const TSoundTrackStereo8Signed &src) { + assert(src.getFormat() == m_sndtrack->getFormat()); + + return ( + mixT(const_cast(&src), m_alpha1, + dynamic_cast(m_sndtrack.getPointer()), + m_alpha2)); + } + + TSoundTrackP compute(const TSoundTrackStereo8Unsigned &src) { + assert(src.getFormat() == m_sndtrack->getFormat()); + + return (mixT( + const_cast(&src), m_alpha1, + dynamic_cast(m_sndtrack.getPointer()), + m_alpha2)); + } + + TSoundTrackP compute(const TSoundTrackMono16 &src) { + assert(src.getFormat() == m_sndtrack->getFormat()); + + return (mixT(const_cast(&src), m_alpha1, + dynamic_cast(m_sndtrack.getPointer()), + m_alpha2)); + } + + TSoundTrackP compute(const TSoundTrackStereo16 &src) { + assert(src.getFormat() == m_sndtrack->getFormat()); + + return (mixT(const_cast(&src), m_alpha1, + dynamic_cast(m_sndtrack.getPointer()), + m_alpha2)); + } + + TSoundTrackP compute(const TSoundTrackMono24 &src) { + assert(src.getFormat() == m_sndtrack->getFormat()); + + return (mixT(const_cast(&src), m_alpha1, + dynamic_cast(m_sndtrack.getPointer()), + m_alpha2)); + } + + TSoundTrackP compute(const TSoundTrackStereo24 &src) { + assert(src.getFormat() == m_sndtrack->getFormat()); + + return (mixT(const_cast(&src), m_alpha1, + dynamic_cast(m_sndtrack.getPointer()), + m_alpha2)); + } }; -TSoundTrackP TSop::mix( - const TSoundTrackP &st1, - const TSoundTrackP &st2, - double a1, - double a2) -{ - TSoundTrackMixer *converter; - a1 = tcrop(a1, 0.0, 1.0); - a2 = tcrop(a2, 0.0, 1.0); - converter = new TSoundTrackMixer(a1, a2, st2); - TSoundTrackP snd = st1->apply(converter); - delete converter; - return (snd); +TSoundTrackP TSop::mix(const TSoundTrackP &st1, const TSoundTrackP &st2, + double a1, double a2) { + TSoundTrackMixer *converter; + a1 = tcrop(a1, 0.0, 1.0); + a2 = tcrop(a2, 0.0, 1.0); + converter = new TSoundTrackMixer(a1, a2, st2); + TSoundTrackP snd = st1->apply(converter); + delete converter; + return (snd); } //============================================================================== @@ -1440,133 +1317,122 @@ TSoundTrackP TSop::mix( //============================================================================== template -TSoundTrackP doFadeIn(const TSoundTrackT &track, double riseFactor) -{ - typedef typename T::ChannelValueType ChannelValueType; - int sampleCount = (int)((double)track.getSampleCount() * riseFactor); - if (!sampleCount) - sampleCount = 1; - assert(sampleCount); - int channelCount = track.getChannelCount(); - - TSoundTrackT *out = - new TSoundTrackT(track.getSampleRate(), channelCount, sampleCount); - - double val[2], step[2]; - - ChannelValueType chan[2]; - const T *firstSample = track.samples(); - for (int k = 0; k < channelCount; ++k) { - chan[k] = firstSample->getValue(k); - if (firstSample->isSampleSigned()) { - val[k] = 0; - step[k] = (double)chan[k] / (double)sampleCount; - } else { - val[k] = 127; - step[k] = (double)(chan[k] - 128) / (double)sampleCount; - } - } - - T *psample = out->samples(); - T *end = psample + out->getSampleCount(); - - while (psample < end) { - T sample; - for (int k = 0; k < channelCount; ++k) { - sample.setValue(k, (ChannelValueType)val[k]); - val[k] += step[k]; - } - *psample = sample; - ++psample; - } - - return out; +TSoundTrackP doFadeIn(const TSoundTrackT &track, double riseFactor) { + typedef typename T::ChannelValueType ChannelValueType; + int sampleCount = (int)((double)track.getSampleCount() * riseFactor); + if (!sampleCount) sampleCount = 1; + assert(sampleCount); + int channelCount = track.getChannelCount(); + + TSoundTrackT *out = + new TSoundTrackT(track.getSampleRate(), channelCount, sampleCount); + + double val[2], step[2]; + + ChannelValueType chan[2]; + const T *firstSample = track.samples(); + for (int k = 0; k < channelCount; ++k) { + chan[k] = firstSample->getValue(k); + if (firstSample->isSampleSigned()) { + val[k] = 0; + step[k] = (double)chan[k] / (double)sampleCount; + } else { + val[k] = 127; + step[k] = (double)(chan[k] - 128) / (double)sampleCount; + } + } + + T *psample = out->samples(); + T *end = psample + out->getSampleCount(); + + while (psample < end) { + T sample; + for (int k = 0; k < channelCount; ++k) { + sample.setValue(k, (ChannelValueType)val[k]); + val[k] += step[k]; + } + *psample = sample; + ++psample; + } + + return out; } //------------------------------------------------------------------------------ -class TSoundTrackFaderIn : public TSoundTransform -{ +class TSoundTrackFaderIn : public TSoundTransform { public: - TSoundTrackFaderIn(double riseFactor) - : TSoundTransform(), m_riseFactor(riseFactor) - { - } - - TSoundTrackP compute(const TSoundTrackMono8Signed &); - TSoundTrackP compute(const TSoundTrackStereo8Signed &); - TSoundTrackP compute(const TSoundTrackMono8Unsigned &); - TSoundTrackP compute(const TSoundTrackStereo8Unsigned &); - TSoundTrackP compute(const TSoundTrackMono16 &); - TSoundTrackP compute(const TSoundTrackStereo16 &); - TSoundTrackP compute(const TSoundTrackMono24 &); - TSoundTrackP compute(const TSoundTrackStereo24 &); - - double m_riseFactor; + TSoundTrackFaderIn(double riseFactor) + : TSoundTransform(), m_riseFactor(riseFactor) {} + + TSoundTrackP compute(const TSoundTrackMono8Signed &); + TSoundTrackP compute(const TSoundTrackStereo8Signed &); + TSoundTrackP compute(const TSoundTrackMono8Unsigned &); + TSoundTrackP compute(const TSoundTrackStereo8Unsigned &); + TSoundTrackP compute(const TSoundTrackMono16 &); + TSoundTrackP compute(const TSoundTrackStereo16 &); + TSoundTrackP compute(const TSoundTrackMono24 &); + TSoundTrackP compute(const TSoundTrackStereo24 &); + + double m_riseFactor; }; //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrackFaderIn::compute(const TSoundTrackMono8Signed &track) -{ - return doFadeIn(track, m_riseFactor); +TSoundTrackP TSoundTrackFaderIn::compute(const TSoundTrackMono8Signed &track) { + return doFadeIn(track, m_riseFactor); } //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrackFaderIn::compute(const TSoundTrackStereo8Signed &track) -{ - return doFadeIn(track, m_riseFactor); +TSoundTrackP TSoundTrackFaderIn::compute( + const TSoundTrackStereo8Signed &track) { + return doFadeIn(track, m_riseFactor); } //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrackFaderIn::compute(const TSoundTrackMono8Unsigned &track) -{ - return doFadeIn(track, m_riseFactor); +TSoundTrackP TSoundTrackFaderIn::compute( + const TSoundTrackMono8Unsigned &track) { + return doFadeIn(track, m_riseFactor); } //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrackFaderIn::compute(const TSoundTrackStereo8Unsigned &track) -{ - return doFadeIn(track, m_riseFactor); +TSoundTrackP TSoundTrackFaderIn::compute( + const TSoundTrackStereo8Unsigned &track) { + return doFadeIn(track, m_riseFactor); } //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrackFaderIn::compute(const TSoundTrackMono16 &track) -{ - return doFadeIn(track, m_riseFactor); +TSoundTrackP TSoundTrackFaderIn::compute(const TSoundTrackMono16 &track) { + return doFadeIn(track, m_riseFactor); } //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrackFaderIn::compute(const TSoundTrackStereo16 &track) -{ - return doFadeIn(track, m_riseFactor); +TSoundTrackP TSoundTrackFaderIn::compute(const TSoundTrackStereo16 &track) { + return doFadeIn(track, m_riseFactor); } //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrackFaderIn::compute(const TSoundTrackMono24 &track) -{ - return doFadeIn(track, m_riseFactor); +TSoundTrackP TSoundTrackFaderIn::compute(const TSoundTrackMono24 &track) { + return doFadeIn(track, m_riseFactor); } //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrackFaderIn::compute(const TSoundTrackStereo24 &track) -{ - return doFadeIn(track, m_riseFactor); +TSoundTrackP TSoundTrackFaderIn::compute(const TSoundTrackStereo24 &track) { + return doFadeIn(track, m_riseFactor); } //------------------------------------------------------------------------------ -TSoundTrackP TSop::fadeIn(const TSoundTrackP src, double riseFactor) -{ - TSoundTrackFaderIn *fader = new TSoundTrackFaderIn(riseFactor); - TSoundTrackP out = src->apply(fader); - delete fader; - return out; +TSoundTrackP TSop::fadeIn(const TSoundTrackP src, double riseFactor) { + TSoundTrackFaderIn *fader = new TSoundTrackFaderIn(riseFactor); + TSoundTrackP out = src->apply(fader); + delete fader; + return out; } //============================================================================== @@ -1576,131 +1442,119 @@ TSoundTrackP TSop::fadeIn(const TSoundTrackP src, double riseFactor) //============================================================================== template -TSoundTrackP doFadeOut( - const TSoundTrackT &track, double decayFactor) -{ - typedef typename T::ChannelValueType ChannelValueType; - int sampleCount = (int)((double)track.getSampleCount() * decayFactor); - if (!sampleCount) - sampleCount = 1; - assert(sampleCount); - int channelCount = track.getChannelCount(); - - TSoundTrackT *out = - new TSoundTrackT(track.getSampleRate(), channelCount, sampleCount); - - double val[2], step[2]; - ChannelValueType chan[2]; - const T *lastSample = (track.samples() + track.getSampleCount() - 1); - for (int k = 0; k < channelCount; ++k) { - chan[k] = lastSample->getValue(k); - val[k] = (double)chan[k]; - if (lastSample->isSampleSigned()) - step[k] = (double)chan[k] / (double)sampleCount; - else - step[k] = (double)(chan[k] - 128) / (double)sampleCount; - } - - T *psample = out->samples(); - T *end = psample + out->getSampleCount(); - - while (psample < end) { - T sample; - for (int k = 0; k < channelCount; ++k) { - sample.setValue(k, (ChannelValueType)val[k]); - val[k] -= step[k]; - } - *psample = sample; - ++psample; - } - - return out; +TSoundTrackP doFadeOut(const TSoundTrackT &track, double decayFactor) { + typedef typename T::ChannelValueType ChannelValueType; + int sampleCount = (int)((double)track.getSampleCount() * decayFactor); + if (!sampleCount) sampleCount = 1; + assert(sampleCount); + int channelCount = track.getChannelCount(); + + TSoundTrackT *out = + new TSoundTrackT(track.getSampleRate(), channelCount, sampleCount); + + double val[2], step[2]; + ChannelValueType chan[2]; + const T *lastSample = (track.samples() + track.getSampleCount() - 1); + for (int k = 0; k < channelCount; ++k) { + chan[k] = lastSample->getValue(k); + val[k] = (double)chan[k]; + if (lastSample->isSampleSigned()) + step[k] = (double)chan[k] / (double)sampleCount; + else + step[k] = (double)(chan[k] - 128) / (double)sampleCount; + } + + T *psample = out->samples(); + T *end = psample + out->getSampleCount(); + + while (psample < end) { + T sample; + for (int k = 0; k < channelCount; ++k) { + sample.setValue(k, (ChannelValueType)val[k]); + val[k] -= step[k]; + } + *psample = sample; + ++psample; + } + + return out; } //------------------------------------------------------------------------------ -class TSoundTrackFaderOut : public TSoundTransform -{ +class TSoundTrackFaderOut : public TSoundTransform { public: - TSoundTrackFaderOut(double decayFactor) - : TSoundTransform(), m_decayFactor(decayFactor) - { - } - - TSoundTrackP compute(const TSoundTrackMono8Signed &); - TSoundTrackP compute(const TSoundTrackStereo8Signed &); - TSoundTrackP compute(const TSoundTrackMono8Unsigned &); - TSoundTrackP compute(const TSoundTrackStereo8Unsigned &); - TSoundTrackP compute(const TSoundTrackMono16 &); - TSoundTrackP compute(const TSoundTrackStereo16 &); - TSoundTrackP compute(const TSoundTrackMono24 &); - TSoundTrackP compute(const TSoundTrackStereo24 &); - - double m_decayFactor; + TSoundTrackFaderOut(double decayFactor) + : TSoundTransform(), m_decayFactor(decayFactor) {} + + TSoundTrackP compute(const TSoundTrackMono8Signed &); + TSoundTrackP compute(const TSoundTrackStereo8Signed &); + TSoundTrackP compute(const TSoundTrackMono8Unsigned &); + TSoundTrackP compute(const TSoundTrackStereo8Unsigned &); + TSoundTrackP compute(const TSoundTrackMono16 &); + TSoundTrackP compute(const TSoundTrackStereo16 &); + TSoundTrackP compute(const TSoundTrackMono24 &); + TSoundTrackP compute(const TSoundTrackStereo24 &); + + double m_decayFactor; }; //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrackFaderOut::compute(const TSoundTrackMono8Signed &track) -{ - return doFadeOut(track, m_decayFactor); +TSoundTrackP TSoundTrackFaderOut::compute(const TSoundTrackMono8Signed &track) { + return doFadeOut(track, m_decayFactor); } //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrackFaderOut::compute(const TSoundTrackStereo8Signed &track) -{ - return doFadeOut(track, m_decayFactor); +TSoundTrackP TSoundTrackFaderOut::compute( + const TSoundTrackStereo8Signed &track) { + return doFadeOut(track, m_decayFactor); } //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrackFaderOut::compute(const TSoundTrackMono8Unsigned &track) -{ - return doFadeOut(track, m_decayFactor); +TSoundTrackP TSoundTrackFaderOut::compute( + const TSoundTrackMono8Unsigned &track) { + return doFadeOut(track, m_decayFactor); } //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrackFaderOut::compute(const TSoundTrackStereo8Unsigned &track) -{ - return doFadeOut(track, m_decayFactor); +TSoundTrackP TSoundTrackFaderOut::compute( + const TSoundTrackStereo8Unsigned &track) { + return doFadeOut(track, m_decayFactor); } //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrackFaderOut::compute(const TSoundTrackMono16 &track) -{ - return doFadeOut(track, m_decayFactor); +TSoundTrackP TSoundTrackFaderOut::compute(const TSoundTrackMono16 &track) { + return doFadeOut(track, m_decayFactor); } //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrackFaderOut::compute(const TSoundTrackStereo16 &track) -{ - return doFadeOut(track, m_decayFactor); +TSoundTrackP TSoundTrackFaderOut::compute(const TSoundTrackStereo16 &track) { + return doFadeOut(track, m_decayFactor); } //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrackFaderOut::compute(const TSoundTrackMono24 &track) -{ - return doFadeOut(track, m_decayFactor); +TSoundTrackP TSoundTrackFaderOut::compute(const TSoundTrackMono24 &track) { + return doFadeOut(track, m_decayFactor); } //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrackFaderOut::compute(const TSoundTrackStereo24 &track) -{ - return doFadeOut(track, m_decayFactor); +TSoundTrackP TSoundTrackFaderOut::compute(const TSoundTrackStereo24 &track) { + return doFadeOut(track, m_decayFactor); } //------------------------------------------------------------------------------ -TSoundTrackP TSop::fadeOut(const TSoundTrackP src, double decayFactor) -{ - TSoundTrackFaderOut *fader = new TSoundTrackFaderOut(decayFactor); - TSoundTrackP out = src->apply(fader); - delete fader; - return out; +TSoundTrackP TSop::fadeOut(const TSoundTrackP src, double decayFactor) { + TSoundTrackFaderOut *fader = new TSoundTrackFaderOut(decayFactor); + TSoundTrackP out = src->apply(fader); + delete fader; + return out; } //============================================================================== @@ -1710,163 +1564,155 @@ TSoundTrackP TSop::fadeOut(const TSoundTrackP src, double decayFactor) //============================================================================== template -TSoundTrackP doCrossFade( - const TSoundTrackT &track1, - TSoundTrackT *track2, - double crossFactor) -{ - typedef typename T::ChannelValueType ChannelValueType; - int channelCount = track2->getChannelCount(); - int sampleCount = (int)((double)track2->getSampleCount() * crossFactor); - if (!sampleCount) - sampleCount = 1; - assert(sampleCount); - - //ultimo campione di track1 - ChannelValueType chanTrack1[2]; - const T *lastSample = (track1.samples() + track1.getSampleCount() - 1); - int k; - for (k = 0; k < channelCount; ++k) - chanTrack1[k] = lastSample->getValue(k); - - double val[2], step[2]; - - //primo campione di track2 - ChannelValueType chanTrack2[2]; - const T *firstSample = track2->samples(); - for (k = 0; k < channelCount; ++k) { - chanTrack2[k] = firstSample->getValue(k); - val[k] = chanTrack1[k] - chanTrack2[k]; - step[k] = val[k] / (double)sampleCount; - } - - TSoundTrackT *out = - new TSoundTrackT(track2->getSampleRate(), channelCount, sampleCount); - - T *psample = out->samples(); - T *end = psample + out->getSampleCount(); - - while (psample < end) { - T sample; - for (int k = 0; k < channelCount; ++k) { - double tot = (double)firstSample->getValue(k) + val[k]; - ChannelValueType value = (ChannelValueType)tot; - - sample.setValue(k, value); - val[k] -= step[k]; - } - *psample = sample; - ++psample; - //++firstSample; - } - - return out; +TSoundTrackP doCrossFade(const TSoundTrackT &track1, TSoundTrackT *track2, + double crossFactor) { + typedef typename T::ChannelValueType ChannelValueType; + int channelCount = track2->getChannelCount(); + int sampleCount = (int)((double)track2->getSampleCount() * crossFactor); + if (!sampleCount) sampleCount = 1; + assert(sampleCount); + + // ultimo campione di track1 + ChannelValueType chanTrack1[2]; + const T *lastSample = (track1.samples() + track1.getSampleCount() - 1); + int k; + for (k = 0; k < channelCount; ++k) chanTrack1[k] = lastSample->getValue(k); + + double val[2], step[2]; + + // primo campione di track2 + ChannelValueType chanTrack2[2]; + const T *firstSample = track2->samples(); + for (k = 0; k < channelCount; ++k) { + chanTrack2[k] = firstSample->getValue(k); + val[k] = chanTrack1[k] - chanTrack2[k]; + step[k] = val[k] / (double)sampleCount; + } + + TSoundTrackT *out = + new TSoundTrackT(track2->getSampleRate(), channelCount, sampleCount); + + T *psample = out->samples(); + T *end = psample + out->getSampleCount(); + + while (psample < end) { + T sample; + for (int k = 0; k < channelCount; ++k) { + double tot = (double)firstSample->getValue(k) + val[k]; + ChannelValueType value = (ChannelValueType)tot; + + sample.setValue(k, value); + val[k] -= step[k]; + } + *psample = sample; + ++psample; + //++firstSample; + } + + return out; } //------------------------------------------------------------------------------ -class TSoundTrackCrossFader : public TSoundTransform -{ +class TSoundTrackCrossFader : public TSoundTransform { public: - TSoundTrackCrossFader(TSoundTrackP src, double crossFactor) - : TSoundTransform(), m_st(src), m_crossFactor(crossFactor) - { - } - - TSoundTrackP compute(const TSoundTrackMono8Signed &); - TSoundTrackP compute(const TSoundTrackStereo8Signed &); - TSoundTrackP compute(const TSoundTrackMono8Unsigned &); - TSoundTrackP compute(const TSoundTrackStereo8Unsigned &); - TSoundTrackP compute(const TSoundTrackMono16 &); - TSoundTrackP compute(const TSoundTrackStereo16 &); - TSoundTrackP compute(const TSoundTrackMono24 &); - TSoundTrackP compute(const TSoundTrackStereo24 &); - - TSoundTrackP m_st; - double m_crossFactor; + TSoundTrackCrossFader(TSoundTrackP src, double crossFactor) + : TSoundTransform(), m_st(src), m_crossFactor(crossFactor) {} + + TSoundTrackP compute(const TSoundTrackMono8Signed &); + TSoundTrackP compute(const TSoundTrackStereo8Signed &); + TSoundTrackP compute(const TSoundTrackMono8Unsigned &); + TSoundTrackP compute(const TSoundTrackStereo8Unsigned &); + TSoundTrackP compute(const TSoundTrackMono16 &); + TSoundTrackP compute(const TSoundTrackStereo16 &); + TSoundTrackP compute(const TSoundTrackMono24 &); + TSoundTrackP compute(const TSoundTrackStereo24 &); + + TSoundTrackP m_st; + double m_crossFactor; }; //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrackCrossFader::compute(const TSoundTrackMono8Signed &src) -{ - assert(src.getFormat() == m_st->getFormat()); - return doCrossFade( - src, dynamic_cast(m_st.getPointer()), m_crossFactor); +TSoundTrackP TSoundTrackCrossFader::compute(const TSoundTrackMono8Signed &src) { + assert(src.getFormat() == m_st->getFormat()); + return doCrossFade(src, + dynamic_cast(m_st.getPointer()), + m_crossFactor); } //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrackCrossFader::compute(const TSoundTrackStereo8Signed &src) -{ - assert(src.getFormat() == m_st->getFormat()); - return doCrossFade( - src, dynamic_cast(m_st.getPointer()), m_crossFactor); +TSoundTrackP TSoundTrackCrossFader::compute( + const TSoundTrackStereo8Signed &src) { + assert(src.getFormat() == m_st->getFormat()); + return doCrossFade( + src, dynamic_cast(m_st.getPointer()), + m_crossFactor); } //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrackCrossFader::compute(const TSoundTrackMono8Unsigned &src) -{ - assert(src.getFormat() == m_st->getFormat()); - return doCrossFade( - src, dynamic_cast(m_st.getPointer()), m_crossFactor); +TSoundTrackP TSoundTrackCrossFader::compute( + const TSoundTrackMono8Unsigned &src) { + assert(src.getFormat() == m_st->getFormat()); + return doCrossFade( + src, dynamic_cast(m_st.getPointer()), + m_crossFactor); } //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrackCrossFader::compute(const TSoundTrackStereo8Unsigned &src) -{ - assert(src.getFormat() == m_st->getFormat()); - return doCrossFade( - src, dynamic_cast(m_st.getPointer()), m_crossFactor); +TSoundTrackP TSoundTrackCrossFader::compute( + const TSoundTrackStereo8Unsigned &src) { + assert(src.getFormat() == m_st->getFormat()); + return doCrossFade( + src, dynamic_cast(m_st.getPointer()), + m_crossFactor); } //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrackCrossFader::compute(const TSoundTrackMono16 &src) -{ - assert(src.getFormat() == m_st->getFormat()); - return doCrossFade( - src, dynamic_cast(m_st.getPointer()), m_crossFactor); +TSoundTrackP TSoundTrackCrossFader::compute(const TSoundTrackMono16 &src) { + assert(src.getFormat() == m_st->getFormat()); + return doCrossFade(src, dynamic_cast(m_st.getPointer()), + m_crossFactor); } //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrackCrossFader::compute(const TSoundTrackStereo16 &src) -{ - assert(src.getFormat() == m_st->getFormat()); - return doCrossFade( - src, dynamic_cast(m_st.getPointer()), m_crossFactor); +TSoundTrackP TSoundTrackCrossFader::compute(const TSoundTrackStereo16 &src) { + assert(src.getFormat() == m_st->getFormat()); + return doCrossFade(src, + dynamic_cast(m_st.getPointer()), + m_crossFactor); } //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrackCrossFader::compute(const TSoundTrackMono24 &src) -{ - assert(src.getFormat() == m_st->getFormat()); - return doCrossFade( - src, dynamic_cast(m_st.getPointer()), m_crossFactor); +TSoundTrackP TSoundTrackCrossFader::compute(const TSoundTrackMono24 &src) { + assert(src.getFormat() == m_st->getFormat()); + return doCrossFade(src, dynamic_cast(m_st.getPointer()), + m_crossFactor); } //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrackCrossFader::compute(const TSoundTrackStereo24 &src) -{ - assert(src.getFormat() == m_st->getFormat()); - return doCrossFade( - src, dynamic_cast(m_st.getPointer()), m_crossFactor); +TSoundTrackP TSoundTrackCrossFader::compute(const TSoundTrackStereo24 &src) { + assert(src.getFormat() == m_st->getFormat()); + return doCrossFade(src, + dynamic_cast(m_st.getPointer()), + m_crossFactor); } //------------------------------------------------------------------------------ -TSoundTrackP TSop::crossFade( - const TSoundTrackP src1, const TSoundTrackP src2, double crossFactor) -{ - TSoundTrackCrossFader *fader = new TSoundTrackCrossFader(src2, crossFactor); - TSoundTrackP out = src1->apply(fader); - delete fader; - return out; +TSoundTrackP TSop::crossFade(const TSoundTrackP src1, const TSoundTrackP src2, + double crossFactor) { + TSoundTrackCrossFader *fader = new TSoundTrackCrossFader(src2, crossFactor); + TSoundTrackP out = src1->apply(fader); + delete fader; + return out; } // @@ -1880,166 +1726,163 @@ TSoundTrackP TSop::crossFade( //============================================================================== template -TSoundTrackP doCrossFadeOverWrite( - const TSoundTrackT &track1, - TSoundTrackT *track2, - double crossFactor) -{ - typedef typename T::ChannelValueType ChannelValueType; - int channelCount = track2->getChannelCount(); - int sampleCount = (int)((double)track2->getSampleCount() * crossFactor); - int sampleCountT2 = track2->getSampleCount(); - - if (sampleCount == 0 && sampleCountT2 == 1) - return track2; - if (sampleCount == 0) - sampleCount = 1; - assert(sampleCount); - - //ultimo campione di track1 - ChannelValueType chanTrack1[2]; - const T *lastSample = (track1.samples() + track1.getSampleCount() - 1); - int k; - for (k = 0; k < channelCount; ++k) - chanTrack1[k] = lastSample->getValue(k); - - double val[2], step[2]; - - //primo campione di track2 - ChannelValueType chanTrack2[2]; - const T *firstSample = track2->samples() + sampleCount; - for (k = 0; k < channelCount; ++k) { - chanTrack2[k] = firstSample->getValue(k); - val[k] = chanTrack1[k] - chanTrack2[k]; - step[k] = val[k] / (double)sampleCount; - } - - TSoundTrackT *out = - new TSoundTrackT(track2->getSampleRate(), channelCount, sampleCountT2); - - T *psample = out->samples(); - T *end = psample + sampleCount; - - while (psample < end) { - T sample; - for (int k = 0; k < channelCount; ++k) { - double tot = (double)firstSample->getValue(k) + val[k]; - ChannelValueType value = (ChannelValueType)tot; - - sample.setValue(k, value); - val[k] -= step[k]; - } - *psample = sample; - ++psample; - } - - out->copy(track2->extract(sampleCount, sampleCountT2 - 1), sampleCount); - - return out; +TSoundTrackP doCrossFadeOverWrite(const TSoundTrackT &track1, + TSoundTrackT *track2, double crossFactor) { + typedef typename T::ChannelValueType ChannelValueType; + int channelCount = track2->getChannelCount(); + int sampleCount = (int)((double)track2->getSampleCount() * crossFactor); + int sampleCountT2 = track2->getSampleCount(); + + if (sampleCount == 0 && sampleCountT2 == 1) return track2; + if (sampleCount == 0) sampleCount = 1; + assert(sampleCount); + + // ultimo campione di track1 + ChannelValueType chanTrack1[2]; + const T *lastSample = (track1.samples() + track1.getSampleCount() - 1); + int k; + for (k = 0; k < channelCount; ++k) chanTrack1[k] = lastSample->getValue(k); + + double val[2], step[2]; + + // primo campione di track2 + ChannelValueType chanTrack2[2]; + const T *firstSample = track2->samples() + sampleCount; + for (k = 0; k < channelCount; ++k) { + chanTrack2[k] = firstSample->getValue(k); + val[k] = chanTrack1[k] - chanTrack2[k]; + step[k] = val[k] / (double)sampleCount; + } + + TSoundTrackT *out = + new TSoundTrackT(track2->getSampleRate(), channelCount, sampleCountT2); + + T *psample = out->samples(); + T *end = psample + sampleCount; + + while (psample < end) { + T sample; + for (int k = 0; k < channelCount; ++k) { + double tot = (double)firstSample->getValue(k) + val[k]; + ChannelValueType value = (ChannelValueType)tot; + + sample.setValue(k, value); + val[k] -= step[k]; + } + *psample = sample; + ++psample; + } + + out->copy(track2->extract(sampleCount, sampleCountT2 - 1), sampleCount); + + return out; } //------------------------------------------------------------------------------ -class TSoundTrackCrossFaderOverWrite : public TSoundTransform -{ +class TSoundTrackCrossFaderOverWrite : public TSoundTransform { public: - TSoundTrackCrossFaderOverWrite(TSoundTrackP src, double crossFactor) - : TSoundTransform(), m_st(src), m_crossFactor(crossFactor) - { - } - - TSoundTrackP compute(const TSoundTrackMono8Signed &); - TSoundTrackP compute(const TSoundTrackStereo8Signed &); - TSoundTrackP compute(const TSoundTrackMono8Unsigned &); - TSoundTrackP compute(const TSoundTrackStereo8Unsigned &); - TSoundTrackP compute(const TSoundTrackMono16 &); - TSoundTrackP compute(const TSoundTrackStereo16 &); - TSoundTrackP compute(const TSoundTrackMono24 &); - TSoundTrackP compute(const TSoundTrackStereo24 &); - - TSoundTrackP m_st; - double m_crossFactor; + TSoundTrackCrossFaderOverWrite(TSoundTrackP src, double crossFactor) + : TSoundTransform(), m_st(src), m_crossFactor(crossFactor) {} + + TSoundTrackP compute(const TSoundTrackMono8Signed &); + TSoundTrackP compute(const TSoundTrackStereo8Signed &); + TSoundTrackP compute(const TSoundTrackMono8Unsigned &); + TSoundTrackP compute(const TSoundTrackStereo8Unsigned &); + TSoundTrackP compute(const TSoundTrackMono16 &); + TSoundTrackP compute(const TSoundTrackStereo16 &); + TSoundTrackP compute(const TSoundTrackMono24 &); + TSoundTrackP compute(const TSoundTrackStereo24 &); + + TSoundTrackP m_st; + double m_crossFactor; }; //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrackCrossFaderOverWrite::compute(const TSoundTrackMono8Signed &src) -{ - assert(src.getFormat() == m_st->getFormat()); - return doCrossFadeOverWrite( - src, dynamic_cast(m_st.getPointer()), m_crossFactor); +TSoundTrackP TSoundTrackCrossFaderOverWrite::compute( + const TSoundTrackMono8Signed &src) { + assert(src.getFormat() == m_st->getFormat()); + return doCrossFadeOverWrite( + src, dynamic_cast(m_st.getPointer()), + m_crossFactor); } //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrackCrossFaderOverWrite::compute(const TSoundTrackStereo8Signed &src) -{ - assert(src.getFormat() == m_st->getFormat()); - return doCrossFadeOverWrite( - src, dynamic_cast(m_st.getPointer()), m_crossFactor); +TSoundTrackP TSoundTrackCrossFaderOverWrite::compute( + const TSoundTrackStereo8Signed &src) { + assert(src.getFormat() == m_st->getFormat()); + return doCrossFadeOverWrite( + src, dynamic_cast(m_st.getPointer()), + m_crossFactor); } //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrackCrossFaderOverWrite::compute(const TSoundTrackMono8Unsigned &src) -{ - assert(src.getFormat() == m_st->getFormat()); - return doCrossFadeOverWrite( - src, dynamic_cast(m_st.getPointer()), m_crossFactor); +TSoundTrackP TSoundTrackCrossFaderOverWrite::compute( + const TSoundTrackMono8Unsigned &src) { + assert(src.getFormat() == m_st->getFormat()); + return doCrossFadeOverWrite( + src, dynamic_cast(m_st.getPointer()), + m_crossFactor); } //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrackCrossFaderOverWrite::compute(const TSoundTrackStereo8Unsigned &src) -{ - assert(src.getFormat() == m_st->getFormat()); - return doCrossFadeOverWrite( - src, dynamic_cast(m_st.getPointer()), m_crossFactor); +TSoundTrackP TSoundTrackCrossFaderOverWrite::compute( + const TSoundTrackStereo8Unsigned &src) { + assert(src.getFormat() == m_st->getFormat()); + return doCrossFadeOverWrite( + src, dynamic_cast(m_st.getPointer()), + m_crossFactor); } //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrackCrossFaderOverWrite::compute(const TSoundTrackMono16 &src) -{ - assert(src.getFormat() == m_st->getFormat()); - return doCrossFadeOverWrite( - src, dynamic_cast(m_st.getPointer()), m_crossFactor); +TSoundTrackP TSoundTrackCrossFaderOverWrite::compute( + const TSoundTrackMono16 &src) { + assert(src.getFormat() == m_st->getFormat()); + return doCrossFadeOverWrite( + src, dynamic_cast(m_st.getPointer()), m_crossFactor); } //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrackCrossFaderOverWrite::compute(const TSoundTrackStereo16 &src) -{ - assert(src.getFormat() == m_st->getFormat()); - return doCrossFadeOverWrite( - src, dynamic_cast(m_st.getPointer()), m_crossFactor); +TSoundTrackP TSoundTrackCrossFaderOverWrite::compute( + const TSoundTrackStereo16 &src) { + assert(src.getFormat() == m_st->getFormat()); + return doCrossFadeOverWrite( + src, dynamic_cast(m_st.getPointer()), + m_crossFactor); } //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrackCrossFaderOverWrite::compute(const TSoundTrackMono24 &src) -{ - assert(src.getFormat() == m_st->getFormat()); - return doCrossFadeOverWrite( - src, dynamic_cast(m_st.getPointer()), m_crossFactor); +TSoundTrackP TSoundTrackCrossFaderOverWrite::compute( + const TSoundTrackMono24 &src) { + assert(src.getFormat() == m_st->getFormat()); + return doCrossFadeOverWrite( + src, dynamic_cast(m_st.getPointer()), m_crossFactor); } //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrackCrossFaderOverWrite::compute(const TSoundTrackStereo24 &src) -{ - assert(src.getFormat() == m_st->getFormat()); - return doCrossFadeOverWrite( - src, dynamic_cast(m_st.getPointer()), m_crossFactor); +TSoundTrackP TSoundTrackCrossFaderOverWrite::compute( + const TSoundTrackStereo24 &src) { + assert(src.getFormat() == m_st->getFormat()); + return doCrossFadeOverWrite( + src, dynamic_cast(m_st.getPointer()), + m_crossFactor); } //------------------------------------------------------------------------------ -TSoundTrackP TSop::crossFade(double crossFactor, - const TSoundTrackP src1, const TSoundTrackP src2) -{ - TSoundTrackCrossFaderOverWrite *fader = new TSoundTrackCrossFaderOverWrite(src2, crossFactor); - TSoundTrackP out = src1->apply(fader); - delete fader; - return out; +TSoundTrackP TSop::crossFade(double crossFactor, const TSoundTrackP src1, + const TSoundTrackP src2) { + TSoundTrackCrossFaderOverWrite *fader = + new TSoundTrackCrossFaderOverWrite(src2, crossFactor); + TSoundTrackP out = src1->apply(fader); + delete fader; + return out; } diff --git a/toonz/sources/common/tsound/tsound.cpp b/toonz/sources/common/tsound/tsound.cpp index d54fdf1..5512466 100644 --- a/toonz/sources/common/tsound/tsound.cpp +++ b/toonz/sources/common/tsound/tsound.cpp @@ -18,333 +18,301 @@ DEFINE_CLASS_CODE(TSoundTrack, 12) //------------------------------------------------------------------------------ TSoundTrack::TSoundTrack() - : TSmartObject(m_classCode), m_parent(0), m_buffer(0), m_bufferOwner(false) -{ -} + : TSmartObject(m_classCode) + , m_parent(0) + , m_buffer(0) + , m_bufferOwner(false) {} //------------------------------------------------------------------------------ -TSoundTrack::TSoundTrack(TUINT32 sampleRate, - int bitPerSample, - int channelCount, - int sampleSize, - TINT32 sampleCount, - bool isSampleSigned) - - : TSmartObject(m_classCode), m_sampleRate(sampleRate), m_sampleSize(sampleSize), m_bitPerSample(bitPerSample), m_sampleCount(sampleCount), m_channelCount(channelCount), m_parent(0), m_bufferOwner(true) -{ - m_buffer = (UCHAR *)malloc(sampleCount * m_sampleSize); - if (!m_buffer) - return; - - //m_buffer = new UCHAR[sampleCount*m_sampleSize]; - if (isSampleSigned) - memset(m_buffer, 0, sampleCount * sampleSize); - else - memset(m_buffer, 127, sampleCount * sampleSize); +TSoundTrack::TSoundTrack(TUINT32 sampleRate, int bitPerSample, int channelCount, + int sampleSize, TINT32 sampleCount, + bool isSampleSigned) + + : TSmartObject(m_classCode) + , m_sampleRate(sampleRate) + , m_sampleSize(sampleSize) + , m_bitPerSample(bitPerSample) + , m_sampleCount(sampleCount) + , m_channelCount(channelCount) + , m_parent(0) + , m_bufferOwner(true) { + m_buffer = (UCHAR *)malloc(sampleCount * m_sampleSize); + if (!m_buffer) return; + + // m_buffer = new UCHAR[sampleCount*m_sampleSize]; + if (isSampleSigned) + memset(m_buffer, 0, sampleCount * sampleSize); + else + memset(m_buffer, 127, sampleCount * sampleSize); } //------------------------------------------------------------------------------ -TSoundTrack::TSoundTrack(TUINT32 sampleRate, - int bitPerSample, - int channelCount, - int sampleSize, - TINT32 sampleCount, - UCHAR *buffer, - TSoundTrack *parent) - - : TSmartObject(m_classCode), m_sampleRate(sampleRate), m_sampleSize(sampleSize), m_bitPerSample(bitPerSample), m_sampleCount(sampleCount), m_channelCount(channelCount), m_parent(parent), m_buffer(buffer), m_bufferOwner(false) -{ - if (m_parent) - m_parent->addRef(); +TSoundTrack::TSoundTrack(TUINT32 sampleRate, int bitPerSample, int channelCount, + int sampleSize, TINT32 sampleCount, UCHAR *buffer, + TSoundTrack *parent) + + : TSmartObject(m_classCode) + , m_sampleRate(sampleRate) + , m_sampleSize(sampleSize) + , m_bitPerSample(bitPerSample) + , m_sampleCount(sampleCount) + , m_channelCount(channelCount) + , m_parent(parent) + , m_buffer(buffer) + , m_bufferOwner(false) { + if (m_parent) m_parent->addRef(); } //------------------------------------------------------------------------------ -TSoundTrack::~TSoundTrack() -{ - if (m_parent) - m_parent->release(); - //if (m_buffer && m_bufferOwner) delete [] m_buffer; - if (m_buffer && m_bufferOwner) - free(m_buffer); +TSoundTrack::~TSoundTrack() { + if (m_parent) m_parent->release(); + // if (m_buffer && m_bufferOwner) delete [] m_buffer; + if (m_buffer && m_bufferOwner) free(m_buffer); } //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrack::create( - TUINT32 sampleRate, int bitPerSample, - int channelCount, TINT32 sampleCount, - bool signedSample) -{ - TSoundTrackP st; - int type = bitPerSample + channelCount; - switch (type) { - case TRK_M8: - if (signedSample) - st = new TSoundTrackMono8Signed( - sampleRate, channelCount, sampleCount); - else - st = new TSoundTrackMono8Unsigned( - sampleRate, channelCount, sampleCount); - break; - case TRK_S8: - if (signedSample) - st = new TSoundTrackStereo8Signed( - sampleRate, channelCount, sampleCount); - else - st = new TSoundTrackStereo8Unsigned( - sampleRate, channelCount, sampleCount); - break; - - case TRK_M16: - st = new TSoundTrackMono16( - sampleRate, channelCount, sampleCount); - break; - - case TRK_S16: - st = new TSoundTrackStereo16( - sampleRate, channelCount, sampleCount); - break; - - case TRK_M24: - st = new TSoundTrackMono24( - sampleRate, channelCount, sampleCount); - break; - - case TRK_S24: - st = new TSoundTrackStereo24( - sampleRate, channelCount, sampleCount); - break; - - default: - std::string s; - s = "Type " + std::to_string(sampleRate) + " Hz " + std::to_string(bitPerSample) + " bits "; - if (channelCount == 1) - s += "mono: "; - else - s += "stereo: "; - s += "Unsupported\n"; - - throw TException(s); - } - - if (!st->getRawData()) { - return 0; - } - return st; +TSoundTrackP TSoundTrack::create(TUINT32 sampleRate, int bitPerSample, + int channelCount, TINT32 sampleCount, + bool signedSample) { + TSoundTrackP st; + int type = bitPerSample + channelCount; + switch (type) { + case TRK_M8: + if (signedSample) + st = new TSoundTrackMono8Signed(sampleRate, channelCount, sampleCount); + else + st = new TSoundTrackMono8Unsigned(sampleRate, channelCount, sampleCount); + break; + case TRK_S8: + if (signedSample) + st = new TSoundTrackStereo8Signed(sampleRate, channelCount, sampleCount); + else + st = + new TSoundTrackStereo8Unsigned(sampleRate, channelCount, sampleCount); + break; + + case TRK_M16: + st = new TSoundTrackMono16(sampleRate, channelCount, sampleCount); + break; + + case TRK_S16: + st = new TSoundTrackStereo16(sampleRate, channelCount, sampleCount); + break; + + case TRK_M24: + st = new TSoundTrackMono24(sampleRate, channelCount, sampleCount); + break; + + case TRK_S24: + st = new TSoundTrackStereo24(sampleRate, channelCount, sampleCount); + break; + + default: + std::string s; + s = "Type " + std::to_string(sampleRate) + " Hz " + + std::to_string(bitPerSample) + " bits "; + if (channelCount == 1) + s += "mono: "; + else + s += "stereo: "; + s += "Unsupported\n"; + + throw TException(s); + } + + if (!st->getRawData()) { + return 0; + } + return st; } //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrack::create( - TUINT32 sampleRate, int bitPerSample, - int channelCount, TINT32 sampleCount, void *buffer, - bool signedSample) -{ - TSoundTrackP st; - int type = bitPerSample + channelCount; - switch (type) { - case TRK_M8: - if (signedSample) - st = new TSoundTrackMono8Signed( - sampleRate, channelCount, sampleCount, (TMono8SignedSample *)buffer, 0); - else - st = new TSoundTrackMono8Unsigned( - sampleRate, channelCount, sampleCount, (TMono8UnsignedSample *)buffer, 0); - break; - case TRK_S8: - if (signedSample) - st = new TSoundTrackStereo8Signed( - sampleRate, channelCount, sampleCount, (TStereo8SignedSample *)buffer, 0); - else - st = new TSoundTrackStereo8Unsigned( - sampleRate, channelCount, sampleCount, (TStereo8UnsignedSample *)buffer, 0); - break; - - case TRK_M16: - st = new TSoundTrackMono16( - sampleRate, channelCount, sampleCount, (TMono16Sample *)buffer, 0); - break; - - case TRK_S16: - st = new TSoundTrackStereo16( - sampleRate, channelCount, sampleCount, (TStereo16Sample *)buffer, 0); - break; - - case TRK_M24: - st = new TSoundTrackMono24( - sampleRate, channelCount, sampleCount, (TMono24Sample *)buffer, 0); - break; - - case TRK_S24: - st = new TSoundTrackStereo24( - sampleRate, channelCount, sampleCount, (TStereo24Sample *)buffer, 0); - break; - - default: - std::string s; - s = "Type " + std::to_string(sampleRate) + " Hz " + std::to_string(bitPerSample) + " bits "; - if (channelCount == 1) - s += "mono: "; - else - s += "stereo: "; - s += "Unsupported\n"; - - throw TException(s); - } - - return st; +TSoundTrackP TSoundTrack::create(TUINT32 sampleRate, int bitPerSample, + int channelCount, TINT32 sampleCount, + void *buffer, bool signedSample) { + TSoundTrackP st; + int type = bitPerSample + channelCount; + switch (type) { + case TRK_M8: + if (signedSample) + st = new TSoundTrackMono8Signed(sampleRate, channelCount, sampleCount, + (TMono8SignedSample *)buffer, 0); + else + st = new TSoundTrackMono8Unsigned(sampleRate, channelCount, sampleCount, + (TMono8UnsignedSample *)buffer, 0); + break; + case TRK_S8: + if (signedSample) + st = new TSoundTrackStereo8Signed(sampleRate, channelCount, sampleCount, + (TStereo8SignedSample *)buffer, 0); + else + st = new TSoundTrackStereo8Unsigned(sampleRate, channelCount, sampleCount, + (TStereo8UnsignedSample *)buffer, 0); + break; + + case TRK_M16: + st = new TSoundTrackMono16(sampleRate, channelCount, sampleCount, + (TMono16Sample *)buffer, 0); + break; + + case TRK_S16: + st = new TSoundTrackStereo16(sampleRate, channelCount, sampleCount, + (TStereo16Sample *)buffer, 0); + break; + + case TRK_M24: + st = new TSoundTrackMono24(sampleRate, channelCount, sampleCount, + (TMono24Sample *)buffer, 0); + break; + + case TRK_S24: + st = new TSoundTrackStereo24(sampleRate, channelCount, sampleCount, + (TStereo24Sample *)buffer, 0); + break; + + default: + std::string s; + s = "Type " + std::to_string(sampleRate) + " Hz " + + std::to_string(bitPerSample) + " bits "; + if (channelCount == 1) + s += "mono: "; + else + s += "stereo: "; + s += "Unsupported\n"; + + throw TException(s); + } + + return st; } //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrack::create(const TSoundTrackFormat &format, TINT32 sampleCount, void *buffer) -{ - return TSoundTrack::create( - (int)format.m_sampleRate, - format.m_bitPerSample, - format.m_channelCount, - sampleCount, - buffer, - format.m_signedSample); +TSoundTrackP TSoundTrack::create(const TSoundTrackFormat &format, + TINT32 sampleCount, void *buffer) { + return TSoundTrack::create((int)format.m_sampleRate, format.m_bitPerSample, + format.m_channelCount, sampleCount, buffer, + format.m_signedSample); } //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrack::create(const TSoundTrackFormat &format, TINT32 sampleCount) -{ - return TSoundTrack::create( - (int)format.m_sampleRate, - format.m_bitPerSample, - format.m_channelCount, - sampleCount, - format.m_signedSample); +TSoundTrackP TSoundTrack::create(const TSoundTrackFormat &format, + TINT32 sampleCount) { + return TSoundTrack::create((int)format.m_sampleRate, format.m_bitPerSample, + format.m_channelCount, sampleCount, + format.m_signedSample); } //------------------------------------------------------------------------------ -TINT32 TSoundTrack::secondsToSamples(double s) const -{ - double dsamp = s * m_sampleRate; - TINT32 lsamp = (TINT32)dsamp; - if ((double)lsamp < dsamp - TConsts::epsilon) - lsamp++; - return lsamp; +TINT32 TSoundTrack::secondsToSamples(double s) const { + double dsamp = s * m_sampleRate; + TINT32 lsamp = (TINT32)dsamp; + if ((double)lsamp < dsamp - TConsts::epsilon) lsamp++; + return lsamp; } //------------------------------------------------------------------------------ -double TSoundTrack::samplesToSeconds(TINT32 f) const -{ - return f / (double)m_sampleRate; +double TSoundTrack::samplesToSeconds(TINT32 f) const { + return f / (double)m_sampleRate; } //============================================================================== -bool TSoundTrackFormat::operator==(const TSoundTrackFormat &rhs) -{ - return (m_sampleRate == rhs.m_sampleRate && - m_bitPerSample == rhs.m_bitPerSample && - m_channelCount == rhs.m_channelCount && - m_signedSample == rhs.m_signedSample); +bool TSoundTrackFormat::operator==(const TSoundTrackFormat &rhs) { + return (m_sampleRate == rhs.m_sampleRate && + m_bitPerSample == rhs.m_bitPerSample && + m_channelCount == rhs.m_channelCount && + m_signedSample == rhs.m_signedSample); } //------------------------------------------------------------------------------ -bool TSoundTrackFormat::operator!=(const TSoundTrackFormat &rhs) -{ - return !operator==(rhs); +bool TSoundTrackFormat::operator!=(const TSoundTrackFormat &rhs) { + return !operator==(rhs); } //============================================================================== -double TSoundTrack::getDuration() const -{ - return samplesToSeconds(m_sampleCount); +double TSoundTrack::getDuration() const { + return samplesToSeconds(m_sampleCount); } //------------------------------------------------------------------------------ -TSoundTrackFormat TSoundTrack::getFormat() const -{ - return TSoundTrackFormat( - getSampleRate(), - getBitPerSample(), - getChannelCount(), - isSampleSigned()); +TSoundTrackFormat TSoundTrack::getFormat() const { + return TSoundTrackFormat(getSampleRate(), getBitPerSample(), + getChannelCount(), isSampleSigned()); } //------------------------------------------------------------------------------ -TSoundTrackP TSoundTrack::extract(double t0, double t1) -{ - return extract(secondsToSamples(t0), secondsToSamples(t1)); +TSoundTrackP TSoundTrack::extract(double t0, double t1) { + return extract(secondsToSamples(t0), secondsToSamples(t1)); } //------------------------------------------------------------------------------ -void TSoundTrack::copy(const TSoundTrackP &src, double dst_t0) -{ - copy(src, secondsToSamples(dst_t0)); +void TSoundTrack::copy(const TSoundTrackP &src, double dst_t0) { + copy(src, secondsToSamples(dst_t0)); } //------------------------------------------------------------------------------ -void TSoundTrack::blank(double t0, double t1) -{ - blank(secondsToSamples(t0), secondsToSamples(t1)); +void TSoundTrack::blank(double t0, double t1) { + blank(secondsToSamples(t0), secondsToSamples(t1)); } //------------------------------------------------------------------------------ -double TSoundTrack::getPressure(double second, TSound::Channel chan) const -{ - return getPressure(secondsToSamples(second), chan); +double TSoundTrack::getPressure(double second, TSound::Channel chan) const { + return getPressure(secondsToSamples(second), chan); } //------------------------------------------------------------------------------ -void TSoundTrack::getMinMaxPressure( - double t0, double t1, TSound::Channel chan, - double &min, double &max) const -{ - getMinMaxPressure(secondsToSamples(t0), secondsToSamples(t1), chan, min, max); +void TSoundTrack::getMinMaxPressure(double t0, double t1, TSound::Channel chan, + double &min, double &max) const { + getMinMaxPressure(secondsToSamples(t0), secondsToSamples(t1), chan, min, max); } //------------------------------------------------------------------------------ -void TSoundTrack::getMinMaxPressure(TSound::Channel chan, double &min, double &max) const -{ - getMinMaxPressure(0, (TINT32)(getSampleCount() - 1), chan, min, max); +void TSoundTrack::getMinMaxPressure(TSound::Channel chan, double &min, + double &max) const { + getMinMaxPressure(0, (TINT32)(getSampleCount() - 1), chan, min, max); } //------------------------------------------------------------------------------ -double TSoundTrack::getMaxPressure(double t0, double t1, TSound::Channel chan) const -{ - return getMaxPressure(secondsToSamples(t0), secondsToSamples(t1), chan); +double TSoundTrack::getMaxPressure(double t0, double t1, + TSound::Channel chan) const { + return getMaxPressure(secondsToSamples(t0), secondsToSamples(t1), chan); } //------------------------------------------------------------------------------ -double TSoundTrack::getMaxPressure(TSound::Channel chan) const -{ - return getMaxPressure(0, (TINT32)(getSampleCount() - 1), chan); +double TSoundTrack::getMaxPressure(TSound::Channel chan) const { + return getMaxPressure(0, (TINT32)(getSampleCount() - 1), chan); } //------------------------------------------------------------------------------ -double TSoundTrack::getMinPressure(double t0, double t1, TSound::Channel chan) const -{ - return getMinPressure(secondsToSamples(t0), secondsToSamples(t1), chan); +double TSoundTrack::getMinPressure(double t0, double t1, + TSound::Channel chan) const { + return getMinPressure(secondsToSamples(t0), secondsToSamples(t1), chan); } //------------------------------------------------------------------------------ -double TSoundTrack::getMinPressure(TSound::Channel chan) const -{ - return getMinPressure(0, (TINT32)(getSampleCount() - 1), chan); +double TSoundTrack::getMinPressure(TSound::Channel chan) const { + return getMinPressure(0, (TINT32)(getSampleCount() - 1), chan); } //------------------------------------------------------------------------------ diff --git a/toonz/sources/common/tsound/tsound_io.cpp b/toonz/sources/common/tsound/tsound_io.cpp index 349879e..0418551 100644 --- a/toonz/sources/common/tsound/tsound_io.cpp +++ b/toonz/sources/common/tsound/tsound_io.cpp @@ -14,9 +14,7 @@ std::map SoundTrackWriterTable; //----------------------------------------------------------- TSoundTrackReader::TSoundTrackReader(const TFilePath &fp) - : TSmartObject(m_classCode), m_path(fp) -{ -} + : TSmartObject(m_classCode), m_path(fp) {} //----------------------------------------------------------- @@ -24,27 +22,25 @@ TSoundTrackReader::~TSoundTrackReader() {} //=========================================================== -TSoundTrackReaderP::TSoundTrackReaderP(const TFilePath &path) -{ - QString type = QString::fromStdString(toLower(path.getType())); - std::map::iterator it; - it = SoundTrackReaderTable.find(type); - if (it != SoundTrackReaderTable.end()) { - m_pointer = it->second(path); - assert(m_pointer); - m_pointer->addRef(); - } else { - m_pointer = 0; - throw TException(path.getWideString() + L": soundtrack reader not implemented"); - } +TSoundTrackReaderP::TSoundTrackReaderP(const TFilePath &path) { + QString type = QString::fromStdString(toLower(path.getType())); + std::map::iterator it; + it = SoundTrackReaderTable.find(type); + if (it != SoundTrackReaderTable.end()) { + m_pointer = it->second(path); + assert(m_pointer); + m_pointer->addRef(); + } else { + m_pointer = 0; + throw TException(path.getWideString() + + L": soundtrack reader not implemented"); + } } //=========================================================== TSoundTrackWriter::TSoundTrackWriter(const TFilePath &fp) - : TSmartObject(m_classCode), m_path(fp) -{ -} + : TSmartObject(m_classCode), m_path(fp) {} //----------------------------------------------------------- @@ -52,19 +48,19 @@ TSoundTrackWriter::~TSoundTrackWriter() {} //=========================================================== -TSoundTrackWriterP::TSoundTrackWriterP(const TFilePath &path) -{ - QString type = QString::fromStdString(toLower(path.getType())); - std::map::iterator it; - it = SoundTrackWriterTable.find(type); - if (it != SoundTrackWriterTable.end()) { - m_pointer = it->second(path); - assert(m_pointer); - m_pointer->addRef(); - } else { - m_pointer = 0; - throw TException(path.getWideString() + L"soundtrack writer not implemented"); - } +TSoundTrackWriterP::TSoundTrackWriterP(const TFilePath &path) { + QString type = QString::fromStdString(toLower(path.getType())); + std::map::iterator it; + it = SoundTrackWriterTable.find(type); + if (it != SoundTrackWriterTable.end()) { + m_pointer = it->second(path); + assert(m_pointer); + m_pointer->addRef(); + } else { + m_pointer = 0; + throw TException(path.getWideString() + + L"soundtrack writer not implemented"); + } } //============================================================ @@ -73,38 +69,34 @@ TSoundTrackWriterP::TSoundTrackWriterP(const TFilePath &path) // //============================================================ -bool TSoundTrackReader::load(const TFilePath &path, TSoundTrackP &st) -{ - st = TSoundTrackReaderP(path)->load(); - return st; +bool TSoundTrackReader::load(const TFilePath &path, TSoundTrackP &st) { + st = TSoundTrackReaderP(path)->load(); + return st; } //----------------------------------------------------------- -void TSoundTrackReader::getSupportedFormats(QStringList &names) -{ - for (std::map::iterator it = SoundTrackReaderTable.begin(); - it != SoundTrackReaderTable.end(); - ++it) { - names.push_back(it->first); - } +void TSoundTrackReader::getSupportedFormats(QStringList &names) { + for (std::map::iterator it = + SoundTrackReaderTable.begin(); + it != SoundTrackReaderTable.end(); ++it) { + names.push_back(it->first); + } } //----------------------------------------------------------- -bool TSoundTrackWriter::save(const TFilePath &path, const TSoundTrackP &st) -{ - return TSoundTrackWriterP(path)->save(st); +bool TSoundTrackWriter::save(const TFilePath &path, const TSoundTrackP &st) { + return TSoundTrackWriterP(path)->save(st); } //----------------------------------------------------------- -void TSoundTrackWriter::getSupportedFormats(QStringList &names) -{ - for (std::map::iterator it = SoundTrackWriterTable.begin(); - it != SoundTrackWriterTable.end(); - ++it) { - names.push_back(it->first); - } +void TSoundTrackWriter::getSupportedFormats(QStringList &names) { + for (std::map::iterator it = + SoundTrackWriterTable.begin(); + it != SoundTrackWriterTable.end(); ++it) { + names.push_back(it->first); + } } //=========================================================== @@ -113,18 +105,14 @@ void TSoundTrackWriter::getSupportedFormats(QStringList &names) // //=========================================================== -void TSoundTrackReader::define( - QString extension, - TSoundTrackReaderCreateProc *proc) -{ - SoundTrackReaderTable[extension] = proc; +void TSoundTrackReader::define(QString extension, + TSoundTrackReaderCreateProc *proc) { + SoundTrackReaderTable[extension] = proc; } //----------------------------------------------------------- -void TSoundTrackWriter::define( - QString extension, - TSoundTrackWriterCreateProc *proc) -{ - SoundTrackWriterTable[extension] = proc; +void TSoundTrackWriter::define(QString extension, + TSoundTrackWriterCreateProc *proc) { + SoundTrackWriterTable[extension] = proc; } diff --git a/toonz/sources/common/tsound/tsound_l.cpp b/toonz/sources/common/tsound/tsound_l.cpp index f922ff3..340096f 100644 --- a/toonz/sources/common/tsound/tsound_l.cpp +++ b/toonz/sources/common/tsound/tsound_l.cpp @@ -17,11 +17,10 @@ #include #include -//using namespace std; +// using namespace std; -//forward declaration -namespace -{ +// forward declaration +namespace { int openMixer(); int getCurrentRecordSource(int mixer); bool writeVolume(int volume, int mixer, int indexDev); @@ -37,43 +36,34 @@ string parseError(int error); // i valori del volume e per selezionare il dispositivo da // cui registrare e ascoltare -class SmartWatch -{ - struct timeval m_start_tv; - TINT32 m_totalus; - bool m_stopped; +class SmartWatch { + struct timeval m_start_tv; + TINT32 m_totalus; + bool m_stopped; public: - SmartWatch() : m_totalus(0), m_stopped(true) - { - timerclear(&m_start_tv); - } - void start() - { - m_stopped = false; - gettimeofday(&m_start_tv, 0); - } - void stop() - { - m_stopped = true; - struct timeval tv; - gettimeofday(&tv, 0); - m_totalus = (tv.tv_sec - m_start_tv.tv_sec) * 1000000 + (tv.tv_usec - m_start_tv.tv_usec); - } - double getTotalTime() - { - if (!m_stopped) //questa e' una porcata! - { - stop(); - m_stopped = false; - } - return m_totalus / 1000.; - } - - void addDelay(double ms) - { - m_start_tv.tv_usec += (long)(ms * 1000.); - } + SmartWatch() : m_totalus(0), m_stopped(true) { timerclear(&m_start_tv); } + void start() { + m_stopped = false; + gettimeofday(&m_start_tv, 0); + } + void stop() { + m_stopped = true; + struct timeval tv; + gettimeofday(&tv, 0); + m_totalus = (tv.tv_sec - m_start_tv.tv_sec) * 1000000 + + (tv.tv_usec - m_start_tv.tv_usec); + } + double getTotalTime() { + if (!m_stopped) // questa e' una porcata! + { + stop(); + m_stopped = false; + } + return m_totalus / 1000.; + } + + void addDelay(double ms) { m_start_tv.tv_usec += (long)(ms * 1000.); } }; //====================================================================== @@ -81,1446 +71,1480 @@ public: // CLASSI PER IL PLAYBACK //====================================================================== //====================================================================== -class TSoundOutputDeviceImp -{ +class TSoundOutputDeviceImp { private: - static int m_count; + static int m_count; public: - int m_dev; - bool m_stopped; - bool m_isPlaying; - bool m_looped; - TSoundTrackFormat m_currentFormat; - std::set m_supportedRate; - static std::multimap m_supportFormats; - - typedef pair WaitPair; - vector m_waitingTracks; - std::set m_listeners; - TThread::Executor m_executor; - TThread::Mutex m_mutex; - - TSoundOutputDeviceImp() - : m_dev(-1), m_stopped(false), m_isPlaying(false), m_looped(false), m_supportedRate() - { - /* - if (m_count != 0) - throw TException("unable to create second instance of TSoundOutputDeviceImp"); + int m_dev; + bool m_stopped; + bool m_isPlaying; + bool m_looped; + TSoundTrackFormat m_currentFormat; + std::set m_supportedRate; + static std::multimap m_supportFormats; + + typedef pair WaitPair; + vector m_waitingTracks; + std::set m_listeners; + TThread::Executor m_executor; + TThread::Mutex m_mutex; + + TSoundOutputDeviceImp() + : m_dev(-1) + , m_stopped(false) + , m_isPlaying(false) + , m_looped(false) + , m_supportedRate() { + /* +if (m_count != 0) +throw TException("unable to create second instance of TSoundOutputDeviceImp"); */ - ++m_count; - checkSupportedFormat(); - }; - - ~TSoundOutputDeviceImp() { --m_count; }; - - bool doOpenDevice(); - bool doCloseDevice(); - bool verifyRate(); - void insertAllRate(); - void checkSupportedFormat(); - bool isSupportFormat(const TSoundTrackFormat &fmt); - void setFormat(const TSoundTrackFormat &fmt); + ++m_count; + checkSupportedFormat(); + }; + + ~TSoundOutputDeviceImp() { --m_count; }; + + bool doOpenDevice(); + bool doCloseDevice(); + bool verifyRate(); + void insertAllRate(); + void checkSupportedFormat(); + bool isSupportFormat(const TSoundTrackFormat &fmt); + void setFormat(const TSoundTrackFormat &fmt); }; int TSoundOutputDeviceImp::m_count = 0; -std::multimap TSoundOutputDeviceImp::m_supportFormats; +std::multimap + TSoundOutputDeviceImp::m_supportFormats; //---------------------------------------------------------------------------- -bool TSoundOutputDeviceImp::doOpenDevice() -{ - if (m_dev >= 0) - return true; - - TThread::ScopedLock sl(m_mutex); - m_dev = open("/dev/dsp", O_WRONLY, 0); - if (m_dev < 0) { - string errMsg = strerror(errno); - throw TSoundDeviceException( - TSoundDeviceException::UnableOpenDevice, errMsg + " /dev/dsp" - /*"Unable to open device /dev/dsp; check permissions"*/); - } - - //le chiamate a questa ioctl sono state commentate perche' pag 36 doc OSS - //"this ioctl stop the device immadiately and returns it to a state where it - //can accept new parameters. It Should not be called after opening the device - //as it may cause unwanted side effect in his situation. require to abort play - //or secord.Generally recommended to open and close device after using the RESET" - //ioctl(m_dev, SNDCTL_DSP_RESET,0); - - // N.B. e' bene che la dimensione sia piccola cosi' l'attesa, in seguito - // alla richiesta di stop, - // e' minore in questo caso vogliamo 32 frammenti ognuno di 256 byte - // Se non chiamata questa ioctl il device la calcola per conto suo - // ma alcune volte la dimensione dei frammenti potrebbe essere eccessiva e - // creare dei click e dei silenzi in attesi ad esempio nel playback dentro - // zcomp, quindi e' meglio settarla. 32 rappresenta il numero di frammenti - // di solito e' documentato che 2 siano sufficienti ma potrebbero essere pochi - // soprattutto se si interagisce con altre console - //int fraginfo = ( 32<<16)|8; - - int fraginfo = 0xffffffff; - if (ioctl(m_dev, SNDCTL_DSP_SETFRAGMENT, &fraginfo) == -1) - perror("SETFRAGMENT"); - //if(fraginfo != ((32<<16)|8)) - //std::cout << std::hex << fraginfo<= 0) return true; + + TThread::ScopedLock sl(m_mutex); + m_dev = open("/dev/dsp", O_WRONLY, 0); + if (m_dev < 0) { + string errMsg = strerror(errno); + throw TSoundDeviceException( + TSoundDeviceException::UnableOpenDevice, errMsg + " /dev/dsp" + /*"Unable to open device /dev/dsp; check permissions"*/); + } + + // le chiamate a questa ioctl sono state commentate perche' pag 36 doc OSS + //"this ioctl stop the device immadiately and returns it to a state where + //it + // can accept new parameters. It Should not be called after opening the device + // as it may cause unwanted side effect in his situation. require to abort + // play + // or secord.Generally recommended to open and close device after using the + // RESET" + // ioctl(m_dev, SNDCTL_DSP_RESET,0); + + // N.B. e' bene che la dimensione sia piccola cosi' l'attesa, in seguito + // alla richiesta di stop, + // e' minore in questo caso vogliamo 32 frammenti ognuno di 256 byte + // Se non chiamata questa ioctl il device la calcola per conto suo + // ma alcune volte la dimensione dei frammenti potrebbe essere eccessiva e + // creare dei click e dei silenzi in attesi ad esempio nel playback dentro + // zcomp, quindi e' meglio settarla. 32 rappresenta il numero di frammenti + // di solito e' documentato che 2 siano sufficienti ma potrebbero essere pochi + // soprattutto se si interagisce con altre console + // int fraginfo = ( 32<<16)|8; + + int fraginfo = 0xffffffff; + if (ioctl(m_dev, SNDCTL_DSP_SETFRAGMENT, &fraginfo) == -1) + perror("SETFRAGMENT"); + // if(fraginfo != ((32<<16)|8)) + // std::cout << std::hex << fraginfo<::iterator it; - - for (it = m_supportedRate.begin(); - it != m_supportedRate.end(); ++it) { - int sampleRate = *it; - if (ioctl(m_dev, SNDCTL_DSP_SPEED, &sampleRate) == -1) - throw TSoundDeviceException( - TSoundDeviceException::UnablePrepare, - "Failed setting the specified sample rate aaaa"); - if (sampleRate != *it) - m_supportedRate.erase(*it); - } - if (m_supportedRate.end() == m_supportedRate.begin()) - return false; - - return true; +bool TSoundOutputDeviceImp::verifyRate() { + std::set::iterator it; + + for (it = m_supportedRate.begin(); it != m_supportedRate.end(); ++it) { + int sampleRate = *it; + if (ioctl(m_dev, SNDCTL_DSP_SPEED, &sampleRate) == -1) + throw TSoundDeviceException( + TSoundDeviceException::UnablePrepare, + "Failed setting the specified sample rate aaaa"); + if (sampleRate != *it) m_supportedRate.erase(*it); + } + if (m_supportedRate.end() == m_supportedRate.begin()) return false; + + return true; } //------------------------------------------------------------------------------ -void TSoundOutputDeviceImp::checkSupportedFormat() -{ - if (!m_supportFormats.empty()) - return; - int test_formats[] = { - AFMT_U8, - AFMT_S8, - AFMT_S16_LE, - AFMT_S16_BE, - /* // servono per supportare traccie a 24 e 32 bit ma non compaiono in - // nessun file linux/soundcard.h in distribuzione sulle macchine che abbiamo - // il che fa pensare che non sono supportati ancora - AFMT_S32_LE, - AFMT_S32_BE, +void TSoundOutputDeviceImp::checkSupportedFormat() { + if (!m_supportFormats.empty()) return; + int test_formats[] = { + AFMT_U8, AFMT_S8, AFMT_S16_LE, AFMT_S16_BE, + /* // servono per supportare traccie a 24 e 32 bit ma non compaiono in +// nessun file linux/soundcard.h in distribuzione sulle macchine che abbiamo +// il che fa pensare che non sono supportati ancora +AFMT_S32_LE, +AFMT_S32_BE, */ - 0}; - - int test_channels[] = { - 1, - 2, - 0}; - - TUINT32 test_sample_rates[] = { - 8000, - 11025, - 16000, - 22050, - 32000, - 44100, - 48000, - 0}; - - // Open the device nonblocking, so the open call returns immediately. - if (m_dev) - if ((m_dev = open("/dev/dsp", O_WRONLY | O_NONBLOCK)) == -1) { - /* - m_dev = -1; - string errMsg = strerror(errno); - throw TSoundDeviceException( - TSoundDeviceException::UnableOpenDevice, errMsg + " /dev/dsp\n: impossible check supported formats"); - */ - return; - } - - int mask; - // Querying hardware supported formats. - if (ioctl(m_dev, SNDCTL_DSP_GETFMTS, &mask) == -1) { - /* - throw TSoundDeviceException( - TSoundDeviceException::UnsupportedFormat, - "Getting supported formats failed."); - */ - return; - } else { - for (int i = 0; test_formats[i] != 0; i++) { - // Test all the formats in test_formats which are supported by the hardware. - - if (mask & test_formats[i]) { - // Test the format only if it is supported by the hardware. - // Note: We also could test formats that are not supported by the hardware. - // In some cases there exist OSS software converter, so that some formats - // work but are not reported by the above SNDCTL_DSP_GETFMTS. - - int fmt = test_formats[i]; - // Try to set the format... - if (ioctl(m_dev, SNDCTL_DSP_SETFMT, &fmt) == -1) - continue; //gli altri formati potrebbero essere supportati - else { - // and always check the variable after doing an ioctl! - if (fmt == test_formats[i]) { - // Test the supported channel numbers for this format. - // Note: If you need a channel that is not tested here, simply add it to - // the definition of the array test_channels in this file. - for (int j = 0; test_channels[j] != 0; j++) { - int test_channel = test_channels[j]; - - // Try to set the channel number. - if (ioctl(m_dev, SNDCTL_DSP_CHANNELS, &test_channel) == -1) - continue; //altri canali potrebbero essere supportati - else { - if (test_channel == test_channels[j]) { - // Last step: Test the supported sample rates for the current channel number - // and format. - // Note: If you need a sample rate that is not tested here, simply add it to - // the definition of the array test_sample_rates in this file. - for (int k = 0; test_sample_rates[k] != 0; k++) { - TUINT32 test_rate = test_sample_rates[k]; - if (ioctl(m_dev, SNDCTL_DSP_SPEED, &test_rate) == -1) - continue; //altri rates ppotrebbero essere supportati - else { - bool sign = true; - int bits; - - if (fmt == AFMT_U8 || fmt == AFMT_S8) { - bits = 8; - if (fmt == AFMT_U8) - sign = false; - } else if (fmt == AFMT_S16_LE || fmt == AFMT_S16_BE) - bits = 16; - /*// vedi commento alla variabile test_formats - else if(fmt == AFMT_S32_LE || fmt == AFMT_S32_BE) - bits = 24; - */ - // Add it to the format in the input property. - //std::cout << test_rate << " " <::iterator it; - pair::iterator, std::multimap::iterator> findRange; - findRange = m_supportFormats.equal_range(fmt.m_sampleRate); - - it = findRange.first; - for (; it != findRange.second; ++it) { - assert(it->first == fmt.m_sampleRate); - if (it->second == fmt) { - return true; - } - } - return false; +bool TSoundOutputDeviceImp::isSupportFormat(const TSoundTrackFormat &fmt) { + try { + if (m_supportFormats.empty()) checkSupportedFormat(); + } catch (TSoundDeviceException &e) { + return false; + } + + std::multimap::iterator it; + pair::iterator, + std::multimap::iterator> + findRange; + findRange = m_supportFormats.equal_range(fmt.m_sampleRate); + + it = findRange.first; + for (; it != findRange.second; ++it) { + assert(it->first == fmt.m_sampleRate); + if (it->second == fmt) { + return true; + } + } + return false; } //------------------------------------------------------------------------------ -void TSoundOutputDeviceImp::setFormat(const TSoundTrackFormat &fmt) -{ - int bps, ch, status; - TUINT32 sampleRate; - - ch = fmt.m_channelCount; - sampleRate = fmt.m_sampleRate; - - if (m_dev == -1) - if (!doOpenDevice()) - return; - - if (fmt.m_bitPerSample == 8) { - if (fmt.m_signedSample) - bps = AFMT_S8; - else - bps = AFMT_U8; - } else if (fmt.m_bitPerSample == 16) { - bps = AFMT_S16_NE; - } - int bitPerSample = bps; - - status = ioctl(m_dev, SNDCTL_DSP_SETFMT, &bps); - if (status == -1) { - throw TSoundDeviceException( - TSoundDeviceException::UnablePrepare, - "Failed setting the specified number of bits"); - } - - status = ioctl(m_dev, SNDCTL_DSP_CHANNELS, &ch); - if (status == -1) - throw TSoundDeviceException( - TSoundDeviceException::UnablePrepare, - "Failed setting the specified number of channel"); - - if (ioctl(m_dev, SNDCTL_DSP_SPEED, &sampleRate) == -1) - throw TSoundDeviceException( - TSoundDeviceException::UnablePrepare, - "Failed setting the specified sample rate"); - - if (ch != fmt.m_channelCount || bps != bitPerSample || sampleRate != fmt.m_sampleRate) { - doCloseDevice(); - m_currentFormat = TSoundTrackFormat(); - return; - } - m_currentFormat = fmt; +void TSoundOutputDeviceImp::setFormat(const TSoundTrackFormat &fmt) { + int bps, ch, status; + TUINT32 sampleRate; + + ch = fmt.m_channelCount; + sampleRate = fmt.m_sampleRate; + + if (m_dev == -1) + if (!doOpenDevice()) return; + + if (fmt.m_bitPerSample == 8) { + if (fmt.m_signedSample) + bps = AFMT_S8; + else + bps = AFMT_U8; + } else if (fmt.m_bitPerSample == 16) { + bps = AFMT_S16_NE; + } + int bitPerSample = bps; + + status = ioctl(m_dev, SNDCTL_DSP_SETFMT, &bps); + if (status == -1) { + throw TSoundDeviceException(TSoundDeviceException::UnablePrepare, + "Failed setting the specified number of bits"); + } + + status = ioctl(m_dev, SNDCTL_DSP_CHANNELS, &ch); + if (status == -1) + throw TSoundDeviceException( + TSoundDeviceException::UnablePrepare, + "Failed setting the specified number of channel"); + + if (ioctl(m_dev, SNDCTL_DSP_SPEED, &sampleRate) == -1) + throw TSoundDeviceException(TSoundDeviceException::UnablePrepare, + "Failed setting the specified sample rate"); + + if (ch != fmt.m_channelCount || bps != bitPerSample || + sampleRate != fmt.m_sampleRate) { + doCloseDevice(); + m_currentFormat = TSoundTrackFormat(); + return; + } + m_currentFormat = fmt; } //============================================================================== -class TPlayTask : public TThread::Runnable -{ - SmartWatch *m_stopWatch; +class TPlayTask : public TThread::Runnable { + SmartWatch *m_stopWatch; public: - TSoundOutputDeviceImp *m_devImp; - TSoundTrackP m_sndtrack; - static int m_skipBytes; + TSoundOutputDeviceImp *m_devImp; + TSoundTrackP m_sndtrack; + static int m_skipBytes; - TPlayTask(TSoundOutputDeviceImp *devImp, const TSoundTrackP &st); + TPlayTask(TSoundOutputDeviceImp *devImp, const TSoundTrackP &st); - ~TPlayTask() { delete m_stopWatch; } + ~TPlayTask() { delete m_stopWatch; } - void run(); - void run2(); + void run(); + void run2(); }; //------------------------------------------------------------------------------- TPlayTask::TPlayTask(TSoundOutputDeviceImp *devImp, const TSoundTrackP &st) - : Runnable(), m_stopWatch(new SmartWatch), m_devImp(devImp), m_sndtrack(st) -{ - if (st->getFormat() != m_devImp->m_currentFormat) - if (m_devImp->doCloseDevice()) - m_devImp->setFormat(st->getFormat()); - m_stopWatch->start(); + : Runnable() + , m_stopWatch(new SmartWatch) + , m_devImp(devImp) + , m_sndtrack(st) { + if (st->getFormat() != m_devImp->m_currentFormat) + if (m_devImp->doCloseDevice()) m_devImp->setFormat(st->getFormat()); + m_stopWatch->start(); }; //------------------------------------------------------------------------------- -void TPlayTask::run() -{ - int bytesLeft = m_sndtrack->getSampleCount() * m_sndtrack->getSampleSize(); - char *buf = (char *)m_sndtrack->getRawData(); - int done = 0; - int written = 0; - TINT32 sampleSize = (TINT32)m_sndtrack->getSampleSize(); - const double msToBytes = sampleSize * m_sndtrack->getSampleRate() / 1000.; - - TThread::milestone(); - double startupDelay = m_stopWatch->getTotalTime(); - //std::cout << "ritardo iniziale " << startupDelay << std::endl; - int miss = 0; - m_stopWatch->start(); //e' meglio ignorare il ritardo iniziale - if (done > 0) { - m_stopWatch->addDelay(((done / sampleSize) * 1000) / double(m_sndtrack->getSampleRate())); - } - int auxbuffersize = 0; - int preWrittenBytes = 0; - int bytesToSkipNext; - TSoundTrackP src = TSoundTrack::create(m_sndtrack->getFormat(), 1); - TSoundTrackP dst = src; - TSoundTrackP newSrc = src; - try { - do //gia' tracce accodate - { - bool changeSnd = false; - do //c'e' il flag loop settato - { - while ((bytesLeft > 0)) { - TThread::milestone(); - changeSnd = false; - audio_buf_info info; - TINT32 bytesToWrite = 0; - TINT32 bytesToWriteNext = 0; - double samplesDone = done / (double)sampleSize; - double trackTime = (samplesDone * 1000.) / m_sndtrack->getSampleRate(); - double curTime = m_stopWatch->getTotalTime(); - double delta = curTime - trackTime; - - /* - delta - == 0 sync - < 0 audio piu' veloce del tempo di playback --> simuliamo un ritardo con un continue; - > 0 audio piu' lento del playback -> skip una porzione di audio - */ - - const double minDelay = -10; - const double maxDelay = 0; - //if (delta>maxDelay) - //std::cout << "buffer underrun:" << delta << std::endl; - //std::cout << "buffer " << (deltamaxDelay?"underrun":"sync") << " " << delta<< std::endl; - - if (delta < minDelay) //overrun - { - //std::cout << "out of sync -> audio troppo veloce" << std::endl; - continue; - } - - if (ioctl(m_devImp->m_dev, SNDCTL_DSP_GETOSPACE, &info) == -1) { - miss++; - break; - } - - int fragmentsFree_bytes = info.fragsize * info.fragments; - if (fragmentsFree_bytes == 0) { - //std::cout << "no bytes left on device" << std::endl; - continue; - } - - int bytesToSkip = 0; - bytesToSkipNext = 0; - if (delta > maxDelay) //underrun - { - //std::cout << "out of sync -> audio troppo lento"< la corrente traccia non basta per avere il sync - bytesLeft -= bytesToSkip; - done += bytesToSkip; - - bytesToWrite = tmin(bytesLeft, fragmentsFree_bytes); - bytesToWriteNext = fragmentsFree_bytes - bytesToWrite; - assert(bytesToWrite >= 0); - assert(bytesToWriteNext >= 0); - - if (bytesToWrite % info.fragsize != 0) { //cerco di gestire il write di un frammento non intero - auxbuffersize = ((bytesToWrite / info.fragsize) + 1) * info.fragsize; - } else - auxbuffersize = 0; - - //--------------write - if (bytesToSkipNext == 0) //la corrente traccia basta per lo skip - { - std::cout << " QUI 0 " << std::endl; - dst = m_sndtrack->extract(done / sampleSize, (done + bytesToWrite) / sampleSize); - if (bytesToSkip != 0) { - //costruisco traccia su cui fare il crossfade - //utilizzo il contenuto della traccia di crossfade - dst = TSop::crossFade(0.2, src, dst); - } - char *auxbuf = new char[fragmentsFree_bytes]; - memcpy(auxbuf, (char *)dst->getRawData(), bytesToWrite); - if (bytesToWriteNext != 0) { - int offset = bytesToWrite; - if (m_devImp->m_looped) { - offset += bytesToWriteNext; - preWrittenBytes = bytesToWriteNext; - memcpy(auxbuf + offset, buf, preWrittenBytes); - newSrc = m_sndtrack->extract(preWrittenBytes / sampleSize, preWrittenBytes / sampleSize); - std::cout << " QUI 1" << std::endl; - } else { - while (!m_devImp->m_waitingTracks.empty()) { - TSoundTrackP st = m_devImp->m_waitingTracks[0].first; - int count = st->getSampleCount() * sampleSize; - if (bytesToWriteNext >= count) { - char *buffer = (char *)st->getRawData(); - memcpy(auxbuf + offset, buffer, count); - bytesToWriteNext -= count; - offset += count; - std::cout << " QUI 2" << std::endl; - if (m_devImp->m_waitingTracks[0].second) { - m_devImp->m_looped = m_devImp->m_waitingTracks[0].second; - m_devImp->m_waitingTracks.erase(m_devImp->m_waitingTracks.begin()); - newSrc = m_sndtrack->extract(count / sampleSize, count / sampleSize); - m_sndtrack = st; - preWrittenBytes = 0; - std::cout << " QUI 3" << std::endl; - break; - } - m_devImp->m_waitingTracks.erase(m_devImp->m_waitingTracks.begin()); - newSrc = m_sndtrack->extract(count / sampleSize, count / sampleSize); - } else { - m_sndtrack = st; - m_devImp->m_looped = m_devImp->m_waitingTracks[0].second; - preWrittenBytes = bytesToWriteNext; - buf = (char *)m_sndtrack->getRawData(); - memcpy(auxbuf + offset, buf, bytesToWriteNext); - m_devImp->m_waitingTracks.erase(m_devImp->m_waitingTracks.begin()); - newSrc = m_sndtrack->extract((bytesToWriteNext) / sampleSize, (bytesToWriteNext) / sampleSize); - std::cout << " QUI 4" << std::endl; - break; - } - } //end while - } - - if (fragmentsFree_bytes > offset) { - std::cout << " QUI 5" << std::endl; - int val = m_sndtrack->isSampleSigned() ? 0 : 127; - memset(auxbuf + offset, val, fragmentsFree_bytes - offset); // ci metto silenzio - newSrc = TSoundTrack::create(m_sndtrack->getFormat(), 1); - } - } - - written = write(m_devImp->m_dev, auxbuf, fragmentsFree_bytes); - delete[] auxbuf; - } else //devo skippare anche parte di una delle seguenti - { - std::cout << " QUI 6a" << std::endl; - assert(bytesToWriteNext > 0); - assert(bytesToWriteNext == fragmentsFree_bytes - bytesToWrite); - assert(bytesToWrite == 0); - assert(bytesToSkip != 0); - char *auxbuf = new char[fragmentsFree_bytes]; - //memcpy(auxbuf, buf+done, bytesToWrite); - //TSoundTrackP subCross = m_sndtrack->extract((done+bytesToWrite)/sampleSize, (done+bytesToWrite)/sampleSize); - //togli quelle da skippare - int backupSkipNext = bytesToSkipNext; - while (!m_devImp->m_waitingTracks.empty()) { - TSoundTrackP st = m_devImp->m_waitingTracks[0].first; - int count = st->getSampleCount() * sampleSize; - if (bytesToSkipNext >= count) { - std::cout << " QUI 6b" << std::endl; - m_devImp->m_waitingTracks.erase(m_devImp->m_waitingTracks.begin()); - bytesToSkipNext -= count; - } else { - std::cout << " QUI 7" << std::endl; - m_devImp->m_waitingTracks.erase(m_devImp->m_waitingTracks.begin()); - m_devImp->m_looped = m_devImp->m_waitingTracks[0].second; - m_sndtrack = st; - buf = (char *)st->getRawData(); - break; - } - } - //scrivi byteWriteNext fai crossfade e cerca quella successiva - //con cui riempire - TINT32 displacement = 0; //deve essere in munero di campioni non bytes - dst = TSoundTrack::create(m_sndtrack->getFormat(), (fragmentsFree_bytes - bytesToWrite) / sampleSize); - int count = m_sndtrack->getSampleCount() * sampleSize; - if (count >= bytesToSkipNext + bytesToWriteNext) //la traccia trovata e' suff sia per skippare che per scrivere - { - preWrittenBytes = bytesToSkipNext + bytesToWriteNext; - dst = m_sndtrack->extract(bytesToSkipNext / sampleSize, preWrittenBytes / sampleSize); - newSrc = m_sndtrack->extract(preWrittenBytes / sampleSize, preWrittenBytes / sampleSize); - } else //non e' suff per scrivere - { - dst->copy(m_sndtrack->extract(bytesToSkipNext / sampleSize, m_sndtrack->getSampleCount() - 1), 0); - displacement = m_sndtrack->getSampleCount() - bytesToSkipNext / sampleSize; - bytesToWriteNext -= displacement * sampleSize; - while (!m_devImp->m_waitingTracks.empty()) { - TSoundTrackP st = m_devImp->m_waitingTracks[0].first; - int count = st->getSampleCount() * sampleSize; - if (bytesToWriteNext >= count) { - std::cout << " QUI 8" << std::endl; - dst->copy(st, displacement); - bytesToWriteNext -= count; - displacement += count; - if (m_devImp->m_waitingTracks[0].second) { - std::cout << " QUI 9" << std::endl; - m_devImp->m_looped = m_devImp->m_waitingTracks[0].second; - m_devImp->m_waitingTracks.erase(m_devImp->m_waitingTracks.begin()); - newSrc = m_sndtrack->extract(count / sampleSize, count / sampleSize); - m_sndtrack = st; - break; - } - m_devImp->m_waitingTracks.erase(m_devImp->m_waitingTracks.begin()); - newSrc = m_sndtrack->extract(count / sampleSize, count / sampleSize); - } else { - std::cout << " QUI 10" << std::endl; - dst->copy(st->extract(0L, bytesToWriteNext / sampleSize), displacement); - m_sndtrack = st; - m_devImp->m_looped = m_devImp->m_waitingTracks[0].second; - preWrittenBytes = bytesToWriteNext; - done = preWrittenBytes; - bytesLeft = m_sndtrack->getSampleCount() * sampleSize - done; - buf = (char *)m_sndtrack->getRawData(); - m_devImp->m_waitingTracks.erase(m_devImp->m_waitingTracks.begin()); - newSrc = m_sndtrack->extract(preWrittenBytes / sampleSize, preWrittenBytes / sampleSize); - break; - } - } - bytesToSkipNext = backupSkipNext; - } - - TSoundTrackP st = TSop::crossFade(0.2, src, dst); - memcpy(auxbuf + bytesToWrite, (char *)st->getRawData(), fragmentsFree_bytes - bytesToWrite); - - //devo ricercare quella giusta che non deve essere skippata - //ma sostitutita come traccia corrente - //devo fare un cross fade - written = write(m_devImp->m_dev, auxbuf, fragmentsFree_bytes); - delete[] auxbuf; - } - //----------- end write - src = newSrc; - if (written == -1) - break; - std::cout << written << " " << (bytesToWrite + preWrittenBytes) << std::endl; - if (written != bytesToWrite + preWrittenBytes) - break; - std::cout << " update done 2" << std::endl; - bytesLeft -= written; - done += written; - } //chiudo il while((bytesLeft > 0)) - std::cout << " QUI 11" << std::endl; - done = preWrittenBytes + bytesToSkipNext; - written = 0; - bytesLeft = m_sndtrack->getSampleCount() * sampleSize - done; - m_stopWatch->start(); - if (done > 0) { - m_stopWatch->addDelay(((done / m_sndtrack->getSampleSize()) * 1000) / double(m_sndtrack->getSampleRate())); - } - preWrittenBytes = 0; - } while (m_devImp->m_looped || changeSnd); - - if (m_devImp->m_waitingTracks.empty()) - break; - m_sndtrack = m_devImp->m_waitingTracks[0].first; - m_devImp->m_looped = m_devImp->m_waitingTracks[0].second; - m_devImp->m_waitingTracks.erase(m_devImp->m_waitingTracks.begin()); - bytesLeft = m_sndtrack->getSampleCount() * m_sndtrack->getSampleSize(); - buf = (char *)m_sndtrack->getRawData(); - done = 0; - written = 0; - - m_stopWatch->start(); //ignoro il ritardo iniziale - if (done > 0) { - m_stopWatch->addDelay(((done / m_sndtrack->getSampleSize()) * 1000) / double(m_sndtrack->getSampleRate())); - } - } while (true); //ci sono gia' tracce accodate - - if (!m_devImp->m_waitingTracks.empty()) { - m_devImp->m_looped = m_devImp->m_waitingTracks[0].second; - m_devImp->m_executor.addTask(new TPlayTask(m_devImp, m_devImp->m_waitingTracks[0].first)); - m_devImp->m_waitingTracks.erase(m_devImp->m_waitingTracks.begin()); - //std::cout<<"OPS ..... erase 4"<m_dev != -1) { - if (ioctl(m_devImp->m_dev, SNDCTL_DSP_SYNC) == -1) { - std::cout << "unable to sync! " << std::endl; - throw TException("unable to sync!"); - } - - m_devImp->m_isPlaying = false; - m_devImp->m_stopped = true; - m_devImp->m_looped = false; - - //std::cout << "miss = " << miss << std::endl; - } - } catch (TThread::Interrupt &e) { - std::cout << "Play interrupted " << e.getMessage() << std::endl; - m_devImp->m_isPlaying = false; - m_devImp->m_stopped = true; - m_devImp->m_looped = false; - } catch (TException &e) { - std::cout << "esco dal play " << e.getMessage() << std::endl; - m_devImp->m_isPlaying = false; - m_devImp->m_stopped = true; - m_devImp->m_looped = false; - } +void TPlayTask::run() { + int bytesLeft = m_sndtrack->getSampleCount() * m_sndtrack->getSampleSize(); + char *buf = (char *)m_sndtrack->getRawData(); + int done = 0; + int written = 0; + TINT32 sampleSize = (TINT32)m_sndtrack->getSampleSize(); + const double msToBytes = sampleSize * m_sndtrack->getSampleRate() / 1000.; + + TThread::milestone(); + double startupDelay = m_stopWatch->getTotalTime(); + // std::cout << "ritardo iniziale " << startupDelay << std::endl; + int miss = 0; + m_stopWatch->start(); // e' meglio ignorare il ritardo iniziale + if (done > 0) { + m_stopWatch->addDelay(((done / sampleSize) * 1000) / + double(m_sndtrack->getSampleRate())); + } + int auxbuffersize = 0; + int preWrittenBytes = 0; + int bytesToSkipNext; + TSoundTrackP src = TSoundTrack::create(m_sndtrack->getFormat(), 1); + TSoundTrackP dst = src; + TSoundTrackP newSrc = src; + try { + do // gia' tracce accodate + { + bool changeSnd = false; + do // c'e' il flag loop settato + { + while ((bytesLeft > 0)) { + TThread::milestone(); + changeSnd = false; + audio_buf_info info; + TINT32 bytesToWrite = 0; + TINT32 bytesToWriteNext = 0; + double samplesDone = done / (double)sampleSize; + double trackTime = + (samplesDone * 1000.) / m_sndtrack->getSampleRate(); + double curTime = m_stopWatch->getTotalTime(); + double delta = curTime - trackTime; + + /* + delta + == 0 sync + < 0 audio piu' veloce del tempo + di playback --> simuliamo un ritardo con un continue; + > 0 audio piu' lento del playback -> + skip una porzione di audio + */ + + const double minDelay = -10; + const double maxDelay = 0; + // if (delta>maxDelay) + // std::cout << "buffer underrun:" << delta << std::endl; + // std::cout << "buffer " << + // (deltamaxDelay?"underrun":"sync") << " " + // << delta<< std::endl; + + if (delta < minDelay) // overrun + { + // std::cout << "out of sync -> audio troppo veloce" << std::endl; + continue; + } + + if (ioctl(m_devImp->m_dev, SNDCTL_DSP_GETOSPACE, &info) == -1) { + miss++; + break; + } + + int fragmentsFree_bytes = info.fragsize * info.fragments; + if (fragmentsFree_bytes == 0) { + // std::cout << "no bytes left on device" << std::endl; + continue; + } + + int bytesToSkip = 0; + bytesToSkipNext = 0; + if (delta > maxDelay) // underrun + { + // std::cout << "out of sync -> audio troppo lento"< la corrente traccia non + // basta per avere il sync + bytesLeft -= bytesToSkip; + done += bytesToSkip; + + bytesToWrite = tmin(bytesLeft, fragmentsFree_bytes); + bytesToWriteNext = fragmentsFree_bytes - bytesToWrite; + assert(bytesToWrite >= 0); + assert(bytesToWriteNext >= 0); + + if (bytesToWrite % info.fragsize != + 0) { // cerco di gestire il write di un frammento non intero + auxbuffersize = + ((bytesToWrite / info.fragsize) + 1) * info.fragsize; + } else + auxbuffersize = 0; + + //--------------write + if (bytesToSkipNext == 0) // la corrente traccia basta per lo skip + { + std::cout << " QUI 0 " << std::endl; + dst = m_sndtrack->extract(done / sampleSize, + (done + bytesToWrite) / sampleSize); + if (bytesToSkip != 0) { + // costruisco traccia su cui fare il crossfade + // utilizzo il contenuto della traccia di crossfade + dst = TSop::crossFade(0.2, src, dst); + } + char *auxbuf = new char[fragmentsFree_bytes]; + memcpy(auxbuf, (char *)dst->getRawData(), bytesToWrite); + if (bytesToWriteNext != 0) { + int offset = bytesToWrite; + if (m_devImp->m_looped) { + offset += bytesToWriteNext; + preWrittenBytes = bytesToWriteNext; + memcpy(auxbuf + offset, buf, preWrittenBytes); + newSrc = m_sndtrack->extract(preWrittenBytes / sampleSize, + preWrittenBytes / sampleSize); + std::cout << " QUI 1" << std::endl; + } else { + while (!m_devImp->m_waitingTracks.empty()) { + TSoundTrackP st = m_devImp->m_waitingTracks[0].first; + int count = st->getSampleCount() * sampleSize; + if (bytesToWriteNext >= count) { + char *buffer = (char *)st->getRawData(); + memcpy(auxbuf + offset, buffer, count); + bytesToWriteNext -= count; + offset += count; + std::cout << " QUI 2" << std::endl; + if (m_devImp->m_waitingTracks[0].second) { + m_devImp->m_looped = m_devImp->m_waitingTracks[0].second; + m_devImp->m_waitingTracks.erase( + m_devImp->m_waitingTracks.begin()); + newSrc = m_sndtrack->extract(count / sampleSize, + count / sampleSize); + m_sndtrack = st; + preWrittenBytes = 0; + std::cout << " QUI 3" << std::endl; + break; + } + m_devImp->m_waitingTracks.erase( + m_devImp->m_waitingTracks.begin()); + newSrc = m_sndtrack->extract(count / sampleSize, + count / sampleSize); + } else { + m_sndtrack = st; + m_devImp->m_looped = m_devImp->m_waitingTracks[0].second; + preWrittenBytes = bytesToWriteNext; + buf = (char *)m_sndtrack->getRawData(); + memcpy(auxbuf + offset, buf, bytesToWriteNext); + m_devImp->m_waitingTracks.erase( + m_devImp->m_waitingTracks.begin()); + newSrc = + m_sndtrack->extract((bytesToWriteNext) / sampleSize, + (bytesToWriteNext) / sampleSize); + std::cout << " QUI 4" << std::endl; + break; + } + } // end while + } + + if (fragmentsFree_bytes > offset) { + std::cout << " QUI 5" << std::endl; + int val = m_sndtrack->isSampleSigned() ? 0 : 127; + memset(auxbuf + offset, val, + fragmentsFree_bytes - offset); // ci metto silenzio + newSrc = TSoundTrack::create(m_sndtrack->getFormat(), 1); + } + } + + written = write(m_devImp->m_dev, auxbuf, fragmentsFree_bytes); + delete[] auxbuf; + } else // devo skippare anche parte di una delle seguenti + { + std::cout << " QUI 6a" << std::endl; + assert(bytesToWriteNext > 0); + assert(bytesToWriteNext == fragmentsFree_bytes - bytesToWrite); + assert(bytesToWrite == 0); + assert(bytesToSkip != 0); + char *auxbuf = new char[fragmentsFree_bytes]; + // memcpy(auxbuf, buf+done, bytesToWrite); + // TSoundTrackP subCross = + // m_sndtrack->extract((done+bytesToWrite)/sampleSize, + // (done+bytesToWrite)/sampleSize); + // togli quelle da skippare + int backupSkipNext = bytesToSkipNext; + while (!m_devImp->m_waitingTracks.empty()) { + TSoundTrackP st = m_devImp->m_waitingTracks[0].first; + int count = st->getSampleCount() * sampleSize; + if (bytesToSkipNext >= count) { + std::cout << " QUI 6b" << std::endl; + m_devImp->m_waitingTracks.erase( + m_devImp->m_waitingTracks.begin()); + bytesToSkipNext -= count; + } else { + std::cout << " QUI 7" << std::endl; + m_devImp->m_waitingTracks.erase( + m_devImp->m_waitingTracks.begin()); + m_devImp->m_looped = m_devImp->m_waitingTracks[0].second; + m_sndtrack = st; + buf = (char *)st->getRawData(); + break; + } + } + // scrivi byteWriteNext fai crossfade e cerca quella successiva + // con cui riempire + TINT32 displacement = + 0; // deve essere in munero di campioni non bytes + dst = TSoundTrack::create( + m_sndtrack->getFormat(), + (fragmentsFree_bytes - bytesToWrite) / sampleSize); + int count = m_sndtrack->getSampleCount() * sampleSize; + if (count >= bytesToSkipNext + bytesToWriteNext) // la traccia + // trovata e' suff + // sia per + // skippare che + // per scrivere + { + preWrittenBytes = bytesToSkipNext + bytesToWriteNext; + dst = m_sndtrack->extract(bytesToSkipNext / sampleSize, + preWrittenBytes / sampleSize); + newSrc = m_sndtrack->extract(preWrittenBytes / sampleSize, + preWrittenBytes / sampleSize); + } else // non e' suff per scrivere + { + dst->copy(m_sndtrack->extract(bytesToSkipNext / sampleSize, + m_sndtrack->getSampleCount() - 1), + 0); + displacement = + m_sndtrack->getSampleCount() - bytesToSkipNext / sampleSize; + bytesToWriteNext -= displacement * sampleSize; + while (!m_devImp->m_waitingTracks.empty()) { + TSoundTrackP st = m_devImp->m_waitingTracks[0].first; + int count = st->getSampleCount() * sampleSize; + if (bytesToWriteNext >= count) { + std::cout << " QUI 8" << std::endl; + dst->copy(st, displacement); + bytesToWriteNext -= count; + displacement += count; + if (m_devImp->m_waitingTracks[0].second) { + std::cout << " QUI 9" << std::endl; + m_devImp->m_looped = m_devImp->m_waitingTracks[0].second; + m_devImp->m_waitingTracks.erase( + m_devImp->m_waitingTracks.begin()); + newSrc = m_sndtrack->extract(count / sampleSize, + count / sampleSize); + m_sndtrack = st; + break; + } + m_devImp->m_waitingTracks.erase( + m_devImp->m_waitingTracks.begin()); + newSrc = m_sndtrack->extract(count / sampleSize, + count / sampleSize); + } else { + std::cout << " QUI 10" << std::endl; + dst->copy(st->extract(0L, bytesToWriteNext / sampleSize), + displacement); + m_sndtrack = st; + m_devImp->m_looped = m_devImp->m_waitingTracks[0].second; + preWrittenBytes = bytesToWriteNext; + done = preWrittenBytes; + bytesLeft = m_sndtrack->getSampleCount() * sampleSize - done; + buf = (char *)m_sndtrack->getRawData(); + m_devImp->m_waitingTracks.erase( + m_devImp->m_waitingTracks.begin()); + newSrc = m_sndtrack->extract(preWrittenBytes / sampleSize, + preWrittenBytes / sampleSize); + break; + } + } + bytesToSkipNext = backupSkipNext; + } + + TSoundTrackP st = TSop::crossFade(0.2, src, dst); + memcpy(auxbuf + bytesToWrite, (char *)st->getRawData(), + fragmentsFree_bytes - bytesToWrite); + + // devo ricercare quella giusta che non deve essere skippata + // ma sostitutita come traccia corrente + // devo fare un cross fade + written = write(m_devImp->m_dev, auxbuf, fragmentsFree_bytes); + delete[] auxbuf; + } + //----------- end write + src = newSrc; + if (written == -1) break; + std::cout << written << " " << (bytesToWrite + preWrittenBytes) + << std::endl; + if (written != bytesToWrite + preWrittenBytes) break; + std::cout << " update done 2" << std::endl; + bytesLeft -= written; + done += written; + } // chiudo il while((bytesLeft > 0)) + std::cout << " QUI 11" << std::endl; + done = preWrittenBytes + bytesToSkipNext; + written = 0; + bytesLeft = m_sndtrack->getSampleCount() * sampleSize - done; + m_stopWatch->start(); + if (done > 0) { + m_stopWatch->addDelay(((done / m_sndtrack->getSampleSize()) * 1000) / + double(m_sndtrack->getSampleRate())); + } + preWrittenBytes = 0; + } while (m_devImp->m_looped || changeSnd); + + if (m_devImp->m_waitingTracks.empty()) break; + m_sndtrack = m_devImp->m_waitingTracks[0].first; + m_devImp->m_looped = m_devImp->m_waitingTracks[0].second; + m_devImp->m_waitingTracks.erase(m_devImp->m_waitingTracks.begin()); + bytesLeft = m_sndtrack->getSampleCount() * m_sndtrack->getSampleSize(); + buf = (char *)m_sndtrack->getRawData(); + done = 0; + written = 0; + + m_stopWatch->start(); // ignoro il ritardo iniziale + if (done > 0) { + m_stopWatch->addDelay(((done / m_sndtrack->getSampleSize()) * 1000) / + double(m_sndtrack->getSampleRate())); + } + } while (true); // ci sono gia' tracce accodate + + if (!m_devImp->m_waitingTracks.empty()) { + m_devImp->m_looped = m_devImp->m_waitingTracks[0].second; + m_devImp->m_executor.addTask( + new TPlayTask(m_devImp, m_devImp->m_waitingTracks[0].first)); + m_devImp->m_waitingTracks.erase(m_devImp->m_waitingTracks.begin()); + // std::cout<<"OPS ..... erase 4"<m_dev != -1) { + if (ioctl(m_devImp->m_dev, SNDCTL_DSP_SYNC) == -1) { + std::cout << "unable to sync! " << std::endl; + throw TException("unable to sync!"); + } + + m_devImp->m_isPlaying = false; + m_devImp->m_stopped = true; + m_devImp->m_looped = false; + + // std::cout << "miss = " << miss << std::endl; + } + } catch (TThread::Interrupt &e) { + std::cout << "Play interrupted " << e.getMessage() << std::endl; + m_devImp->m_isPlaying = false; + m_devImp->m_stopped = true; + m_devImp->m_looped = false; + } catch (TException &e) { + std::cout << "esco dal play " << e.getMessage() << std::endl; + m_devImp->m_isPlaying = false; + m_devImp->m_stopped = true; + m_devImp->m_looped = false; + } } //------------------------------------------------------------------------------- -void TPlayTask::run2() -{ - int bytesLeft = m_sndtrack->getSampleCount() * m_sndtrack->getSampleSize(); - char *buf = (char *)m_sndtrack->getRawData(); - int done = 0; - int written = 0; - TINT32 sampleSize = (TINT32)m_sndtrack->getSampleSize(); - const double msToBytes = sampleSize * m_sndtrack->getSampleRate() / 1000.; - - TThread::milestone(); - double startupDelay = m_stopWatch->getTotalTime(); - //std::cout << "ritardo iniziale " << startupDelay << std::endl; - int miss = 0; - m_stopWatch->start(); //e' meglio ignorare il ritardo iniziale - if (done > 0) { - m_stopWatch->addDelay(((done / sampleSize) * 1000) / double(m_sndtrack->getSampleRate())); - } - int auxbuffersize = 0; - int preWrittenBytes = 0; - TSoundTrackP src = TSoundTrack::create(m_sndtrack->getFormat(), 1); - TSoundTrackP dst = src; - try { - do //gia' tracce accodate - { - bool changeSnd = false; - do //c'e' il flag loop settato - { - while ((bytesLeft > 0)) { - changeSnd = false; - TThread::milestone(); - audio_buf_info info; - TINT32 bytesToWrite; - double samplesDone = done / (double)sampleSize; - double trackTime = (samplesDone * 1000.) / m_sndtrack->getSampleRate(); - double curTime = m_stopWatch->getTotalTime(); - double delta = curTime - trackTime; - - /* - delta - == 0 sync - < 0 audio piu' veloce del tempo di playback --> simuliamo un ritardo con un continue; - > 0 audio piu' lento del playback -> skip una porzione di audio - */ - - const double minDelay = -10; - const double maxDelay = 0; - //if (delta>maxDelay) - //std::cout << "buffer underrun:" << delta << std::endl; - //std::cout << "buffer " << (deltamaxDelay?"underrun":"sync") << " " << delta<< std::endl; - - if (delta < minDelay) //overrun - { - //std::cout << "out of sync -> audio troppo veloce" << std::endl; - continue; - } - - if (ioctl(m_devImp->m_dev, SNDCTL_DSP_GETOSPACE, &info) == -1) { - miss++; - break; - } - - int fragmentsFree_bytes = info.fragsize * info.fragments; - if (fragmentsFree_bytes == 0) { - //std::cout << "no bytes left on device" << std::endl; - continue; - } - - int bytesToSkip = 0; - int bigSkip = 0; - if (delta > maxDelay) //underrun - { - //std::cout << "out of sync -> audio troppo lento"<m_waitingTracks.empty()) { - TSoundTrackP st = m_devImp->m_waitingTracks[0].first; - int count = st->getSampleCount() * sampleSize; - if (bigSkip >= count) { - m_devImp->m_waitingTracks.erase(m_devImp->m_waitingTracks.begin()); - bigSkip -= count; - } else - break; - } - - preWrittenBytes = 0; - if (auxbuffersize == 0) { - if (bytesToSkip != 0) { - //costruisco traccia su cui fare il crossfade - //utilizzo il contenuto della traccia di crossfade - dst = m_sndtrack->extract(done / sampleSize, (done + bytesToWrite) / sampleSize); - TSoundTrackP st = TSop::crossFade(0.2, src, dst); - char *buffer = (char *)st->getRawData(); - written = write(m_devImp->m_dev, buffer, bytesToWrite); - } else - written = write(m_devImp->m_dev, buf + done, bytesToWrite); - src = m_sndtrack->extract((done + bytesToWrite) / sampleSize, (done + bytesToWrite) / sampleSize); - } else { //auxbuffersize != 0 sse il numero di bytes residui nella traccia e' inferiore alla dimensione del frammento - char *auxbuf = new char[auxbuffersize]; - TSoundTrackP newSrc; - dst = TSoundTrack::create(m_sndtrack->getFormat(), auxbuffersize / sampleSize); - memcpy(auxbuf, buf + done, bytesToWrite); - dst->copy(m_sndtrack->extract(done / sampleSize, (done + bytesToWrite) / sampleSize), 0); - preWrittenBytes = auxbuffersize - bytesToWrite; - if (m_devImp->m_looped) { - memcpy(auxbuf + bytesToWrite, buf, preWrittenBytes); - dst->copy(m_sndtrack->extract(0, preWrittenBytes / sampleSize), bytesToWrite / sampleSize); - newSrc = m_sndtrack->extract(preWrittenBytes / sampleSize, preWrittenBytes / sampleSize); - } else { - newSrc = TSoundTrack::create(m_sndtrack->getFormat(), 1); - static int added = 0; - //se non c'e' alcuna altra traccia o e di diverso format - //riempo il frammento con del silenzio - if (m_devImp->m_waitingTracks.empty() || - (m_sndtrack->getFormat() != m_devImp->m_waitingTracks[0].first->getFormat())) { - int val = m_sndtrack->isSampleSigned() ? 0 : 127; - memset(auxbuf + bytesToWrite, val, preWrittenBytes); // ci metto silenzio - } else - while (true) //ci sono altre tracce accodate - { - TSoundTrackP st = m_devImp->m_waitingTracks[0].first; - int sampleBytes = st->getSampleCount() * st->getSampleSize(); - if (sampleBytes >= preWrittenBytes - added) { - //La traccia ha abbastanza campioni per riempire il frammento - //quindi la sostituisco alla corrente del runnable e continuo - buf = (char *)st->getRawData(); - memcpy(auxbuf + bytesToWrite, buf, preWrittenBytes - added); - m_sndtrack = st; - m_devImp->m_looped = m_devImp->m_waitingTracks[0].second; - m_devImp->m_waitingTracks.erase(m_devImp->m_waitingTracks.begin()); - changeSnd = true; - dst->copy(m_sndtrack->extract(0, (preWrittenBytes - added) / sampleSize), bytesToWrite / sampleSize + added); - newSrc = m_sndtrack->extract((preWrittenBytes - added) / sampleSize, (preWrittenBytes - added) / sampleSize); - break; - } else { //occhio al loop - //La traccia successiva e' piu corta del frammento da riempire quindi - //ce la metto tutta e se non ha il flag di loop settato cerco di aggiungere - //i byte della successiva - memcpy(auxbuf + bytesToWrite, st->getRawData(), sampleBytes); - dst->copy(st->extract(0, st->getSampleCount() - 1), bytesToWrite / sampleSize); - added += st->getSampleCount(); - if (m_devImp->m_waitingTracks[0].second) //e' quella che deve essere in loop - { - buf = (char *)st->getRawData(); - m_sndtrack = st; - m_devImp->m_looped = m_devImp->m_waitingTracks[0].second; - preWrittenBytes = 0; - bytesLeft = 0; - m_devImp->m_waitingTracks.erase(m_devImp->m_waitingTracks.begin()); - changeSnd = true; - break; - } - - //la elimino e vedo se esiste la successiva altrimenti metto campioni "zero" - m_devImp->m_waitingTracks.erase(m_devImp->m_waitingTracks.begin()); - if (!m_devImp->m_waitingTracks.empty()) { - st = m_devImp->m_waitingTracks[0].first; - std::cout << " Traccia con meno campioni cerco la successiva" << std::endl; - } else { - int val = m_sndtrack->isSampleSigned() ? 0 : 127; - memset(auxbuf + bytesToWrite, val, preWrittenBytes - sampleBytes); // ci metto silenzio - std::cout << "OPS ..... silence" << std::endl; - break; - } - } - } //end while(true) - } - //qui andrebbe fatto un cross-fade se c'erano da skippare campioni => bytesToSkip != 0 - if (bytesToSkip != 0) { - TSoundTrackP st = TSop::crossFade(0.2, src, dst); - char *buffer = (char *)st->getRawData(); - written = write(m_devImp->m_dev, buffer, bytesToWrite); - } else - written = write(m_devImp->m_dev, auxbuf, auxbuffersize); - src = newSrc; - auxbuffersize = 0; - delete[] auxbuf; - } - if (written == -1) - break; - if (written != bytesToWrite + preWrittenBytes) - break; - bytesLeft -= written; - done += written; - } //chiudo il while((bytesLeft > 0)) - done = preWrittenBytes; - written = 0; - bytesLeft = m_sndtrack->getSampleCount() * m_sndtrack->getSampleSize() - done; - m_stopWatch->start(); - if (done > 0) { - m_stopWatch->addDelay(((done / m_sndtrack->getSampleSize()) * 1000) / double(m_sndtrack->getSampleRate())); - } - } while (m_devImp->m_looped || changeSnd); - - if (m_devImp->m_waitingTracks.empty()) { - //std::cout<<"OPS ..... non accodato"<m_waitingTracks[0].first; - m_devImp->m_looped = m_devImp->m_waitingTracks[0].second; - m_devImp->m_waitingTracks.erase(m_devImp->m_waitingTracks.begin()); - bytesLeft = m_sndtrack->getSampleCount() * m_sndtrack->getSampleSize(); - buf = (char *)m_sndtrack->getRawData(); - done = 0; - written = 0; - - m_stopWatch->start(); //ignoro il ritardo iniziale - if (done > 0) { - m_stopWatch->addDelay(((done / m_sndtrack->getSampleSize()) * 1000) / double(m_sndtrack->getSampleRate())); - } - } while (true); //ci sono gia' tracce accodate - - if (!m_devImp->m_waitingTracks.empty()) { - m_devImp->m_looped = m_devImp->m_waitingTracks[0].second; - m_devImp->m_executor.addTask(new TPlayTask(m_devImp, m_devImp->m_waitingTracks[0].first)); - m_devImp->m_waitingTracks.erase(m_devImp->m_waitingTracks.begin()); - //std::cout<<"OPS ..... erase 4"<m_dev != -1) { - if (ioctl(m_devImp->m_dev, SNDCTL_DSP_SYNC) == -1) { - std::cout << "unable to sync! " << std::endl; - throw TException("unable to sync!"); - } - - m_devImp->m_isPlaying = false; - m_devImp->m_stopped = true; - m_devImp->m_looped = false; - - //std::cout << "miss = " << miss << std::endl; - } - } catch (TThread::Interrupt &e) { - std::cout << "Play interrupted " << e.getMessage() << std::endl; - m_devImp->m_isPlaying = false; - m_devImp->m_stopped = true; - m_devImp->m_looped = false; - } catch (TException &e) { - std::cout << "esco dal play " << e.getMessage() << std::endl; - m_devImp->m_isPlaying = false; - m_devImp->m_stopped = true; - m_devImp->m_looped = false; - } +void TPlayTask::run2() { + int bytesLeft = m_sndtrack->getSampleCount() * m_sndtrack->getSampleSize(); + char *buf = (char *)m_sndtrack->getRawData(); + int done = 0; + int written = 0; + TINT32 sampleSize = (TINT32)m_sndtrack->getSampleSize(); + const double msToBytes = sampleSize * m_sndtrack->getSampleRate() / 1000.; + + TThread::milestone(); + double startupDelay = m_stopWatch->getTotalTime(); + // std::cout << "ritardo iniziale " << startupDelay << std::endl; + int miss = 0; + m_stopWatch->start(); // e' meglio ignorare il ritardo iniziale + if (done > 0) { + m_stopWatch->addDelay(((done / sampleSize) * 1000) / + double(m_sndtrack->getSampleRate())); + } + int auxbuffersize = 0; + int preWrittenBytes = 0; + TSoundTrackP src = TSoundTrack::create(m_sndtrack->getFormat(), 1); + TSoundTrackP dst = src; + try { + do // gia' tracce accodate + { + bool changeSnd = false; + do // c'e' il flag loop settato + { + while ((bytesLeft > 0)) { + changeSnd = false; + TThread::milestone(); + audio_buf_info info; + TINT32 bytesToWrite; + double samplesDone = done / (double)sampleSize; + double trackTime = + (samplesDone * 1000.) / m_sndtrack->getSampleRate(); + double curTime = m_stopWatch->getTotalTime(); + double delta = curTime - trackTime; + + /* + delta + == 0 sync + < 0 audio piu' veloce del tempo + di playback --> simuliamo un ritardo con un continue; + > 0 audio piu' lento del playback -> + skip una porzione di audio + */ + + const double minDelay = -10; + const double maxDelay = 0; + // if (delta>maxDelay) + // std::cout << "buffer underrun:" << delta << std::endl; + // std::cout << "buffer " << + // (deltamaxDelay?"underrun":"sync") << " " + // << delta<< std::endl; + + if (delta < minDelay) // overrun + { + // std::cout << "out of sync -> audio troppo veloce" << std::endl; + continue; + } + + if (ioctl(m_devImp->m_dev, SNDCTL_DSP_GETOSPACE, &info) == -1) { + miss++; + break; + } + + int fragmentsFree_bytes = info.fragsize * info.fragments; + if (fragmentsFree_bytes == 0) { + // std::cout << "no bytes left on device" << std::endl; + continue; + } + + int bytesToSkip = 0; + int bigSkip = 0; + if (delta > maxDelay) // underrun + { + // std::cout << "out of sync -> audio troppo lento"<m_waitingTracks.empty()) { + TSoundTrackP st = m_devImp->m_waitingTracks[0].first; + int count = st->getSampleCount() * sampleSize; + if (bigSkip >= count) { + m_devImp->m_waitingTracks.erase( + m_devImp->m_waitingTracks.begin()); + bigSkip -= count; + } else + break; + } + + preWrittenBytes = 0; + if (auxbuffersize == 0) { + if (bytesToSkip != 0) { + // costruisco traccia su cui fare il crossfade + // utilizzo il contenuto della traccia di crossfade + dst = m_sndtrack->extract(done / sampleSize, + (done + bytesToWrite) / sampleSize); + TSoundTrackP st = TSop::crossFade(0.2, src, dst); + char *buffer = (char *)st->getRawData(); + written = write(m_devImp->m_dev, buffer, bytesToWrite); + } else + written = write(m_devImp->m_dev, buf + done, bytesToWrite); + src = m_sndtrack->extract((done + bytesToWrite) / sampleSize, + (done + bytesToWrite) / sampleSize); + } else { // auxbuffersize != 0 sse il numero di bytes residui nella + // traccia e' inferiore alla dimensione del frammento + char *auxbuf = new char[auxbuffersize]; + TSoundTrackP newSrc; + dst = TSoundTrack::create(m_sndtrack->getFormat(), + auxbuffersize / sampleSize); + memcpy(auxbuf, buf + done, bytesToWrite); + dst->copy(m_sndtrack->extract(done / sampleSize, + (done + bytesToWrite) / sampleSize), + 0); + preWrittenBytes = auxbuffersize - bytesToWrite; + if (m_devImp->m_looped) { + memcpy(auxbuf + bytesToWrite, buf, preWrittenBytes); + dst->copy(m_sndtrack->extract(0, preWrittenBytes / sampleSize), + bytesToWrite / sampleSize); + newSrc = m_sndtrack->extract(preWrittenBytes / sampleSize, + preWrittenBytes / sampleSize); + } else { + newSrc = TSoundTrack::create(m_sndtrack->getFormat(), 1); + static int added = 0; + // se non c'e' alcuna altra traccia o e di diverso format + // riempo il frammento con del silenzio + if (m_devImp->m_waitingTracks.empty() || + (m_sndtrack->getFormat() != + m_devImp->m_waitingTracks[0].first->getFormat())) { + int val = m_sndtrack->isSampleSigned() ? 0 : 127; + memset(auxbuf + bytesToWrite, val, + preWrittenBytes); // ci metto silenzio + } else + while (true) // ci sono altre tracce accodate + { + TSoundTrackP st = m_devImp->m_waitingTracks[0].first; + int sampleBytes = st->getSampleCount() * st->getSampleSize(); + if (sampleBytes >= preWrittenBytes - added) { + // La traccia ha abbastanza campioni per riempire il + // frammento + // quindi la sostituisco alla corrente del runnable e + // continuo + buf = (char *)st->getRawData(); + memcpy(auxbuf + bytesToWrite, buf, preWrittenBytes - added); + m_sndtrack = st; + m_devImp->m_looped = m_devImp->m_waitingTracks[0].second; + m_devImp->m_waitingTracks.erase( + m_devImp->m_waitingTracks.begin()); + changeSnd = true; + dst->copy(m_sndtrack->extract( + 0, (preWrittenBytes - added) / sampleSize), + bytesToWrite / sampleSize + added); + newSrc = m_sndtrack->extract( + (preWrittenBytes - added) / sampleSize, + (preWrittenBytes - added) / sampleSize); + break; + } else { // occhio al loop + // La traccia successiva e' piu corta del frammento da + // riempire quindi + // ce la metto tutta e se non ha il flag di loop settato + // cerco di aggiungere + // i byte della successiva + memcpy(auxbuf + bytesToWrite, st->getRawData(), + sampleBytes); + dst->copy(st->extract(0, st->getSampleCount() - 1), + bytesToWrite / sampleSize); + added += st->getSampleCount(); + if (m_devImp->m_waitingTracks[0] + .second) // e' quella che deve essere in loop + { + buf = (char *)st->getRawData(); + m_sndtrack = st; + m_devImp->m_looped = m_devImp->m_waitingTracks[0].second; + preWrittenBytes = 0; + bytesLeft = 0; + m_devImp->m_waitingTracks.erase( + m_devImp->m_waitingTracks.begin()); + changeSnd = true; + break; + } + + // la elimino e vedo se esiste la successiva altrimenti + // metto campioni "zero" + m_devImp->m_waitingTracks.erase( + m_devImp->m_waitingTracks.begin()); + if (!m_devImp->m_waitingTracks.empty()) { + st = m_devImp->m_waitingTracks[0].first; + std::cout + << " Traccia con meno campioni cerco la successiva" + << std::endl; + } else { + int val = m_sndtrack->isSampleSigned() ? 0 : 127; + memset( + auxbuf + bytesToWrite, val, + preWrittenBytes - sampleBytes); // ci metto silenzio + std::cout << "OPS ..... silence" << std::endl; + break; + } + } + } // end while(true) + } + // qui andrebbe fatto un cross-fade se c'erano da skippare campioni + // => bytesToSkip != 0 + if (bytesToSkip != 0) { + TSoundTrackP st = TSop::crossFade(0.2, src, dst); + char *buffer = (char *)st->getRawData(); + written = write(m_devImp->m_dev, buffer, bytesToWrite); + } else + written = write(m_devImp->m_dev, auxbuf, auxbuffersize); + src = newSrc; + auxbuffersize = 0; + delete[] auxbuf; + } + if (written == -1) break; + if (written != bytesToWrite + preWrittenBytes) break; + bytesLeft -= written; + done += written; + } // chiudo il while((bytesLeft > 0)) + done = preWrittenBytes; + written = 0; + bytesLeft = + m_sndtrack->getSampleCount() * m_sndtrack->getSampleSize() - done; + m_stopWatch->start(); + if (done > 0) { + m_stopWatch->addDelay(((done / m_sndtrack->getSampleSize()) * 1000) / + double(m_sndtrack->getSampleRate())); + } + } while (m_devImp->m_looped || changeSnd); + + if (m_devImp->m_waitingTracks.empty()) { + // std::cout<<"OPS ..... non accodato"<m_waitingTracks[0].first; + m_devImp->m_looped = m_devImp->m_waitingTracks[0].second; + m_devImp->m_waitingTracks.erase(m_devImp->m_waitingTracks.begin()); + bytesLeft = m_sndtrack->getSampleCount() * m_sndtrack->getSampleSize(); + buf = (char *)m_sndtrack->getRawData(); + done = 0; + written = 0; + + m_stopWatch->start(); // ignoro il ritardo iniziale + if (done > 0) { + m_stopWatch->addDelay(((done / m_sndtrack->getSampleSize()) * 1000) / + double(m_sndtrack->getSampleRate())); + } + } while (true); // ci sono gia' tracce accodate + + if (!m_devImp->m_waitingTracks.empty()) { + m_devImp->m_looped = m_devImp->m_waitingTracks[0].second; + m_devImp->m_executor.addTask( + new TPlayTask(m_devImp, m_devImp->m_waitingTracks[0].first)); + m_devImp->m_waitingTracks.erase(m_devImp->m_waitingTracks.begin()); + // std::cout<<"OPS ..... erase 4"<m_dev != -1) { + if (ioctl(m_devImp->m_dev, SNDCTL_DSP_SYNC) == -1) { + std::cout << "unable to sync! " << std::endl; + throw TException("unable to sync!"); + } + + m_devImp->m_isPlaying = false; + m_devImp->m_stopped = true; + m_devImp->m_looped = false; + + // std::cout << "miss = " << miss << std::endl; + } + } catch (TThread::Interrupt &e) { + std::cout << "Play interrupted " << e.getMessage() << std::endl; + m_devImp->m_isPlaying = false; + m_devImp->m_stopped = true; + m_devImp->m_looped = false; + } catch (TException &e) { + std::cout << "esco dal play " << e.getMessage() << std::endl; + m_devImp->m_isPlaying = false; + m_devImp->m_stopped = true; + m_devImp->m_looped = false; + } } //============================================================================== -TSoundOutputDevice::TSoundOutputDevice() : m_imp(new TSoundOutputDeviceImp) -{ - if (m_imp->doOpenDevice()) { - m_imp->insertAllRate(); - try { - if (!m_imp->verifyRate()) - throw TSoundDeviceException( - TSoundDeviceException::UnablePrepare, - "No default samplerate are supported"); - } catch (TSoundDeviceException &e) { - throw TSoundDeviceException(e.getType(), e.getMessage()); - } - m_imp->doCloseDevice(); - } +TSoundOutputDevice::TSoundOutputDevice() : m_imp(new TSoundOutputDeviceImp) { + if (m_imp->doOpenDevice()) { + m_imp->insertAllRate(); + try { + if (!m_imp->verifyRate()) + throw TSoundDeviceException(TSoundDeviceException::UnablePrepare, + "No default samplerate are supported"); + } catch (TSoundDeviceException &e) { + throw TSoundDeviceException(e.getType(), e.getMessage()); + } + m_imp->doCloseDevice(); + } } //------------------------------------------------------------------------------ -TSoundOutputDevice::~TSoundOutputDevice() -{ - close(); -} +TSoundOutputDevice::~TSoundOutputDevice() { close(); } //------------------------------------------------------------------------------ -bool TSoundOutputDevice::installed() -{ - bool ret = false; - int dev = ::open("/dev/dsp", O_WRONLY, 0); - if (dev >= 0) { - ret = true; - ::close(dev); - } - return ret; +bool TSoundOutputDevice::installed() { + bool ret = false; + int dev = ::open("/dev/dsp", O_WRONLY, 0); + if (dev >= 0) { + ret = true; + ::close(dev); + } + return ret; } //------------------------------------------------------------------------------ -bool TSoundOutputDevice::open(const TSoundTrackP &st) -{ - m_imp->m_currentFormat = st->getFormat(); - try { - m_imp->doOpenDevice(); - } catch (TSoundDeviceException &e) { - throw TSoundDeviceException(e.getType(), e.getMessage()); - } - return true; +bool TSoundOutputDevice::open(const TSoundTrackP &st) { + m_imp->m_currentFormat = st->getFormat(); + try { + m_imp->doOpenDevice(); + } catch (TSoundDeviceException &e) { + throw TSoundDeviceException(e.getType(), e.getMessage()); + } + return true; } //------------------------------------------------------------------------------ -bool TSoundOutputDevice::close() -{ - stop(); - if (m_imp->m_dev != -1) { - bool closed = m_imp->doCloseDevice(); - if (!closed) - throw TSoundDeviceException( - TSoundDeviceException::UnableCloseDevice, - "Error during the closing of the output device"); - } - return true; +bool TSoundOutputDevice::close() { + stop(); + if (m_imp->m_dev != -1) { + bool closed = m_imp->doCloseDevice(); + if (!closed) + throw TSoundDeviceException( + TSoundDeviceException::UnableCloseDevice, + "Error during the closing of the output device"); + } + return true; } //------------------------------------------------------------------------------ -void TSoundOutputDevice::attach(TSoundOutputDeviceListener *listener) -{ - m_imp->m_listeners.insert(listener); +void TSoundOutputDevice::attach(TSoundOutputDeviceListener *listener) { + m_imp->m_listeners.insert(listener); } //------------------------------------------------------------------------------ -void TSoundOutputDevice::detach(TSoundOutputDeviceListener *listener) -{ - m_imp->m_listeners.erase(listener); +void TSoundOutputDevice::detach(TSoundOutputDeviceListener *listener) { + m_imp->m_listeners.erase(listener); } //------------------------------------------------------------------------------ -void TSoundOutputDevice::play(const TSoundTrackP &st, TINT32 s0, TINT32 s1, bool loop, bool scrubbing) -{ - assert((scrubbing && !loop) || !scrubbing); - if (!st->getSampleCount()) - return; - - TThread::ScopedLock sl(m_imp->m_mutex); - if (m_imp->m_looped) - throw TSoundDeviceException( - TSoundDeviceException::Busy, - "Unable to queue another playback when the sound player is looping"); - - TSoundTrackFormat format = st->getFormat(); - if (!m_imp->isSupportFormat(format)) { - throw TSoundDeviceException( - TSoundDeviceException::UnsupportedFormat, - "Unsupported format for playback"); - } - - if (m_imp->m_isPlaying) { - assert(s1 >= s0); - TSoundTrackP subTrack = st->extract(s0, s1); - m_imp->m_waitingTracks.push_back(std::make_pair(subTrack, loop)); - //std::cout<<"Sono in pushback"<m_dev == -1)) - try { - if (m_imp->doOpenDevice()) - m_imp->setFormat(format); - } catch (TSoundDeviceException &e) { - m_imp->doCloseDevice(); - throw TSoundDeviceException(e.getType(), e.getMessage()); - } - - m_imp->m_isPlaying = true; - m_imp->m_stopped = false; - m_imp->m_looped = loop; - //m_imp->m_currentFormat = st->getFormat(); - - assert(s1 >= s0); - TSoundTrackP subTrack = st->extract(s0, s1); - - m_imp->m_executor.addTask(new TPlayTask(m_imp, subTrack)); +void TSoundOutputDevice::play(const TSoundTrackP &st, TINT32 s0, TINT32 s1, + bool loop, bool scrubbing) { + assert((scrubbing && !loop) || !scrubbing); + if (!st->getSampleCount()) return; + + TThread::ScopedLock sl(m_imp->m_mutex); + if (m_imp->m_looped) + throw TSoundDeviceException( + TSoundDeviceException::Busy, + "Unable to queue another playback when the sound player is looping"); + + TSoundTrackFormat format = st->getFormat(); + if (!m_imp->isSupportFormat(format)) { + throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat, + "Unsupported format for playback"); + } + + if (m_imp->m_isPlaying) { + assert(s1 >= s0); + TSoundTrackP subTrack = st->extract(s0, s1); + m_imp->m_waitingTracks.push_back(std::make_pair(subTrack, loop)); + // std::cout<<"Sono in pushback"<m_dev == -1)) try { + if (m_imp->doOpenDevice()) m_imp->setFormat(format); + } catch (TSoundDeviceException &e) { + m_imp->doCloseDevice(); + throw TSoundDeviceException(e.getType(), e.getMessage()); + } + + m_imp->m_isPlaying = true; + m_imp->m_stopped = false; + m_imp->m_looped = loop; + // m_imp->m_currentFormat = st->getFormat(); + + assert(s1 >= s0); + TSoundTrackP subTrack = st->extract(s0, s1); + + m_imp->m_executor.addTask(new TPlayTask(m_imp, subTrack)); } //------------------------------------------------------------------------------ -void TSoundOutputDevice::stop() -{ - TThread::ScopedLock sl(m_imp->m_mutex); - if (!m_imp->m_isPlaying) - return; - m_imp->m_executor.cancel(); - ioctl(m_imp->m_dev, SNDCTL_DSP_POST, 0); - m_imp->m_isPlaying = false; - m_imp->m_stopped = true; - m_imp->m_looped = false; - m_imp->m_waitingTracks.clear(); +void TSoundOutputDevice::stop() { + TThread::ScopedLock sl(m_imp->m_mutex); + if (!m_imp->m_isPlaying) return; + m_imp->m_executor.cancel(); + ioctl(m_imp->m_dev, SNDCTL_DSP_POST, 0); + m_imp->m_isPlaying = false; + m_imp->m_stopped = true; + m_imp->m_looped = false; + m_imp->m_waitingTracks.clear(); } //------------------------------------------------------------------------------ -double TSoundOutputDevice::getVolume() -{ - int mixer; - if ((mixer = openMixer()) < 0) - throw TSoundDeviceException( - TSoundDeviceException::NoMixer, - "Can't open the mixer device"); - - int devmask; - if (ioctl(mixer, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) { - ::close(mixer); - throw TSoundDeviceException( - TSoundDeviceException::NoMixer, - "Error in ioctl with mixer device"); - } - - int recmask; - if (ioctl(mixer, SOUND_MIXER_READ_RECMASK, &recmask) == -1) { - ::close(mixer); - throw TSoundDeviceException( - TSoundDeviceException::NoMixer, - "Error in ioctl with mixer device"); - } - - int stereo; - if (ioctl(mixer, SOUND_MIXER_READ_STEREODEVS, &stereo) == -1) { - ::close(mixer); - throw TSoundDeviceException( - TSoundDeviceException::NoMixer, - "Error in ioctl with mixer device"); - } - - int outmask = devmask | ~recmask; - - int index; - if (outmask & (1 << SOUND_MIXER_ALTPCM)) - index = SOUND_MIXER_ALTPCM; - else if (outmask & (1 << SOUND_MIXER_PCM)) - index = SOUND_MIXER_PCM; - - int level; - if (ioctl(mixer, MIXER_READ(index), &level) == -1) { - ::close(mixer); - throw TSoundDeviceException( - TSoundDeviceException::UnableVolume, - "Error to read the volume"); - } - if ((1 << index) & stereo) { - int left = level & 0xff; - int right = ((level & 0xff00) >> 8); - ::close(mixer); - return (left + right) / 20.0; - } else { - ::close(mixer); - return (level & 0xff) / 10.0; - } +double TSoundOutputDevice::getVolume() { + int mixer; + if ((mixer = openMixer()) < 0) + throw TSoundDeviceException(TSoundDeviceException::NoMixer, + "Can't open the mixer device"); + + int devmask; + if (ioctl(mixer, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) { + ::close(mixer); + throw TSoundDeviceException(TSoundDeviceException::NoMixer, + "Error in ioctl with mixer device"); + } + + int recmask; + if (ioctl(mixer, SOUND_MIXER_READ_RECMASK, &recmask) == -1) { + ::close(mixer); + throw TSoundDeviceException(TSoundDeviceException::NoMixer, + "Error in ioctl with mixer device"); + } + + int stereo; + if (ioctl(mixer, SOUND_MIXER_READ_STEREODEVS, &stereo) == -1) { + ::close(mixer); + throw TSoundDeviceException(TSoundDeviceException::NoMixer, + "Error in ioctl with mixer device"); + } + + int outmask = devmask | ~recmask; + + int index; + if (outmask & (1 << SOUND_MIXER_ALTPCM)) + index = SOUND_MIXER_ALTPCM; + else if (outmask & (1 << SOUND_MIXER_PCM)) + index = SOUND_MIXER_PCM; + + int level; + if (ioctl(mixer, MIXER_READ(index), &level) == -1) { + ::close(mixer); + throw TSoundDeviceException(TSoundDeviceException::UnableVolume, + "Error to read the volume"); + } + if ((1 << index) & stereo) { + int left = level & 0xff; + int right = ((level & 0xff00) >> 8); + ::close(mixer); + return (left + right) / 20.0; + } else { + ::close(mixer); + return (level & 0xff) / 10.0; + } } //------------------------------------------------------------------------------ -bool TSoundOutputDevice::setVolume(double volume) -{ - int mixer; - if ((mixer = openMixer()) < 0) - throw TSoundDeviceException( - TSoundDeviceException::NoMixer, - "Can't open the mixer device"); - - int devmask; - if (ioctl(mixer, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) { - ::close(mixer); - throw TSoundDeviceException( - TSoundDeviceException::NoMixer, - "Error in ioctl with mixer device"); - } - - int recmask; - if (ioctl(mixer, SOUND_MIXER_READ_DEVMASK, &recmask) == -1) { - ::close(mixer); - throw TSoundDeviceException( - TSoundDeviceException::NoMixer, - "Error in ioctl with mixer device"); - } - - int stereo; - if (ioctl(mixer, SOUND_MIXER_READ_STEREODEVS, &stereo) == -1) { - ::close(mixer); - throw TSoundDeviceException( - TSoundDeviceException::NoMixer, - "Error in ioctl with mixer device"); - } - - int outmask = devmask | ~recmask; - - if (outmask & (1 << SOUND_MIXER_ALTPCM)) { - int vol, index = SOUND_MIXER_ALTPCM; - if ((1 << index) & stereo) { - volume *= 10.0; - vol = (int)volume + ((int)(volume * 256.0)); - } else - vol = (int)(volume * 10.0); - - if (!writeVolume(vol, mixer, index)) { - ::close(mixer); - throw TSoundDeviceException( - TSoundDeviceException::UnableVolume, - "Can't write the volume"); - } - - // metto anche l'altro ad un livello di sensibilita' adeguata - if (outmask & (1 << SOUND_MIXER_PCM)) { - int vol, index = SOUND_MIXER_PCM; - double volDefault = 6.7; - if ((1 << index) & stereo) { - volDefault *= 10.0; - vol = (int)volDefault + ((int)(volDefault * 256.0)); - } else - vol = (int)(volDefault * 10.0); - - if (!writeVolume(vol, mixer, index)) { - ::close(mixer); - throw TSoundDeviceException( - TSoundDeviceException::UnableVolume, - "Can't write the volume"); - } - } - } else if (outmask & (1 << SOUND_MIXER_PCM)) { - int vol, index = SOUND_MIXER_PCM; - if ((1 << index) & stereo) { - volume *= 10.0; - vol = (int)volume + ((int)(volume * 256.0)); - } else - vol = (int)(volume * 10.0); - - if (!writeVolume(vol, mixer, index)) { - ::close(mixer); - throw TSoundDeviceException( - TSoundDeviceException::NoMixer, - "Can't write the volume"); - } - } - - ::close(mixer); - return true; +bool TSoundOutputDevice::setVolume(double volume) { + int mixer; + if ((mixer = openMixer()) < 0) + throw TSoundDeviceException(TSoundDeviceException::NoMixer, + "Can't open the mixer device"); + + int devmask; + if (ioctl(mixer, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) { + ::close(mixer); + throw TSoundDeviceException(TSoundDeviceException::NoMixer, + "Error in ioctl with mixer device"); + } + + int recmask; + if (ioctl(mixer, SOUND_MIXER_READ_DEVMASK, &recmask) == -1) { + ::close(mixer); + throw TSoundDeviceException(TSoundDeviceException::NoMixer, + "Error in ioctl with mixer device"); + } + + int stereo; + if (ioctl(mixer, SOUND_MIXER_READ_STEREODEVS, &stereo) == -1) { + ::close(mixer); + throw TSoundDeviceException(TSoundDeviceException::NoMixer, + "Error in ioctl with mixer device"); + } + + int outmask = devmask | ~recmask; + + if (outmask & (1 << SOUND_MIXER_ALTPCM)) { + int vol, index = SOUND_MIXER_ALTPCM; + if ((1 << index) & stereo) { + volume *= 10.0; + vol = (int)volume + ((int)(volume * 256.0)); + } else + vol = (int)(volume * 10.0); + + if (!writeVolume(vol, mixer, index)) { + ::close(mixer); + throw TSoundDeviceException(TSoundDeviceException::UnableVolume, + "Can't write the volume"); + } + + // metto anche l'altro ad un livello di sensibilita' adeguata + if (outmask & (1 << SOUND_MIXER_PCM)) { + int vol, index = SOUND_MIXER_PCM; + double volDefault = 6.7; + if ((1 << index) & stereo) { + volDefault *= 10.0; + vol = (int)volDefault + ((int)(volDefault * 256.0)); + } else + vol = (int)(volDefault * 10.0); + + if (!writeVolume(vol, mixer, index)) { + ::close(mixer); + throw TSoundDeviceException(TSoundDeviceException::UnableVolume, + "Can't write the volume"); + } + } + } else if (outmask & (1 << SOUND_MIXER_PCM)) { + int vol, index = SOUND_MIXER_PCM; + if ((1 << index) & stereo) { + volume *= 10.0; + vol = (int)volume + ((int)(volume * 256.0)); + } else + vol = (int)(volume * 10.0); + + if (!writeVolume(vol, mixer, index)) { + ::close(mixer); + throw TSoundDeviceException(TSoundDeviceException::NoMixer, + "Can't write the volume"); + } + } + + ::close(mixer); + return true; } //------------------------------------------------------------------------------ -bool TSoundOutputDevice::isPlaying() const -{ - TThread::ScopedLock sl(m_imp->m_mutex); - return m_imp->m_isPlaying; +bool TSoundOutputDevice::isPlaying() const { + TThread::ScopedLock sl(m_imp->m_mutex); + return m_imp->m_isPlaying; } //------------------------------------------------------------------------------ -bool TSoundOutputDevice::isLooping() -{ - TThread::ScopedLock sl(m_imp->m_mutex); - return m_imp->m_looped; +bool TSoundOutputDevice::isLooping() { + TThread::ScopedLock sl(m_imp->m_mutex); + return m_imp->m_looped; } //------------------------------------------------------------------------------ -void TSoundOutputDevice::setLooping(bool loop) -{ - TThread::ScopedLock sl(m_imp->m_mutex); - m_imp->m_looped = loop; +void TSoundOutputDevice::setLooping(bool loop) { + TThread::ScopedLock sl(m_imp->m_mutex); + m_imp->m_looped = loop; } //------------------------------------------------------------------------------ -bool TSoundOutputDevice::supportsVolume() -{ - int mixer; - if ((mixer = openMixer()) < 0) - throw TSoundDeviceException( - TSoundDeviceException::NoMixer, - "Can't open the mixer device"); - - int devmask; - if (ioctl(mixer, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) { - ::close(mixer); - throw TSoundDeviceException( - TSoundDeviceException::NoMixer, - "Error in ioctl with mixer device"); - } - - int recmask; - if (ioctl(mixer, SOUND_MIXER_READ_DEVMASK, &recmask) == -1) { - ::close(mixer); - throw TSoundDeviceException( - TSoundDeviceException::NoMixer, - "Error in ioctl with mixer device"); - } - - int stereo; - if (ioctl(mixer, SOUND_MIXER_READ_STEREODEVS, &stereo) == -1) { - ::close(mixer); - throw TSoundDeviceException( - TSoundDeviceException::NoMixer, - "Error in ioctl with mixer device"); - } - - int outmask = devmask | ~recmask; - - if ((outmask & (1 << SOUND_MIXER_ALTPCM)) || (outmask & (1 << SOUND_MIXER_PCM))) { - ::close(mixer); - return true; - } - - return false; +bool TSoundOutputDevice::supportsVolume() { + int mixer; + if ((mixer = openMixer()) < 0) + throw TSoundDeviceException(TSoundDeviceException::NoMixer, + "Can't open the mixer device"); + + int devmask; + if (ioctl(mixer, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) { + ::close(mixer); + throw TSoundDeviceException(TSoundDeviceException::NoMixer, + "Error in ioctl with mixer device"); + } + + int recmask; + if (ioctl(mixer, SOUND_MIXER_READ_DEVMASK, &recmask) == -1) { + ::close(mixer); + throw TSoundDeviceException(TSoundDeviceException::NoMixer, + "Error in ioctl with mixer device"); + } + + int stereo; + if (ioctl(mixer, SOUND_MIXER_READ_STEREODEVS, &stereo) == -1) { + ::close(mixer); + throw TSoundDeviceException(TSoundDeviceException::NoMixer, + "Error in ioctl with mixer device"); + } + + int outmask = devmask | ~recmask; + + if ((outmask & (1 << SOUND_MIXER_ALTPCM)) || + (outmask & (1 << SOUND_MIXER_PCM))) { + ::close(mixer); + return true; + } + + return false; } //------------------------------------------------------------------------------ -TSoundTrackFormat TSoundOutputDevice::getPreferredFormat( - TUINT32 sampleRate, int channelCount, int bitPerSample) -{ - TSoundTrackFormat fmt; - if (bitPerSample == 8) - fmt = TSoundTrackFormat(sampleRate, channelCount, bitPerSample, false); - else - fmt = TSoundTrackFormat(sampleRate, channelCount, bitPerSample); - if (m_imp->isSupportFormat(fmt)) - return fmt; - - int bps, ch, status; - - bps = bitPerSample; - ch = channelCount; - - if (m_imp->m_dev == -1) - m_imp->doOpenDevice(); - - if (bitPerSample <= 8) { - bitPerSample = AFMT_U8; - fmt.m_signedSample = false; - } else if ((bitPerSample > 8 && bitPerSample < 16) || bitPerSample >= 16) { - bitPerSample = AFMT_S16_NE; - fmt.m_signedSample = true; - } - - status = ioctl(m_imp->m_dev, SNDCTL_DSP_SETFMT, &bitPerSample); - if (status == -1) { - perror("CHE palle "); - throw TSoundDeviceException( - TSoundDeviceException::UnablePrepare, - "Failed setting the specified number of bits"); - } - fmt.m_bitPerSample = bitPerSample; - - status = ioctl(m_imp->m_dev, SNDCTL_DSP_CHANNELS, &channelCount); - if (status == -1) - throw TSoundDeviceException( - TSoundDeviceException::UnablePrepare, - "Failed setting the specified number of channel"); - fmt.m_channelCount = channelCount; - - if (m_imp->m_supportedRate.find((int)sampleRate) == m_imp->m_supportedRate.end()) { - std::set::iterator it = m_imp->m_supportedRate.lower_bound((int)sampleRate); - if (it == m_imp->m_supportedRate.end()) { - it = std::max_element(m_imp->m_supportedRate.begin(), - m_imp->m_supportedRate.end()); - if (it != m_imp->m_supportedRate.end()) - sampleRate = *(m_imp->m_supportedRate.rbegin()); - else - throw TSoundDeviceException( - TSoundDeviceException::UnsupportedFormat, - "There isn't a supported rate"); - } else - sampleRate = *it; - } - - if (ioctl(m_imp->m_dev, SNDCTL_DSP_SPEED, &sampleRate) == -1) - throw TSoundDeviceException( - TSoundDeviceException::UnablePrepare, - "Failed setting the specified sample rate"); - fmt.m_sampleRate = sampleRate; - - if (ch != channelCount || bps != bitPerSample) { - m_imp->doCloseDevice(); - } - - return fmt; +TSoundTrackFormat TSoundOutputDevice::getPreferredFormat(TUINT32 sampleRate, + int channelCount, + int bitPerSample) { + TSoundTrackFormat fmt; + if (bitPerSample == 8) + fmt = TSoundTrackFormat(sampleRate, channelCount, bitPerSample, false); + else + fmt = TSoundTrackFormat(sampleRate, channelCount, bitPerSample); + if (m_imp->isSupportFormat(fmt)) return fmt; + + int bps, ch, status; + + bps = bitPerSample; + ch = channelCount; + + if (m_imp->m_dev == -1) m_imp->doOpenDevice(); + + if (bitPerSample <= 8) { + bitPerSample = AFMT_U8; + fmt.m_signedSample = false; + } else if ((bitPerSample > 8 && bitPerSample < 16) || bitPerSample >= 16) { + bitPerSample = AFMT_S16_NE; + fmt.m_signedSample = true; + } + + status = ioctl(m_imp->m_dev, SNDCTL_DSP_SETFMT, &bitPerSample); + if (status == -1) { + perror("CHE palle "); + throw TSoundDeviceException(TSoundDeviceException::UnablePrepare, + "Failed setting the specified number of bits"); + } + fmt.m_bitPerSample = bitPerSample; + + status = ioctl(m_imp->m_dev, SNDCTL_DSP_CHANNELS, &channelCount); + if (status == -1) + throw TSoundDeviceException( + TSoundDeviceException::UnablePrepare, + "Failed setting the specified number of channel"); + fmt.m_channelCount = channelCount; + + if (m_imp->m_supportedRate.find((int)sampleRate) == + m_imp->m_supportedRate.end()) { + std::set::iterator it = + m_imp->m_supportedRate.lower_bound((int)sampleRate); + if (it == m_imp->m_supportedRate.end()) { + it = std::max_element(m_imp->m_supportedRate.begin(), + m_imp->m_supportedRate.end()); + if (it != m_imp->m_supportedRate.end()) + sampleRate = *(m_imp->m_supportedRate.rbegin()); + else + throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat, + "There isn't a supported rate"); + } else + sampleRate = *it; + } + + if (ioctl(m_imp->m_dev, SNDCTL_DSP_SPEED, &sampleRate) == -1) + throw TSoundDeviceException(TSoundDeviceException::UnablePrepare, + "Failed setting the specified sample rate"); + fmt.m_sampleRate = sampleRate; + + if (ch != channelCount || bps != bitPerSample) { + m_imp->doCloseDevice(); + } + + return fmt; } //------------------------------------------------------------------------------ TSoundTrackFormat TSoundOutputDevice::getPreferredFormat( - const TSoundTrackFormat &format) -{ - try { - return getPreferredFormat( - format.m_sampleRate, format.m_channelCount, format.m_bitPerSample); - } catch (TSoundDeviceException &e) { - throw TSoundDeviceException(e.getType(), e.getMessage()); - } + const TSoundTrackFormat &format) { + try { + return getPreferredFormat(format.m_sampleRate, format.m_channelCount, + format.m_bitPerSample); + } catch (TSoundDeviceException &e) { + throw TSoundDeviceException(e.getType(), e.getMessage()); + } } //====================================================================== @@ -1529,723 +1553,664 @@ TSoundTrackFormat TSoundOutputDevice::getPreferredFormat( //====================================================================== //====================================================================== -class TSoundInputDeviceImp -{ +class TSoundInputDeviceImp { public: - int m_dev; - bool m_stopped; - bool m_isRecording; - TSoundTrackFormat m_currentFormat; - TSoundTrackP m_st; - std::set m_supportedRate; - - TINT32 m_recordedSampleCount; - vector m_recordedBlocks; - vector m_samplePerBlocks; - bool m_oneShotRecording; - - TThread::Executor m_executor; - - TSoundInputDeviceImp() - : m_dev(-1), m_stopped(false), m_isRecording(false), m_st(0), m_supportedRate(), m_recordedBlocks(), m_samplePerBlocks(), m_oneShotRecording(false) - { - } - - ~TSoundInputDeviceImp() {} - - bool doOpenDevice(const TSoundTrackFormat &format, - TSoundInputDevice::Source devType); - bool doCloseDevice(); - void insertAllRate(); - bool verifyRate(); + int m_dev; + bool m_stopped; + bool m_isRecording; + TSoundTrackFormat m_currentFormat; + TSoundTrackP m_st; + std::set m_supportedRate; + + TINT32 m_recordedSampleCount; + vector m_recordedBlocks; + vector m_samplePerBlocks; + bool m_oneShotRecording; + + TThread::Executor m_executor; + + TSoundInputDeviceImp() + : m_dev(-1) + , m_stopped(false) + , m_isRecording(false) + , m_st(0) + , m_supportedRate() + , m_recordedBlocks() + , m_samplePerBlocks() + , m_oneShotRecording(false) {} + + ~TSoundInputDeviceImp() {} + + bool doOpenDevice(const TSoundTrackFormat &format, + TSoundInputDevice::Source devType); + bool doCloseDevice(); + void insertAllRate(); + bool verifyRate(); }; //------------------------------------------------------------------------------ bool TSoundInputDeviceImp::doOpenDevice(const TSoundTrackFormat &format, - TSoundInputDevice::Source devType) -{ - m_dev = open("/dev/dsp", O_RDONLY); - if (m_dev < 0) - throw TSoundDeviceException( - TSoundDeviceException::UnableOpenDevice, - "Cannot open the dsp device"); + TSoundInputDevice::Source devType) { + m_dev = open("/dev/dsp", O_RDONLY); + if (m_dev < 0) + throw TSoundDeviceException(TSoundDeviceException::UnableOpenDevice, + "Cannot open the dsp device"); - //ioctl(m_dev, SNDCTL_DSP_RESET,0); + // ioctl(m_dev, SNDCTL_DSP_RESET,0); - return true; + return true; } //------------------------------------------------------------------------------ -bool TSoundInputDeviceImp::doCloseDevice() -{ - if (close(m_dev) < 0) - throw TSoundDeviceException( - TSoundDeviceException::UnableCloseDevice, - "Cannot close the dsp device"); - m_dev = -1; - return true; +bool TSoundInputDeviceImp::doCloseDevice() { + if (close(m_dev) < 0) + throw TSoundDeviceException(TSoundDeviceException::UnableCloseDevice, + "Cannot close the dsp device"); + m_dev = -1; + return true; } //---------------------------------------------------------------------------- -void TSoundInputDeviceImp::insertAllRate() -{ - m_supportedRate.insert(8000); - m_supportedRate.insert(11025); - m_supportedRate.insert(16000); - m_supportedRate.insert(22050); - m_supportedRate.insert(32000); - m_supportedRate.insert(44100); - m_supportedRate.insert(48000); +void TSoundInputDeviceImp::insertAllRate() { + m_supportedRate.insert(8000); + m_supportedRate.insert(11025); + m_supportedRate.insert(16000); + m_supportedRate.insert(22050); + m_supportedRate.insert(32000); + m_supportedRate.insert(44100); + m_supportedRate.insert(48000); } //---------------------------------------------------------------------------- -bool TSoundInputDeviceImp::verifyRate() -{ - std::set::iterator it; - - for (it = m_supportedRate.begin(); - it != m_supportedRate.end(); ++it) { - int sampleRate = *it; - if (ioctl(m_dev, SNDCTL_DSP_SPEED, &sampleRate) == -1) - throw TSoundDeviceException( - TSoundDeviceException::UnablePrepare, - "Failed setting the specified sample rate"); - if (sampleRate != *it) - m_supportedRate.erase(*it); - } - if (m_supportedRate.end() == m_supportedRate.begin()) - return false; - - return true; +bool TSoundInputDeviceImp::verifyRate() { + std::set::iterator it; + + for (it = m_supportedRate.begin(); it != m_supportedRate.end(); ++it) { + int sampleRate = *it; + if (ioctl(m_dev, SNDCTL_DSP_SPEED, &sampleRate) == -1) + throw TSoundDeviceException(TSoundDeviceException::UnablePrepare, + "Failed setting the specified sample rate"); + if (sampleRate != *it) m_supportedRate.erase(*it); + } + if (m_supportedRate.end() == m_supportedRate.begin()) return false; + + return true; } //============================================================================== -class TRecordTask : public TThread::Runnable -{ +class TRecordTask : public TThread::Runnable { public: - TSoundInputDeviceImp *m_devImp; + TSoundInputDeviceImp *m_devImp; - TRecordTask(TSoundInputDeviceImp *devImp) - : Runnable(), m_devImp(devImp){}; + TRecordTask(TSoundInputDeviceImp *devImp) : Runnable(), m_devImp(devImp){}; - ~TRecordTask(){}; + ~TRecordTask(){}; - void run(); + void run(); }; //------------------------------------------------------------------------------ -void TRecordTask::run() -{ - // N.B. e' bene che la dimensione sia piccola cosi' l'attesa perche' termini - // e' minore in questo caso vogliamo 16 frammenti ognuno di 4096 byte - int fraginfo = (16 << 16) | 12; - if (ioctl(m_devImp->m_dev, SNDCTL_DSP_SETFRAGMENT, &fraginfo) == -1) - perror("SETFRAGMENT"); - - int fragsize = 0; - if (ioctl(m_devImp->m_dev, SNDCTL_DSP_GETBLKSIZE, &fragsize) == -1) - perror("GETFRAGMENT"); - TINT32 byteRecordedSample = 0; - - if (m_devImp->m_oneShotRecording) { - TINT32 byteToSample = m_devImp->m_st->getSampleSize() * m_devImp->m_st->getSampleCount(); - char *buf = (char *)m_devImp->m_st->getRawData(); - - while ((byteRecordedSample < byteToSample) && m_devImp->m_isRecording) { - int sample; - if (fragsize > (byteToSample - byteRecordedSample)) - sample = byteToSample - byteRecordedSample; - else - sample = fragsize; - int nread = read(m_devImp->m_dev, buf + byteRecordedSample, sample); - if (nread == -1) - break; - if (nread != sample) - break; - - byteRecordedSample += nread; - } - } else { - int bytePerSample = m_devImp->m_currentFormat.m_bitPerSample >> 3; - switch (bytePerSample) { - case 3: - bytePerSample++; - break; - default: - break; - } - bytePerSample *= m_devImp->m_currentFormat.m_channelCount; - - while (m_devImp->m_isRecording) { - char *dataBuffer = new char[fragsize]; - m_devImp->m_recordedBlocks.push_back(dataBuffer); - m_devImp->m_samplePerBlocks.push_back(fragsize); - - int nread = read(m_devImp->m_dev, dataBuffer, fragsize); - if (nread == -1) - break; - if (nread != fragsize) - break; - - m_devImp->m_recordedSampleCount += (fragsize / bytePerSample); - } - } - ioctl(m_devImp->m_dev, SNDCTL_DSP_RESET, 0); +void TRecordTask::run() { + // N.B. e' bene che la dimensione sia piccola cosi' l'attesa perche' termini + // e' minore in questo caso vogliamo 16 frammenti ognuno di 4096 byte + int fraginfo = (16 << 16) | 12; + if (ioctl(m_devImp->m_dev, SNDCTL_DSP_SETFRAGMENT, &fraginfo) == -1) + perror("SETFRAGMENT"); + + int fragsize = 0; + if (ioctl(m_devImp->m_dev, SNDCTL_DSP_GETBLKSIZE, &fragsize) == -1) + perror("GETFRAGMENT"); + TINT32 byteRecordedSample = 0; + + if (m_devImp->m_oneShotRecording) { + TINT32 byteToSample = + m_devImp->m_st->getSampleSize() * m_devImp->m_st->getSampleCount(); + char *buf = (char *)m_devImp->m_st->getRawData(); + + while ((byteRecordedSample < byteToSample) && m_devImp->m_isRecording) { + int sample; + if (fragsize > (byteToSample - byteRecordedSample)) + sample = byteToSample - byteRecordedSample; + else + sample = fragsize; + int nread = read(m_devImp->m_dev, buf + byteRecordedSample, sample); + if (nread == -1) break; + if (nread != sample) break; + + byteRecordedSample += nread; + } + } else { + int bytePerSample = m_devImp->m_currentFormat.m_bitPerSample >> 3; + switch (bytePerSample) { + case 3: + bytePerSample++; + break; + default: + break; + } + bytePerSample *= m_devImp->m_currentFormat.m_channelCount; + + while (m_devImp->m_isRecording) { + char *dataBuffer = new char[fragsize]; + m_devImp->m_recordedBlocks.push_back(dataBuffer); + m_devImp->m_samplePerBlocks.push_back(fragsize); + + int nread = read(m_devImp->m_dev, dataBuffer, fragsize); + if (nread == -1) break; + if (nread != fragsize) break; + + m_devImp->m_recordedSampleCount += (fragsize / bytePerSample); + } + } + ioctl(m_devImp->m_dev, SNDCTL_DSP_RESET, 0); } //============================================================================== -TSoundInputDevice::TSoundInputDevice() : m_imp(new TSoundInputDeviceImp) -{ - m_imp->m_dev = open("/dev/dsp", O_RDONLY); - if (m_imp->m_dev < 0) - throw TSoundDeviceException( - TSoundDeviceException::UnableOpenDevice, - "Cannot open the dsp device"); - - m_imp->insertAllRate(); - try { - if (!m_imp->verifyRate()) - throw TSoundDeviceException( - TSoundDeviceException::UnablePrepare, - "No default samplerate are supported"); - } catch (TSoundDeviceException &e) { - throw TSoundDeviceException(e.getType(), e.getMessage()); - } - m_imp->doCloseDevice(); +TSoundInputDevice::TSoundInputDevice() : m_imp(new TSoundInputDeviceImp) { + m_imp->m_dev = open("/dev/dsp", O_RDONLY); + if (m_imp->m_dev < 0) + throw TSoundDeviceException(TSoundDeviceException::UnableOpenDevice, + "Cannot open the dsp device"); + + m_imp->insertAllRate(); + try { + if (!m_imp->verifyRate()) + throw TSoundDeviceException(TSoundDeviceException::UnablePrepare, + "No default samplerate are supported"); + } catch (TSoundDeviceException &e) { + throw TSoundDeviceException(e.getType(), e.getMessage()); + } + m_imp->doCloseDevice(); } //------------------------------------------------------------------------------ -TSoundInputDevice::~TSoundInputDevice() -{ - if (m_imp->m_dev != -1) - m_imp->doCloseDevice(); - delete m_imp; +TSoundInputDevice::~TSoundInputDevice() { + if (m_imp->m_dev != -1) m_imp->doCloseDevice(); + delete m_imp; } //------------------------------------------------------------------------------ -bool TSoundInputDevice::installed() -{ - bool ret = false; - int dev = ::open("/dev/dsp", O_RDONLY); - if (dev >= 0) { - ret = true; - ::close(dev); - } - return ret; +bool TSoundInputDevice::installed() { + bool ret = false; + int dev = ::open("/dev/dsp", O_RDONLY); + if (dev >= 0) { + ret = true; + ::close(dev); + } + return ret; } //------------------------------------------------------------------------------ -void TSoundInputDevice::record(const TSoundTrackFormat &format, TSoundInputDevice::Source type) -{ - m_imp->m_recordedBlocks.clear(); - m_imp->m_samplePerBlocks.clear(); - - //registra creando una nuova traccia - m_imp->m_oneShotRecording = false; - try { - if (m_imp->m_dev == -1) - m_imp->doOpenDevice(format, type); - - if (!selectInputDevice(type)) - throw TSoundDeviceException( - TSoundDeviceException::UnableSetDevice, - "Input device is not supported for recording"); - - TSoundTrackFormat fmt = getPreferredFormat(format); - if (fmt != format) - throw TSoundDeviceException( - TSoundDeviceException::UnsupportedFormat, - "Unsupported format"); - } catch (TSoundDeviceException &e) { - throw TSoundDeviceException(e.getType(), e.getMessage()); - } - - try { - if (getVolume() == 0.0) { - double volume = 5.0; - setVolume(volume); - } - } catch (TSoundDeviceException &e) { - throw TSoundDeviceException(e.getType(), e.getMessage()); - } - - m_imp->m_currentFormat = format; - m_imp->m_isRecording = true; - m_imp->m_stopped = false; - m_imp->m_recordedSampleCount = 0; - - //far partire il thread - /*TRecordThread *recordThread = new TRecordThread(m_imp); - if (!recordThread) - throw TSoundDeviceException( - TSoundDeviceException::UnablePrepare, - "Problemi per creare il thread"); - recordThread->start();*/ - m_imp->m_executor.addTask(new TRecordTask(m_imp)); +void TSoundInputDevice::record(const TSoundTrackFormat &format, + TSoundInputDevice::Source type) { + m_imp->m_recordedBlocks.clear(); + m_imp->m_samplePerBlocks.clear(); + + // registra creando una nuova traccia + m_imp->m_oneShotRecording = false; + try { + if (m_imp->m_dev == -1) m_imp->doOpenDevice(format, type); + + if (!selectInputDevice(type)) + throw TSoundDeviceException( + TSoundDeviceException::UnableSetDevice, + "Input device is not supported for recording"); + + TSoundTrackFormat fmt = getPreferredFormat(format); + if (fmt != format) + throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat, + "Unsupported format"); + } catch (TSoundDeviceException &e) { + throw TSoundDeviceException(e.getType(), e.getMessage()); + } + + try { + if (getVolume() == 0.0) { + double volume = 5.0; + setVolume(volume); + } + } catch (TSoundDeviceException &e) { + throw TSoundDeviceException(e.getType(), e.getMessage()); + } + + m_imp->m_currentFormat = format; + m_imp->m_isRecording = true; + m_imp->m_stopped = false; + m_imp->m_recordedSampleCount = 0; + + // far partire il thread + /*TRecordThread *recordThread = new TRecordThread(m_imp); +if (!recordThread) +throw TSoundDeviceException( +TSoundDeviceException::UnablePrepare, +"Problemi per creare il thread"); +recordThread->start();*/ + m_imp->m_executor.addTask(new TRecordTask(m_imp)); } //------------------------------------------------------------------------------ -void TSoundInputDevice::record(const TSoundTrackP &st, TSoundInputDevice::Source type) -{ - m_imp->m_recordedBlocks.clear(); - m_imp->m_samplePerBlocks.clear(); - - try { - if (m_imp->m_dev == -1) - m_imp->doOpenDevice(st->getFormat(), type); - - if (!selectInputDevice(type)) - throw TSoundDeviceException( - TSoundDeviceException::UnableSetDevice, - "Input device is not supported for recording"); - - TSoundTrackFormat fmt = getPreferredFormat(st->getFormat()); - if (fmt != st->getFormat()) - throw TSoundDeviceException( - TSoundDeviceException::UnsupportedFormat, - "Unsupported format"); - - if (getVolume() == 0.0) { - double volume = 5.0; - setVolume(volume); - } - } catch (TSoundDeviceException &e) { - throw TSoundDeviceException(e.getType(), e.getMessage()); - } - - //Sovrascive un'intera o parte di traccia gia' esistente - m_imp->m_oneShotRecording = true; - m_imp->m_currentFormat = st->getFormat(); - m_imp->m_isRecording = true; - m_imp->m_stopped = false; - m_imp->m_recordedSampleCount = 0; - m_imp->m_st = st; - - m_imp->m_recordedBlocks.push_back((char *)st->getRawData()); - - //far partire il thread - /*TRecordThread *recordThread = new TRecordThread(m_imp); - if (!recordThread) - throw TSoundDeviceException( - TSoundDeviceException::UnablePrepare, - "Problemi per creare il thread"); - recordThread->start();*/ - m_imp->m_executor.addTask(new TRecordTask(m_imp)); +void TSoundInputDevice::record(const TSoundTrackP &st, + TSoundInputDevice::Source type) { + m_imp->m_recordedBlocks.clear(); + m_imp->m_samplePerBlocks.clear(); + + try { + if (m_imp->m_dev == -1) m_imp->doOpenDevice(st->getFormat(), type); + + if (!selectInputDevice(type)) + throw TSoundDeviceException( + TSoundDeviceException::UnableSetDevice, + "Input device is not supported for recording"); + + TSoundTrackFormat fmt = getPreferredFormat(st->getFormat()); + if (fmt != st->getFormat()) + throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat, + "Unsupported format"); + + if (getVolume() == 0.0) { + double volume = 5.0; + setVolume(volume); + } + } catch (TSoundDeviceException &e) { + throw TSoundDeviceException(e.getType(), e.getMessage()); + } + + // Sovrascive un'intera o parte di traccia gia' esistente + m_imp->m_oneShotRecording = true; + m_imp->m_currentFormat = st->getFormat(); + m_imp->m_isRecording = true; + m_imp->m_stopped = false; + m_imp->m_recordedSampleCount = 0; + m_imp->m_st = st; + + m_imp->m_recordedBlocks.push_back((char *)st->getRawData()); + + // far partire il thread + /*TRecordThread *recordThread = new TRecordThread(m_imp); +if (!recordThread) +throw TSoundDeviceException( +TSoundDeviceException::UnablePrepare, +"Problemi per creare il thread"); +recordThread->start();*/ + m_imp->m_executor.addTask(new TRecordTask(m_imp)); } //------------------------------------------------------------------------------ -TSoundTrackP TSoundInputDevice::stop() -{ - TSoundTrackP st; - - if (!m_imp->m_isRecording) - return st; - - m_imp->m_isRecording = false; - - // mettere istruzioni per fermare il rec - ioctl(m_imp->m_dev, SNDCTL_DSP_SYNC, 0); - try { - m_imp->doCloseDevice(); - } catch (TSoundDeviceException &e) { - throw TSoundDeviceException(e.getType(), e.getMessage()); - } - - // attendo 1/5 di secondo - usleep(200000); - if (m_imp->m_oneShotRecording) - st = m_imp->m_st; - else { - st = TSoundTrack::create(m_imp->m_currentFormat, m_imp->m_recordedSampleCount); - TINT32 bytesCopied = 0; - - for (int i = 0; i < (int)m_imp->m_recordedBlocks.size(); ++i) { - memcpy( - (void *)(st->getRawData() + bytesCopied), - m_imp->m_recordedBlocks[i], - m_imp->m_samplePerBlocks[i]); - delete[] m_imp->m_recordedBlocks[i]; - - bytesCopied += m_imp->m_samplePerBlocks[i]; - } - m_imp->m_samplePerBlocks.clear(); - } - - return st; +TSoundTrackP TSoundInputDevice::stop() { + TSoundTrackP st; + + if (!m_imp->m_isRecording) return st; + + m_imp->m_isRecording = false; + + // mettere istruzioni per fermare il rec + ioctl(m_imp->m_dev, SNDCTL_DSP_SYNC, 0); + try { + m_imp->doCloseDevice(); + } catch (TSoundDeviceException &e) { + throw TSoundDeviceException(e.getType(), e.getMessage()); + } + + // attendo 1/5 di secondo + usleep(200000); + if (m_imp->m_oneShotRecording) + st = m_imp->m_st; + else { + st = TSoundTrack::create(m_imp->m_currentFormat, + m_imp->m_recordedSampleCount); + TINT32 bytesCopied = 0; + + for (int i = 0; i < (int)m_imp->m_recordedBlocks.size(); ++i) { + memcpy((void *)(st->getRawData() + bytesCopied), + m_imp->m_recordedBlocks[i], m_imp->m_samplePerBlocks[i]); + delete[] m_imp->m_recordedBlocks[i]; + + bytesCopied += m_imp->m_samplePerBlocks[i]; + } + m_imp->m_samplePerBlocks.clear(); + } + + return st; } //------------------------------------------------------------------------------ -double TSoundInputDevice::getVolume() -{ - int mixer; - if ((mixer = openMixer()) < 0) - throw TSoundDeviceException( - TSoundDeviceException::NoMixer, - "Can't have the mixer"); - - int index; - if ((index = getCurrentRecordSource(mixer)) == -1) { - ::close(mixer); - throw TSoundDeviceException( - TSoundDeviceException::NoMixer, - "Can't obtain information by mixer"); - } - - int stereo; - if (ioctl(mixer, SOUND_MIXER_READ_STEREODEVS, &stereo) == -1) { - ::close(mixer); - throw TSoundDeviceException( - TSoundDeviceException::NoMixer, - "Can't obtain information by mixer"); - } - - int level; - if (ioctl(mixer, MIXER_READ(index), &level) == -1) { - ::close(mixer); - throw TSoundDeviceException( - TSoundDeviceException::UnableVolume, - "Can't read the volume value"); - } - - if ((1 << index) & stereo) { - int left = level & 0xff; - int right = ((level & 0xff00) >> 8); - ::close(mixer); - return (left + right) / 20.0; - } else { - ::close(mixer); - return (level & 0xff) / 10.0; - } +double TSoundInputDevice::getVolume() { + int mixer; + if ((mixer = openMixer()) < 0) + throw TSoundDeviceException(TSoundDeviceException::NoMixer, + "Can't have the mixer"); + + int index; + if ((index = getCurrentRecordSource(mixer)) == -1) { + ::close(mixer); + throw TSoundDeviceException(TSoundDeviceException::NoMixer, + "Can't obtain information by mixer"); + } + + int stereo; + if (ioctl(mixer, SOUND_MIXER_READ_STEREODEVS, &stereo) == -1) { + ::close(mixer); + throw TSoundDeviceException(TSoundDeviceException::NoMixer, + "Can't obtain information by mixer"); + } + + int level; + if (ioctl(mixer, MIXER_READ(index), &level) == -1) { + ::close(mixer); + throw TSoundDeviceException(TSoundDeviceException::UnableVolume, + "Can't read the volume value"); + } + + if ((1 << index) & stereo) { + int left = level & 0xff; + int right = ((level & 0xff00) >> 8); + ::close(mixer); + return (left + right) / 20.0; + } else { + ::close(mixer); + return (level & 0xff) / 10.0; + } } //------------------------------------------------------------------------------ -bool TSoundInputDevice::setVolume(double volume) -{ - int mixer; - if ((mixer = openMixer()) < 0) - throw TSoundDeviceException( - TSoundDeviceException::NoMixer, - "Can't have the mixer"); - - int caps; - if (ioctl(mixer, SOUND_MIXER_READ_CAPS, &caps) == -1) { - ::close(mixer); - throw TSoundDeviceException( - TSoundDeviceException::NoMixer, - "Can't obtain information by mixer"); - } - - if (!(caps & SOUND_CAP_EXCL_INPUT)) { - int rec; - if (ioctl(mixer, SOUND_MIXER_READ_RECMASK, &rec) == -1) { - ::close(mixer); - throw TSoundDeviceException( - TSoundDeviceException::NoMixer, - "Can't obtain information by mixer"); - } - int i; - int nosound = 0; - for (i = 0; i < 32; ++i) - if (rec & (1 << i)) - if (!writeVolume(nosound, mixer, i)) { - ::close(mixer); - throw TSoundDeviceException( - TSoundDeviceException::UnableVolume, - "Can't set the volume value"); - } - } - - int index; - if ((index = getCurrentRecordSource(mixer)) == -1) { - ::close(mixer); - throw TSoundDeviceException( - TSoundDeviceException::NoMixer, - "Can't obtain information by mixer"); - } - - int stereo; - if (ioctl(mixer, SOUND_MIXER_READ_STEREODEVS, &stereo) == -1) { - ::close(mixer); - throw TSoundDeviceException( - TSoundDeviceException::NoMixer, - "Can't obtain information by mixer"); - } - - int vol; - if ((1 << index) & stereo) { - volume *= 10.0; - vol = (int)volume + ((int)(volume * 256.0)); - } else - vol = (int)(volume * 10.0); - - if (!writeVolume(vol, mixer, index)) { - ::close(mixer); - throw TSoundDeviceException( - TSoundDeviceException::UnableVolume, - "Can't write the volume value"); - } - ::close(mixer); - return true; +bool TSoundInputDevice::setVolume(double volume) { + int mixer; + if ((mixer = openMixer()) < 0) + throw TSoundDeviceException(TSoundDeviceException::NoMixer, + "Can't have the mixer"); + + int caps; + if (ioctl(mixer, SOUND_MIXER_READ_CAPS, &caps) == -1) { + ::close(mixer); + throw TSoundDeviceException(TSoundDeviceException::NoMixer, + "Can't obtain information by mixer"); + } + + if (!(caps & SOUND_CAP_EXCL_INPUT)) { + int rec; + if (ioctl(mixer, SOUND_MIXER_READ_RECMASK, &rec) == -1) { + ::close(mixer); + throw TSoundDeviceException(TSoundDeviceException::NoMixer, + "Can't obtain information by mixer"); + } + int i; + int nosound = 0; + for (i = 0; i < 32; ++i) + if (rec & (1 << i)) + if (!writeVolume(nosound, mixer, i)) { + ::close(mixer); + throw TSoundDeviceException(TSoundDeviceException::UnableVolume, + "Can't set the volume value"); + } + } + + int index; + if ((index = getCurrentRecordSource(mixer)) == -1) { + ::close(mixer); + throw TSoundDeviceException(TSoundDeviceException::NoMixer, + "Can't obtain information by mixer"); + } + + int stereo; + if (ioctl(mixer, SOUND_MIXER_READ_STEREODEVS, &stereo) == -1) { + ::close(mixer); + throw TSoundDeviceException(TSoundDeviceException::NoMixer, + "Can't obtain information by mixer"); + } + + int vol; + if ((1 << index) & stereo) { + volume *= 10.0; + vol = (int)volume + ((int)(volume * 256.0)); + } else + vol = (int)(volume * 10.0); + + if (!writeVolume(vol, mixer, index)) { + ::close(mixer); + throw TSoundDeviceException(TSoundDeviceException::UnableVolume, + "Can't write the volume value"); + } + ::close(mixer); + return true; } //------------------------------------------------------------------------------ -bool TSoundInputDevice::isRecording() -{ - return m_imp->m_isRecording; -} +bool TSoundInputDevice::isRecording() { return m_imp->m_isRecording; } //------------------------------------------------------------------------------ -TSoundTrackFormat TSoundInputDevice::getPreferredFormat( - TUINT32 sampleRate, int channelCount, int bitPerSample) -{ - TSoundTrackFormat fmt; - int status; - - if (bitPerSample <= 8) { - bitPerSample = AFMT_U8; - fmt.m_signedSample = false; - } else if ((bitPerSample > 8 && bitPerSample < 16) || bitPerSample >= 16) { - bitPerSample = AFMT_S16_NE; - fmt.m_signedSample = true; - } - - status = ioctl(m_imp->m_dev, SNDCTL_DSP_SETFMT, &bitPerSample); - if (status == -1) - throw TSoundDeviceException( - TSoundDeviceException::UnablePrepare, - "Failed setting the specified number of bits"); - fmt.m_bitPerSample = bitPerSample; - - status = ioctl(m_imp->m_dev, SNDCTL_DSP_CHANNELS, &channelCount); - if (status == -1) - throw TSoundDeviceException( - TSoundDeviceException::UnablePrepare, - "Failed setting the specified number of channel"); - fmt.m_channelCount = channelCount; - - if (m_imp->m_supportedRate.find((int)sampleRate) == - m_imp->m_supportedRate.end()) { - std::set::iterator it = - m_imp->m_supportedRate.lower_bound((int)sampleRate); - if (it == m_imp->m_supportedRate.end()) { - it = std::max_element(m_imp->m_supportedRate.begin(), - m_imp->m_supportedRate.end()); - if (it != m_imp->m_supportedRate.end()) - sampleRate = *(m_imp->m_supportedRate.rbegin()); - else - throw TSoundDeviceException( - TSoundDeviceException::UnsupportedFormat, - "There isn't a supported rate"); - } else - sampleRate = *it; - } - - if (ioctl(m_imp->m_dev, SNDCTL_DSP_SPEED, &sampleRate) == -1) - throw TSoundDeviceException( - TSoundDeviceException::UnablePrepare, - "Failed setting the specified sample rate"); - fmt.m_sampleRate = sampleRate; - - return fmt; +TSoundTrackFormat TSoundInputDevice::getPreferredFormat(TUINT32 sampleRate, + int channelCount, + int bitPerSample) { + TSoundTrackFormat fmt; + int status; + + if (bitPerSample <= 8) { + bitPerSample = AFMT_U8; + fmt.m_signedSample = false; + } else if ((bitPerSample > 8 && bitPerSample < 16) || bitPerSample >= 16) { + bitPerSample = AFMT_S16_NE; + fmt.m_signedSample = true; + } + + status = ioctl(m_imp->m_dev, SNDCTL_DSP_SETFMT, &bitPerSample); + if (status == -1) + throw TSoundDeviceException(TSoundDeviceException::UnablePrepare, + "Failed setting the specified number of bits"); + fmt.m_bitPerSample = bitPerSample; + + status = ioctl(m_imp->m_dev, SNDCTL_DSP_CHANNELS, &channelCount); + if (status == -1) + throw TSoundDeviceException( + TSoundDeviceException::UnablePrepare, + "Failed setting the specified number of channel"); + fmt.m_channelCount = channelCount; + + if (m_imp->m_supportedRate.find((int)sampleRate) == + m_imp->m_supportedRate.end()) { + std::set::iterator it = + m_imp->m_supportedRate.lower_bound((int)sampleRate); + if (it == m_imp->m_supportedRate.end()) { + it = std::max_element(m_imp->m_supportedRate.begin(), + m_imp->m_supportedRate.end()); + if (it != m_imp->m_supportedRate.end()) + sampleRate = *(m_imp->m_supportedRate.rbegin()); + else + throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat, + "There isn't a supported rate"); + } else + sampleRate = *it; + } + + if (ioctl(m_imp->m_dev, SNDCTL_DSP_SPEED, &sampleRate) == -1) + throw TSoundDeviceException(TSoundDeviceException::UnablePrepare, + "Failed setting the specified sample rate"); + fmt.m_sampleRate = sampleRate; + + return fmt; } //------------------------------------------------------------------------------ TSoundTrackFormat TSoundInputDevice::getPreferredFormat( - const TSoundTrackFormat &format) -{ - try { - return getPreferredFormat( - format.m_sampleRate, format.m_channelCount, format.m_bitPerSample); - } catch (TSoundDeviceException &e) { - throw TSoundDeviceException(e.getType(), e.getMessage()); - } + const TSoundTrackFormat &format) { + try { + return getPreferredFormat(format.m_sampleRate, format.m_channelCount, + format.m_bitPerSample); + } catch (TSoundDeviceException &e) { + throw TSoundDeviceException(e.getType(), e.getMessage()); + } } //****************************************************************************** //****************************************************************************** -// funzioni per l'interazione con la libreria OSS +// funzioni per l'interazione con la libreria +//OSS //****************************************************************************** //****************************************************************************** -namespace -{ -string parseError(int error) -{ - switch (error) { - case EBADF: - return string("Bad file descriptor"); - case EFAULT: - return string("Pointer to/from buffer data is invalid"); - case EINTR: - return string("Signal interrupt the signal"); - case EINVAL: - return string("Request/arg isn't valid for this device"); - case EIO: - return string("Some phisical I/O error has occurred"); - case ENOTTY: - return string("Fieldes isn't associated with a device that accepts control"); - case ENXIO: - return string("Request/arg valid, but the requested cannot be performed on this subdevice"); - default: - return string("Unknown error"); - break; - } +namespace { +string parseError(int error) { + switch (error) { + case EBADF: + return string("Bad file descriptor"); + case EFAULT: + return string("Pointer to/from buffer data is invalid"); + case EINTR: + return string("Signal interrupt the signal"); + case EINVAL: + return string("Request/arg isn't valid for this device"); + case EIO: + return string("Some phisical I/O error has occurred"); + case ENOTTY: + return string( + "Fieldes isn't associated with a device that accepts control"); + case ENXIO: + return string( + "Request/arg valid, but the requested cannot be performed on this " + "subdevice"); + default: + return string("Unknown error"); + break; + } } //------------------------------------------------------------------------------ -TSoundInputDevice::Source stringToSource(string dev) -{ - if (dev == "mic") - return TSoundInputDevice::Mic; - else if (dev == "line") - return TSoundInputDevice::LineIn; - else if (dev == "cd") - return TSoundInputDevice::CdAudio; - else - return TSoundInputDevice::DigitalIn; +TSoundInputDevice::Source stringToSource(string dev) { + if (dev == "mic") + return TSoundInputDevice::Mic; + else if (dev == "line") + return TSoundInputDevice::LineIn; + else if (dev == "cd") + return TSoundInputDevice::CdAudio; + else + return TSoundInputDevice::DigitalIn; } //------------------------------------------------------------------------------ -string sourceToString(TSoundInputDevice::Source dev) -{ - switch (dev) { - case TSoundInputDevice::Mic: - return string("mic"); - case TSoundInputDevice::LineIn: - return string("line"); - case TSoundInputDevice::DigitalIn: - return string("digital"); - default: - return string("cd"); - } +string sourceToString(TSoundInputDevice::Source dev) { + switch (dev) { + case TSoundInputDevice::Mic: + return string("mic"); + case TSoundInputDevice::LineIn: + return string("line"); + case TSoundInputDevice::DigitalIn: + return string("digital"); + default: + return string("cd"); + } } //------------------------------------------------------------------------------ -int openMixer() -{ - int mixer = open("/dev/mixer", O_RDWR); - if (mixer == -1) - return false; - return mixer; +int openMixer() { + int mixer = open("/dev/mixer", O_RDWR); + if (mixer == -1) return false; + return mixer; } //------------------------------------------------------------------------------ -int getCurrentRecordSource(int mixer) -{ - int recsrc; - if (ioctl(mixer, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) - return -1; - int index = -1; - for (index = 0; index < 32; ++index) - if (recsrc & 1 << index) - break; - return index; +int getCurrentRecordSource(int mixer) { + int recsrc; + if (ioctl(mixer, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) return -1; + int index = -1; + for (index = 0; index < 32; ++index) + if (recsrc & 1 << index) break; + return index; } //------------------------------------------------------------------------------ -bool writeVolume(int volume, int mixer, int indexDev) -{ - if (ioctl(mixer, MIXER_WRITE(indexDev), &volume) == -1) - return false; - return true; +bool writeVolume(int volume, int mixer, int indexDev) { + if (ioctl(mixer, MIXER_WRITE(indexDev), &volume) == -1) return false; + return true; } //------------------------------------------------------------------------------ -bool controlEnableRecord(int mixer) -{ - int recmask; - if (ioctl(mixer, SOUND_MIXER_READ_RECMASK, &recmask) == -1) { - perror("Read recmask"); - return false; - } - if (recmask & (1 << SOUND_MIXER_IGAIN)) { - int volume; - if (ioctl(mixer, MIXER_READ(SOUND_MIXER_IGAIN), &volume) == -1) - return false; - - int app = (volume & 0xff); - if (app <= 30) { - volume = 80 | 80 << 8; - if (!writeVolume(volume, mixer, SOUND_MIXER_IGAIN)) - return false; - } - } - return true; +bool controlEnableRecord(int mixer) { + int recmask; + if (ioctl(mixer, SOUND_MIXER_READ_RECMASK, &recmask) == -1) { + perror("Read recmask"); + return false; + } + if (recmask & (1 << SOUND_MIXER_IGAIN)) { + int volume; + if (ioctl(mixer, MIXER_READ(SOUND_MIXER_IGAIN), &volume) == -1) + return false; + + int app = (volume & 0xff); + if (app <= 30) { + volume = 80 | 80 << 8; + if (!writeVolume(volume, mixer, SOUND_MIXER_IGAIN)) return false; + } + } + return true; } //------------------------------------------------------------------------------ -int isInputDeviceSupported(TSoundInputDevice::Source dev, int &mixer) -{ - int recmask; - if (ioctl(mixer, SOUND_MIXER_READ_RECMASK, &recmask) == -1) { - perror("Read recmask"); - return -1; - } - - int i; - string devS = sourceToString(dev); - const char *deviceName[] = SOUND_DEVICE_NAMES; - for (i = 0; i < 32; ++i) { - if (!(recmask & 1 << i)) - continue; - if (strcmp(devS.c_str(), deviceName[i]) == 0) - return i; - } - return -1; +int isInputDeviceSupported(TSoundInputDevice::Source dev, int &mixer) { + int recmask; + if (ioctl(mixer, SOUND_MIXER_READ_RECMASK, &recmask) == -1) { + perror("Read recmask"); + return -1; + } + + int i; + string devS = sourceToString(dev); + const char *deviceName[] = SOUND_DEVICE_NAMES; + for (i = 0; i < 32; ++i) { + if (!(recmask & 1 << i)) continue; + if (strcmp(devS.c_str(), deviceName[i]) == 0) return i; + } + return -1; } //------------------------------------------------------------------------------ -bool selectInputDevice(TSoundInputDevice::Source dev) -{ - int mixer; - if ((mixer = openMixer()) < 0) { - close(mixer); - return false; //throw TException("Can't open the mixer device"); - } - int index = isInputDeviceSupported(dev, mixer); - if (index == -1) - return false; - int recsrc; - if (ioctl(mixer, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) { - perror("Read recsrc"); - close(mixer); - return false; - } - if (!(recsrc & 1 << index)) { - recsrc = 1 << index; - if (ioctl(mixer, SOUND_MIXER_WRITE_RECSRC, &recsrc) == -1) { - perror("Write recsrc"); - ::close(mixer); - return false; - } - } - - if (!controlEnableRecord(mixer)) { - close(mixer); - return false; //throw TException("Can't enable recording"); - } - ::close(mixer); - return true; +bool selectInputDevice(TSoundInputDevice::Source dev) { + int mixer; + if ((mixer = openMixer()) < 0) { + close(mixer); + return false; // throw TException("Can't open the mixer device"); + } + int index = isInputDeviceSupported(dev, mixer); + if (index == -1) return false; + int recsrc; + if (ioctl(mixer, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) { + perror("Read recsrc"); + close(mixer); + return false; + } + if (!(recsrc & 1 << index)) { + recsrc = 1 << index; + if (ioctl(mixer, SOUND_MIXER_WRITE_RECSRC, &recsrc) == -1) { + perror("Write recsrc"); + ::close(mixer); + return false; + } + } + + if (!controlEnableRecord(mixer)) { + close(mixer); + return false; // throw TException("Can't enable recording"); + } + ::close(mixer); + return true; } } diff --git a/toonz/sources/common/tsound/tsound_mac.cpp b/toonz/sources/common/tsound/tsound_mac.cpp index 63dd759..e801618 100644 --- a/toonz/sources/common/tsound/tsound_mac.cpp +++ b/toonz/sources/common/tsound/tsound_mac.cpp @@ -17,294 +17,286 @@ using namespace std; //============================================================================== -namespace -{ +namespace { TThread::Mutex MutexOut; } -class TSoundOutputDeviceImp : public std::enable_shared_from_this -{ +class TSoundOutputDeviceImp + : public std::enable_shared_from_this { public: - bool m_isPlaying; - bool m_looped; - TSoundTrackFormat m_currentFormat; - std::set m_supportedRate; - bool m_opened; - AudioFileID musicFileID; - AudioUnit theOutputUnit; - AudioStreamBasicDescription fileASBD; - AudioStreamBasicDescription outputASBD; - AudioConverterRef converter; - - TSoundOutputDeviceImp() - : m_isPlaying(false), m_looped(false), m_supportedRate(), m_opened(false){}; - - std::set m_listeners; - - ~TSoundOutputDeviceImp(){}; - - bool doOpenDevice(); - bool doSetStreamFormat(const TSoundTrackFormat &format); - bool doStopDevice(); - void play(const TSoundTrackP &st, TINT32 s0, TINT32 s1, bool loop, bool scrubbing); + bool m_isPlaying; + bool m_looped; + TSoundTrackFormat m_currentFormat; + std::set m_supportedRate; + bool m_opened; + AudioFileID musicFileID; + AudioUnit theOutputUnit; + AudioStreamBasicDescription fileASBD; + AudioStreamBasicDescription outputASBD; + AudioConverterRef converter; + + TSoundOutputDeviceImp() + : m_isPlaying(false) + , m_looped(false) + , m_supportedRate() + , m_opened(false){}; + + std::set m_listeners; + + ~TSoundOutputDeviceImp(){}; + + bool doOpenDevice(); + bool doSetStreamFormat(const TSoundTrackFormat &format); + bool doStopDevice(); + void play(const TSoundTrackP &st, TINT32 s0, TINT32 s1, bool loop, + bool scrubbing); }; //----------------------------------------------------------------------------- -namespace -{ +namespace { struct MyData { - char *entireFileBuffer; - - UInt64 totalPacketCount; - UInt64 fileByteCount; - UInt32 maxPacketSize; - UInt64 packetOffset; - UInt64 byteOffset; - bool m_doNotify; - - void *sourceBuffer; - AudioConverterRef converter; - std::shared_ptr imp; - bool isLooping; - MyData() - : entireFileBuffer(0) - , totalPacketCount(0) - , fileByteCount(0) - , maxPacketSize(0) - , packetOffset(0) - , byteOffset(0) - , sourceBuffer(0) - , isLooping(false) - , m_doNotify(true) - { - } + char *entireFileBuffer; + + UInt64 totalPacketCount; + UInt64 fileByteCount; + UInt32 maxPacketSize; + UInt64 packetOffset; + UInt64 byteOffset; + bool m_doNotify; + + void *sourceBuffer; + AudioConverterRef converter; + std::shared_ptr imp; + bool isLooping; + MyData() + : entireFileBuffer(0) + , totalPacketCount(0) + , fileByteCount(0) + , maxPacketSize(0) + , packetOffset(0) + , byteOffset(0) + , sourceBuffer(0) + , isLooping(false) + , m_doNotify(true) {} }; -class PlayCompletedMsg : public TThread::Message -{ - std::set m_listeners; - MyData *m_data; +class PlayCompletedMsg : public TThread::Message { + std::set m_listeners; + MyData *m_data; public: - PlayCompletedMsg(MyData *data) - : m_data(data) - { - } - - TThread::Message *clone() const - { - return new PlayCompletedMsg(*this); - } - - void onDeliver() - { - if (m_data->imp) { - if (m_data->m_doNotify == false) - return; - m_data->m_doNotify = false; - if (m_data->imp->m_isPlaying) - m_data->imp->doStopDevice(); - std::set::iterator it = m_data->imp->m_listeners.begin(); - for (; it != m_data->imp->m_listeners.end(); ++it) - (*it)->onPlayCompleted(); - } - } + PlayCompletedMsg(MyData *data) : m_data(data) {} + + TThread::Message *clone() const { return new PlayCompletedMsg(*this); } + + void onDeliver() { + if (m_data->imp) { + if (m_data->m_doNotify == false) return; + m_data->m_doNotify = false; + if (m_data->imp->m_isPlaying) m_data->imp->doStopDevice(); + std::set::iterator it = + m_data->imp->m_listeners.begin(); + for (; it != m_data->imp->m_listeners.end(); ++it) + (*it)->onPlayCompleted(); + } + } }; } -#define checkStatus(err) \ - if (err) { \ - printf("Error: 0x%x -> %s: %d\n", (int)err, __FILE__, __LINE__); \ - fflush(stdout); \ - } +#define checkStatus(err) \ + if (err) { \ + printf("Error: 0x%x -> %s: %d\n", (int)err, __FILE__, __LINE__); \ + fflush(stdout); \ + } extern "C" { -//This is an example of a Input Procedure from a call to AudioConverterFillComplexBuffer. -//The total amount of data needed is "ioNumberDataPackets" when this method is first called. -//On exit, "ioNumberDataPackets" must be set to the actual amount of data obtained. -//Upon completion, all new input data must point to the AudioBufferList in the parameter ( "ioData" ) -OSStatus MyACComplexInputProc(AudioConverterRef inAudioConverter, - UInt32 *ioNumberDataPackets, - AudioBufferList *ioData, - AudioStreamPacketDescription **outDataPacketDescription, - void *inUserData) -{ - OSStatus err = noErr; - UInt32 bytesCopied = 0; - - MyData *myData = static_cast(inUserData); - - // initialize in case of failure - ioData->mBuffers[0].mData = NULL; - ioData->mBuffers[0].mDataByteSize = 0; - - { - //TThread::ScopedLock sl(MutexOut); - if (myData->imp->m_isPlaying == false) - return noErr; - } - - // if there are not enough packets to satisfy request, then read what's left - if (myData->packetOffset + *ioNumberDataPackets > myData->totalPacketCount) - *ioNumberDataPackets = myData->totalPacketCount - myData->packetOffset; - - // do nothing if there are no packets available - if (*ioNumberDataPackets) { - if (myData->sourceBuffer != NULL) { - free(myData->sourceBuffer); - myData->sourceBuffer = NULL; - } - - //the total amount of data requested by the AudioConverter - bytesCopied = *ioNumberDataPackets * myData->maxPacketSize; - //alloc a small buffer for the AudioConverter to use. - myData->sourceBuffer = (void *)calloc(1, bytesCopied); - //copy the amount of data needed (bytesCopied) from buffer of audio file - memcpy(myData->sourceBuffer, myData->entireFileBuffer + myData->byteOffset, bytesCopied); - - // keep track of where we want to read from next time - myData->byteOffset += *ioNumberDataPackets * myData->maxPacketSize; - myData->packetOffset += *ioNumberDataPackets; - - ioData->mBuffers[0].mData = myData->sourceBuffer; // tell the Audio Converter where it's source data is - ioData->mBuffers[0].mDataByteSize = bytesCopied; // tell the Audio Converter how much data in each buffer - } else { - // there aren't any more packets to read. - // Set the amount of data read (mDataByteSize) to zero - // and return noErr to signal the AudioConverter there are - // no packets left. - - ioData->mBuffers[0].mData = NULL; - ioData->mBuffers[0].mDataByteSize = 0; - delete[] myData->entireFileBuffer; - myData->entireFileBuffer = 0; - err = noErr; - /* +// This is an example of a Input Procedure from a call to +// AudioConverterFillComplexBuffer. +// The total amount of data needed is "ioNumberDataPackets" when this method is +// first called. +// On exit, "ioNumberDataPackets" must be set to the actual amount of data +// obtained. +// Upon completion, all new input data must point to the AudioBufferList in the +// parameter ( "ioData" ) +OSStatus MyACComplexInputProc( + AudioConverterRef inAudioConverter, UInt32 *ioNumberDataPackets, + AudioBufferList *ioData, + AudioStreamPacketDescription **outDataPacketDescription, void *inUserData) { + OSStatus err = noErr; + UInt32 bytesCopied = 0; + + MyData *myData = static_cast(inUserData); + + // initialize in case of failure + ioData->mBuffers[0].mData = NULL; + ioData->mBuffers[0].mDataByteSize = 0; + { - TThread::ScopedLock sl(MutexOut); - *(myData->isPlaying) = false; //questo lo faccio nel main thread + // TThread::ScopedLock sl(MutexOut); + if (myData->imp->m_isPlaying == false) return noErr; } -*/ - PlayCompletedMsg(myData).send(); - } - return err; + // if there are not enough packets to satisfy request, then read what's left + if (myData->packetOffset + *ioNumberDataPackets > myData->totalPacketCount) + *ioNumberDataPackets = myData->totalPacketCount - myData->packetOffset; + + // do nothing if there are no packets available + if (*ioNumberDataPackets) { + if (myData->sourceBuffer != NULL) { + free(myData->sourceBuffer); + myData->sourceBuffer = NULL; + } + + // the total amount of data requested by the AudioConverter + bytesCopied = *ioNumberDataPackets * myData->maxPacketSize; + // alloc a small buffer for the AudioConverter to use. + myData->sourceBuffer = (void *)calloc(1, bytesCopied); + // copy the amount of data needed (bytesCopied) from buffer of audio file + memcpy(myData->sourceBuffer, myData->entireFileBuffer + myData->byteOffset, + bytesCopied); + + // keep track of where we want to read from next time + myData->byteOffset += *ioNumberDataPackets * myData->maxPacketSize; + myData->packetOffset += *ioNumberDataPackets; + + ioData->mBuffers[0].mData = myData->sourceBuffer; // tell the Audio + // Converter where it's + // source data is + ioData->mBuffers[0].mDataByteSize = + bytesCopied; // tell the Audio Converter how much data in each buffer + } else { + // there aren't any more packets to read. + // Set the amount of data read (mDataByteSize) to zero + // and return noErr to signal the AudioConverter there are + // no packets left. + + ioData->mBuffers[0].mData = NULL; + ioData->mBuffers[0].mDataByteSize = 0; + delete[] myData->entireFileBuffer; + myData->entireFileBuffer = 0; + err = noErr; + /* +{ +TThread::ScopedLock sl(MutexOut); +*(myData->isPlaying) = false; //questo lo faccio nel main thread } +*/ + PlayCompletedMsg(myData).send(); + } -OSStatus MyFileRenderProc(void *inRefCon, AudioUnitRenderActionFlags *inActionFlags, - const AudioTimeStamp *inTimeStamp, - UInt32 inBusNumber, UInt32 inNumFrames, AudioBufferList *ioData) -{ - MyData *myData = static_cast(inRefCon); - OSStatus err = noErr; - void *inInputDataProcUserData = inRefCon; - AudioStreamPacketDescription *outPacketDescription = NULL; - //To obtain a data buffer of converted data from a complex input source(compressed files, etc.) - //use AudioConverterFillComplexBuffer. The total amount of data requested is "inNumFrames" and - //on return is set to the actual amount of data recieved. - //All converted data is returned to "ioData" (AudioBufferList). - err = AudioConverterFillComplexBuffer(myData->converter, MyACComplexInputProc, inInputDataProcUserData, &inNumFrames, ioData, outPacketDescription); - - /*Parameters for AudioConverterFillComplexBuffer() + return err; +} + +OSStatus MyFileRenderProc(void *inRefCon, + AudioUnitRenderActionFlags *inActionFlags, + const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, + UInt32 inNumFrames, AudioBufferList *ioData) { + MyData *myData = static_cast(inRefCon); + OSStatus err = noErr; + void *inInputDataProcUserData = inRefCon; + AudioStreamPacketDescription *outPacketDescription = NULL; + // To obtain a data buffer of converted data from a complex input + // source(compressed files, etc.) + // use AudioConverterFillComplexBuffer. The total amount of data requested is + // "inNumFrames" and + // on return is set to the actual amount of data recieved. + // All converted data is returned to "ioData" (AudioBufferList). + err = AudioConverterFillComplexBuffer(myData->converter, MyACComplexInputProc, + inInputDataProcUserData, &inNumFrames, + ioData, outPacketDescription); + + /*Parameters for AudioConverterFillComplexBuffer() converter - the converter being used ACComplexInputProc() - input procedure to supply data to the Audio Converter -inInputDataProcUserData - Used to hold any data that needs to be passed on. Not needed in this example. +inInputDataProcUserData - Used to hold any data that needs to be passed on. Not +needed in this example. inNumFrames - The amount of requested data. On output, this number is the amount actually received. ioData - Buffer of the converted data recieved on return -outPacketDescription - contains the format of the returned data. Not used in this example. +outPacketDescription - contains the format of the returned data. Not used in +this example. */ - //checkStatus(err); - return err; + // checkStatus(err); + return err; } -} //extern "C" - -void PrintStreamDesc(AudioStreamBasicDescription *inDesc) -{ - if (!inDesc) { - printf("Can't print a NULL desc!\n"); - return; - } - - printf("- - - - - - - - - - - - - - - - - - - -\n"); - printf(" Sample Rate:%f\n", inDesc->mSampleRate); - printf(" Format ID:%.*s\n", (int)sizeof(inDesc->mFormatID), (char *)&inDesc->mFormatID); - printf(" Format Flags:%lX\n", inDesc->mFormatFlags); - printf(" Bytes per Packet:%ld\n", inDesc->mBytesPerPacket); - printf(" Frames per Packet:%ld\n", inDesc->mFramesPerPacket); - printf(" Bytes per Frame:%ld\n", inDesc->mBytesPerFrame); - printf(" Channels per Frame:%ld\n", inDesc->mChannelsPerFrame); - printf(" Bits per Channel:%ld\n", inDesc->mBitsPerChannel); - printf("- - - - - - - - - - - - - - - - - - - -\n"); -} +} // extern "C" -bool TSoundOutputDeviceImp::doOpenDevice() -{ - m_opened = false; - OSStatus err = noErr; - ComponentDescription desc; - Component comp; - - desc.componentType = kAudioUnitType_Output; - desc.componentSubType = kAudioUnitSubType_DefaultOutput; - //all Audio Units in AUComponent.h must use "kAudioUnitManufacturer_Apple" as the Manufacturer - desc.componentManufacturer = kAudioUnitManufacturer_Apple; - desc.componentFlags = 0; - desc.componentFlagsMask = 0; - - comp = FindNextComponent(NULL, &desc); //Finds an component that meets the desc spec's - if (comp == NULL) - return false; - err = OpenAComponent(comp, &theOutputUnit); //gains access to the services provided by the component - if (err) - return false; - - UInt32 size; - Boolean outWritable; - UInt32 theInputBus = 0; - //Gets the size of the Stream Format Property and if it is writable - err = AudioUnitGetPropertyInfo(theOutputUnit, - kAudioUnitProperty_StreamFormat, - kAudioUnitScope_Output, - 0, &size, &outWritable); - //Get the current stream format of the output - err = AudioUnitGetProperty(theOutputUnit, - kAudioUnitProperty_StreamFormat, - kAudioUnitScope_Output, - 0, &outputASBD, &size); - checkStatus(err); - //Set the stream format of the output to match the input - err = AudioUnitSetProperty(theOutputUnit, - kAudioUnitProperty_StreamFormat, - kAudioUnitScope_Input, - theInputBus, - &outputASBD, - size); - checkStatus(err); - - // Initialize AudioUnit, alloc mem buffers for processing - err = AudioUnitInitialize(theOutputUnit); - checkStatus(err); - if (err == noErr) - m_opened = true; - return m_opened; -} +void PrintStreamDesc(AudioStreamBasicDescription *inDesc) { + if (!inDesc) { + printf("Can't print a NULL desc!\n"); + return; + } -bool TSoundOutputDeviceImp::doSetStreamFormat(const TSoundTrackFormat &format) -{ - if (!m_opened) - doOpenDevice(); - if (!m_opened) - return false; - - fileASBD.mSampleRate = format.m_sampleRate; - fileASBD.mFormatID = kAudioFormatLinearPCM; - fileASBD.mFormatFlags = 14; - /* -Standard flags: kAudioFormatFlagIsFloat = (1L << 0) + printf("- - - - - - - - - - - - - - - - - - - -\n"); + printf(" Sample Rate:%f\n", inDesc->mSampleRate); + printf(" Format ID:%.*s\n", (int)sizeof(inDesc->mFormatID), + (char *)&inDesc->mFormatID); + printf(" Format Flags:%lX\n", inDesc->mFormatFlags); + printf(" Bytes per Packet:%ld\n", inDesc->mBytesPerPacket); + printf(" Frames per Packet:%ld\n", inDesc->mFramesPerPacket); + printf(" Bytes per Frame:%ld\n", inDesc->mBytesPerFrame); + printf(" Channels per Frame:%ld\n", inDesc->mChannelsPerFrame); + printf(" Bits per Channel:%ld\n", inDesc->mBitsPerChannel); + printf("- - - - - - - - - - - - - - - - - - - -\n"); +} + +bool TSoundOutputDeviceImp::doOpenDevice() { + m_opened = false; + OSStatus err = noErr; + ComponentDescription desc; + Component comp; + + desc.componentType = kAudioUnitType_Output; + desc.componentSubType = kAudioUnitSubType_DefaultOutput; + // all Audio Units in AUComponent.h must use "kAudioUnitManufacturer_Apple" as + // the Manufacturer + desc.componentManufacturer = kAudioUnitManufacturer_Apple; + desc.componentFlags = 0; + desc.componentFlagsMask = 0; + + comp = FindNextComponent( + NULL, &desc); // Finds an component that meets the desc spec's + if (comp == NULL) return false; + err = OpenAComponent(comp, &theOutputUnit); // gains access to the services + // provided by the component + if (err) return false; + + UInt32 size; + Boolean outWritable; + UInt32 theInputBus = 0; + // Gets the size of the Stream Format Property and if it is writable + err = + AudioUnitGetPropertyInfo(theOutputUnit, kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Output, 0, &size, &outWritable); + // Get the current stream format of the output + err = AudioUnitGetProperty(theOutputUnit, kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Output, 0, &outputASBD, &size); + checkStatus(err); + // Set the stream format of the output to match the input + err = AudioUnitSetProperty(theOutputUnit, kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Input, theInputBus, &outputASBD, + size); + checkStatus(err); + + // Initialize AudioUnit, alloc mem buffers for processing + err = AudioUnitInitialize(theOutputUnit); + checkStatus(err); + if (err == noErr) m_opened = true; + return m_opened; +} + +bool TSoundOutputDeviceImp::doSetStreamFormat(const TSoundTrackFormat &format) { + if (!m_opened) doOpenDevice(); + if (!m_opened) return false; + + fileASBD.mSampleRate = format.m_sampleRate; + fileASBD.mFormatID = kAudioFormatLinearPCM; + fileASBD.mFormatFlags = 14; + /* +Standard flags: kAudioFormatFlagIsFloat = (1L << 0) kAudioFormatFlagIsBigEndian = (1L << 1) kAudioFormatFlagIsSignedInteger = (1L << 2) kAudioFormatFlagIsPacked = (1L << 3) @@ -312,339 +304,295 @@ kAudioFormatFlagIsAlignedHigh = (1L << 4) kAudioFormatFlagIsNonInterleaved = (1L << 5) kAudioFormatFlagsAreAllClear = (1L << 31) -Linear PCM flags: +Linear PCM flags: kLinearPCMFormatFlagIsFloat = kAudioFormatFlagIsFloat kLinearPCMFormatFlagIsBigEndian = kAudioFormatFlagIsBigEndian kLinearPCMFormatFlagIsSignedInteger = kAudioFormatFlagIsSignedInteger kLinearPCMFormatFlagIsPacked = kAudioFormatFlagIsPacked kLinearPCMFormatFlagIsAlignedHigh = kAudioFormatFlagIsAlignedHigh kLinearPCMFormatFlagIsNonInterleaved = kAudioFormatFlagIsNonInterleaved -kLinearPCMFormatFlagsAreAllClear = kAudioFormatFlagsAreAllClear +kLinearPCMFormatFlagsAreAllClear = kAudioFormatFlagsAreAllClear */ - fileASBD.mBytesPerPacket = (format.m_bitPerSample >> 3) * format.m_channelCount; - fileASBD.mFramesPerPacket = 1; - fileASBD.mBytesPerFrame = (format.m_bitPerSample >> 3) * format.m_channelCount; - fileASBD.mChannelsPerFrame = format.m_channelCount; - fileASBD.mBitsPerChannel = format.m_bitPerSample; - fileASBD.mReserved = 0; - //PrintStreamDesc(&fileASBD); - m_opened = true; - return true; + fileASBD.mBytesPerPacket = + (format.m_bitPerSample >> 3) * format.m_channelCount; + fileASBD.mFramesPerPacket = 1; + fileASBD.mBytesPerFrame = + (format.m_bitPerSample >> 3) * format.m_channelCount; + fileASBD.mChannelsPerFrame = format.m_channelCount; + fileASBD.mBitsPerChannel = format.m_bitPerSample; + fileASBD.mReserved = 0; + // PrintStreamDesc(&fileASBD); + m_opened = true; + return true; } //============================================================================== -TSoundOutputDevice::TSoundOutputDevice() : m_imp(new TSoundOutputDeviceImp) -{ - try { - supportsVolume(); - } catch (TSoundDeviceException &e) { - throw TSoundDeviceException(e.getType(), e.getMessage()); - } +TSoundOutputDevice::TSoundOutputDevice() : m_imp(new TSoundOutputDeviceImp) { + try { + supportsVolume(); + } catch (TSoundDeviceException &e) { + throw TSoundDeviceException(e.getType(), e.getMessage()); + } } //------------------------------------------------------------------------------ -TSoundOutputDevice::~TSoundOutputDevice() -{ - stop(); - close(); +TSoundOutputDevice::~TSoundOutputDevice() { + stop(); + close(); } //------------------------------------------------------------------------------ -bool TSoundOutputDevice::installed() -{ - return true; -} +bool TSoundOutputDevice::installed() { return true; } //------------------------------------------------------------------------------ -bool TSoundOutputDevice::open(const TSoundTrackP &st) -{ - if (!m_imp->doOpenDevice()) - throw TSoundDeviceException( - TSoundDeviceException::UnableOpenDevice, - "Problem to open the output device"); - if (!m_imp->doSetStreamFormat(st->getFormat())) - throw TSoundDeviceException( - TSoundDeviceException::UnableOpenDevice, - "Problem to open the output device setting some params"); - return true; +bool TSoundOutputDevice::open(const TSoundTrackP &st) { + if (!m_imp->doOpenDevice()) + throw TSoundDeviceException(TSoundDeviceException::UnableOpenDevice, + "Problem to open the output device"); + if (!m_imp->doSetStreamFormat(st->getFormat())) + throw TSoundDeviceException( + TSoundDeviceException::UnableOpenDevice, + "Problem to open the output device setting some params"); + return true; } //------------------------------------------------------------------------------ -bool TSoundOutputDevice::close() -{ - stop(); - m_imp->m_opened = false; - AudioUnitUninitialize(m_imp->theOutputUnit); //release resources without closing the component - CloseComponent(m_imp->theOutputUnit); //Terminates your application's access to the services provided - return true; +bool TSoundOutputDevice::close() { + stop(); + m_imp->m_opened = false; + AudioUnitUninitialize( + m_imp->theOutputUnit); // release resources without closing the component + CloseComponent(m_imp->theOutputUnit); // Terminates your application's access + // to the services provided + return true; } //------------------------------------------------------------------------------ -void TSoundOutputDevice::play(const TSoundTrackP &st, TINT32 s0, TINT32 s1, bool loop, bool scrubbing) -{ - //TThread::ScopedLock sl(MutexOut); - int lastSample = st->getSampleCount() - 1; - notLessThan(0, s0); - notLessThan(0, s1); +void TSoundOutputDevice::play(const TSoundTrackP &st, TINT32 s0, TINT32 s1, + bool loop, bool scrubbing) { + // TThread::ScopedLock sl(MutexOut); + int lastSample = st->getSampleCount() - 1; + notLessThan(0, s0); + notLessThan(0, s1); - notMoreThan(lastSample, s0); - notMoreThan(lastSample, s1); + notMoreThan(lastSample, s0); + notMoreThan(lastSample, s1); - if (s0 > s1) { + if (s0 > s1) { #ifdef DEBUG - cout << "s0 > s1; reorder" << endl; + cout << "s0 > s1; reorder" << endl; #endif - swap(s0, s1); - } + swap(s0, s1); + } - if (isPlaying()) { + if (isPlaying()) { #ifdef DEBUG - cout << "is playing, stop it!" << endl; + cout << "is playing, stop it!" << endl; #endif - stop(); - } - m_imp->play(st, s0, s1, loop, scrubbing); + stop(); + } + m_imp->play(st, s0, s1, loop, scrubbing); } //------------------------------------------------------------------------------ -void TSoundOutputDeviceImp::play(const TSoundTrackP &st, TINT32 s0, TINT32 s1, bool loop, bool scrubbing) -{ - if (!doSetStreamFormat(st->getFormat())) - return; - - OSStatus err = noErr; - MyData *myData = new MyData(); - - myData->imp = shared_from_this(); - UInt32 magicCookieSize = 0; - //PrintStreamDesc(&outputASBD); - err = AudioConverterNew(&fileASBD, &outputASBD, &converter); - checkStatus(err); - err = AudioFileGetPropertyInfo(musicFileID, - kAudioFilePropertyMagicCookieData, - &magicCookieSize, - NULL); - - if (err == noErr) { - void *magicCookie = calloc(1, magicCookieSize); - if (magicCookie) { - //Get Magic Cookie data from Audio File - err = AudioFileGetProperty(musicFileID, - kAudioFilePropertyMagicCookieData, - &magicCookieSize, - magicCookie); - - // Give the AudioConverter the magic cookie decompression params if there are any - if (err == noErr) { - err = AudioConverterSetProperty(myData->converter, - kAudioConverterDecompressionMagicCookie, - magicCookieSize, - magicCookie); - } - err = noErr; - if (magicCookie) - free(magicCookie); - } - } else //this is OK because some audio data doesn't need magic cookie data - err = noErr; - - checkStatus(err); - myData->converter = converter; - myData->totalPacketCount = s1 - s0; - myData->fileByteCount = (s1 - s0) * st->getSampleSize(); - myData->entireFileBuffer = new char[myData->fileByteCount]; +void TSoundOutputDeviceImp::play(const TSoundTrackP &st, TINT32 s0, TINT32 s1, + bool loop, bool scrubbing) { + if (!doSetStreamFormat(st->getFormat())) return; + + OSStatus err = noErr; + MyData *myData = new MyData(); + + myData->imp = shared_from_this(); + UInt32 magicCookieSize = 0; + // PrintStreamDesc(&outputASBD); + err = AudioConverterNew(&fileASBD, &outputASBD, &converter); + checkStatus(err); + err = AudioFileGetPropertyInfo(musicFileID, kAudioFilePropertyMagicCookieData, + &magicCookieSize, NULL); + + if (err == noErr) { + void *magicCookie = calloc(1, magicCookieSize); + if (magicCookie) { + // Get Magic Cookie data from Audio File + err = AudioFileGetProperty(musicFileID, kAudioFilePropertyMagicCookieData, + &magicCookieSize, magicCookie); + + // Give the AudioConverter the magic cookie decompression params if there + // are any + if (err == noErr) { + err = AudioConverterSetProperty(myData->converter, + kAudioConverterDecompressionMagicCookie, + magicCookieSize, magicCookie); + } + err = noErr; + if (magicCookie) free(magicCookie); + } + } else // this is OK because some audio data doesn't need magic cookie data + err = noErr; + + checkStatus(err); + myData->converter = converter; + myData->totalPacketCount = s1 - s0; + myData->fileByteCount = (s1 - s0) * st->getSampleSize(); + myData->entireFileBuffer = new char[myData->fileByteCount]; #if defined(i386) - if (st->getBitPerSample() == 16) { - int i; - USHORT *dst = (USHORT *)(myData->entireFileBuffer); - USHORT *src = (USHORT *)(st->getRawData() + s0 * st->getSampleSize()); - - for (i = 0; i < myData->fileByteCount / 2; i++) - *dst++ = swapUshort(*src++); - } else - memcpy(myData->entireFileBuffer, st->getRawData() + s0 * st->getSampleSize(), myData->fileByteCount); + if (st->getBitPerSample() == 16) { + int i; + USHORT *dst = (USHORT *)(myData->entireFileBuffer); + USHORT *src = (USHORT *)(st->getRawData() + s0 * st->getSampleSize()); + + for (i = 0; i < myData->fileByteCount / 2; i++) *dst++ = swapUshort(*src++); + } else + memcpy(myData->entireFileBuffer, + st->getRawData() + s0 * st->getSampleSize(), myData->fileByteCount); #else - memcpy(myData->entireFileBuffer, st->getRawData() + s0 * st->getSampleSize(), myData->fileByteCount); + memcpy(myData->entireFileBuffer, st->getRawData() + s0 * st->getSampleSize(), + myData->fileByteCount); #endif - myData->maxPacketSize = fileASBD.mFramesPerPacket * fileASBD.mBytesPerFrame; - { - //TThread::ScopedLock sl(MutexOut); - m_isPlaying = true; - } - myData->isLooping = loop; + myData->maxPacketSize = fileASBD.mFramesPerPacket * fileASBD.mBytesPerFrame; + { + // TThread::ScopedLock sl(MutexOut); + m_isPlaying = true; + } + myData->isLooping = loop; - //cout << "total packet count = " << myData->totalPacketCount <fileByteCount << endl; + // cout << "total packet count = " << myData->totalPacketCount <fileByteCount << endl; - AURenderCallbackStruct renderCallback; - memset(&renderCallback, 0, sizeof(AURenderCallbackStruct)); + AURenderCallbackStruct renderCallback; + memset(&renderCallback, 0, sizeof(AURenderCallbackStruct)); - renderCallback.inputProc = MyFileRenderProc; - renderCallback.inputProcRefCon = myData; + renderCallback.inputProc = MyFileRenderProc; + renderCallback.inputProcRefCon = myData; - //Sets the callback for the Audio Unit to the renderCallback - err = AudioUnitSetProperty(theOutputUnit, - kAudioUnitProperty_SetRenderCallback, - kAudioUnitScope_Input, - 0, &renderCallback, - sizeof(AURenderCallbackStruct)); + // Sets the callback for the Audio Unit to the renderCallback + err = + AudioUnitSetProperty(theOutputUnit, kAudioUnitProperty_SetRenderCallback, + kAudioUnitScope_Input, 0, &renderCallback, + sizeof(AURenderCallbackStruct)); - checkStatus(err); + checkStatus(err); - err = AudioOutputUnitStart(theOutputUnit); + err = AudioOutputUnitStart(theOutputUnit); - checkStatus(err); + checkStatus(err); } //------------------------------------------------------------------------------ -bool TSoundOutputDeviceImp::doStopDevice() -{ - m_isPlaying = false; - AudioOutputUnitStop(theOutputUnit); //you must stop the audio unit from processing - AudioConverterDispose(converter); //deallocates the memory used by inAudioConverter - return true; +bool TSoundOutputDeviceImp::doStopDevice() { + m_isPlaying = false; + AudioOutputUnitStop( + theOutputUnit); // you must stop the audio unit from processing + AudioConverterDispose( + converter); // deallocates the memory used by inAudioConverter + return true; } //------------------------------------------------------------------------------ -void TSoundOutputDevice::stop() -{ - //TThread::ScopedLock sl(MutexOut); - if (m_imp->m_opened == false) - return; +void TSoundOutputDevice::stop() { + // TThread::ScopedLock sl(MutexOut); + if (m_imp->m_opened == false) return; - //TThread::ScopedLock sl(MutexOut); - m_imp->doStopDevice(); + // TThread::ScopedLock sl(MutexOut); + m_imp->doStopDevice(); } //------------------------------------------------------------------------------ -void TSoundOutputDevice::attach(TSoundOutputDeviceListener *listener) -{ - m_imp->m_listeners.insert(listener); +void TSoundOutputDevice::attach(TSoundOutputDeviceListener *listener) { + m_imp->m_listeners.insert(listener); } //------------------------------------------------------------------------------ -void TSoundOutputDevice::detach(TSoundOutputDeviceListener *listener) -{ - m_imp->m_listeners.erase(listener); +void TSoundOutputDevice::detach(TSoundOutputDeviceListener *listener) { + m_imp->m_listeners.erase(listener); } //------------------------------------------------------------------------------ -double TSoundOutputDevice::getVolume() -{ - if (!m_imp->m_opened) - m_imp->doOpenDevice(); - - Float32 leftVol, rightVol; - AudioUnitGetParameter( - m_imp->theOutputUnit, - kHALOutputParam_Volume, - kAudioUnitScope_Output, - 0, - &leftVol); - - AudioUnitGetParameter( - m_imp->theOutputUnit, - kHALOutputParam_Volume, - kAudioUnitScope_Output, - 0, - &rightVol); - double vol = (leftVol + rightVol) / 2; - - return (vol < 0. ? 0. : vol); +double TSoundOutputDevice::getVolume() { + if (!m_imp->m_opened) m_imp->doOpenDevice(); + + Float32 leftVol, rightVol; + AudioUnitGetParameter(m_imp->theOutputUnit, kHALOutputParam_Volume, + kAudioUnitScope_Output, 0, &leftVol); + + AudioUnitGetParameter(m_imp->theOutputUnit, kHALOutputParam_Volume, + kAudioUnitScope_Output, 0, &rightVol); + double vol = (leftVol + rightVol) / 2; + + return (vol < 0. ? 0. : vol); } //------------------------------------------------------------------------------ -bool TSoundOutputDevice::setVolume(double volume) -{ - Float32 vol = volume; - AudioUnitSetParameter( - m_imp->theOutputUnit, - kHALOutputParam_Volume, - kAudioUnitScope_Output, - 0, - vol, - 0); - - AudioUnitSetParameter( - m_imp->theOutputUnit, - kHALOutputParam_Volume, - kAudioUnitScope_Output, - 0, - vol, - 0); - return true; +bool TSoundOutputDevice::setVolume(double volume) { + Float32 vol = volume; + AudioUnitSetParameter(m_imp->theOutputUnit, kHALOutputParam_Volume, + kAudioUnitScope_Output, 0, vol, 0); + + AudioUnitSetParameter(m_imp->theOutputUnit, kHALOutputParam_Volume, + kAudioUnitScope_Output, 0, vol, 0); + return true; } //------------------------------------------------------------------------------ -bool TSoundOutputDevice::supportsVolume() -{ - return true; -} +bool TSoundOutputDevice::supportsVolume() { return true; } //------------------------------------------------------------------------------ -bool TSoundOutputDevice::isPlaying() const -{ - // TThread::ScopedLock sl(MutexOut); - return m_imp->m_isPlaying; +bool TSoundOutputDevice::isPlaying() const { + // TThread::ScopedLock sl(MutexOut); + return m_imp->m_isPlaying; } //------------------------------------------------------------------------------ -bool TSoundOutputDevice::isLooping() -{ - //TThread::ScopedLock sl(MutexOut); - return m_imp->m_looped; +bool TSoundOutputDevice::isLooping() { + // TThread::ScopedLock sl(MutexOut); + return m_imp->m_looped; } //------------------------------------------------------------------------------ -void TSoundOutputDevice::setLooping(bool loop) -{ - //TThread::ScopedLock sl(MutexOut); - m_imp->m_looped = loop; +void TSoundOutputDevice::setLooping(bool loop) { + // TThread::ScopedLock sl(MutexOut); + m_imp->m_looped = loop; } //------------------------------------------------------------------------------ -TSoundTrackFormat TSoundOutputDevice::getPreferredFormat( - TUINT32 sampleRate, int channelCount, int bitPerSample) -{ - TSoundTrackFormat fmt( - sampleRate, - bitPerSample, - channelCount, - true); - return fmt; +TSoundTrackFormat TSoundOutputDevice::getPreferredFormat(TUINT32 sampleRate, + int channelCount, + int bitPerSample) { + TSoundTrackFormat fmt(sampleRate, bitPerSample, channelCount, true); + return fmt; } //------------------------------------------------------------------------------ -TSoundTrackFormat TSoundOutputDevice::getPreferredFormat(const TSoundTrackFormat &format) -{ - // try { - return getPreferredFormat( - format.m_sampleRate, format.m_channelCount, format.m_bitPerSample); - /*} - catch (TSoundDeviceException &e) { - throw TSoundDeviceException( e.getType(), e.getMessage()); - }*/ +TSoundTrackFormat TSoundOutputDevice::getPreferredFormat( + const TSoundTrackFormat &format) { + // try { + return getPreferredFormat(format.m_sampleRate, format.m_channelCount, + format.m_bitPerSample); + /*} +catch (TSoundDeviceException &e) { +throw TSoundDeviceException( e.getType(), e.getMessage()); +}*/ } //============================================================================== @@ -653,153 +601,131 @@ TSoundTrackFormat TSoundOutputDevice::getPreferredFormat(const TSoundTrackFormat //============================================================================== //============================================================================== -class TSoundInputDeviceImp -{ +class TSoundInputDeviceImp { public: - //ALport m_port; - bool m_stopped; - bool m_isRecording; - bool m_oneShotRecording; + // ALport m_port; + bool m_stopped; + bool m_isRecording; + bool m_oneShotRecording; - long m_recordedSampleCount; + long m_recordedSampleCount; - TSoundTrackFormat m_currentFormat; - TSoundTrackP m_st; - std::set m_supportedRate; + TSoundTrackFormat m_currentFormat; + TSoundTrackP m_st; + std::set m_supportedRate; - TThread::Executor m_executor; + TThread::Executor m_executor; - TSoundInputDeviceImp() - : m_stopped(false), m_isRecording(false) - // , m_port(NULL) - , - m_oneShotRecording(false), m_recordedSampleCount(0), m_st(0), m_supportedRate(){}; + TSoundInputDeviceImp() + : m_stopped(false) + , m_isRecording(false) + // , m_port(NULL) + , m_oneShotRecording(false) + , m_recordedSampleCount(0) + , m_st(0) + , m_supportedRate(){}; - ~TSoundInputDeviceImp(){}; + ~TSoundInputDeviceImp(){}; - bool doOpenDevice(const TSoundTrackFormat &format, - TSoundInputDevice::Source devType); + bool doOpenDevice(const TSoundTrackFormat &format, + TSoundInputDevice::Source devType); }; bool TSoundInputDeviceImp::doOpenDevice(const TSoundTrackFormat &format, - TSoundInputDevice::Source devType) -{ - return true; + TSoundInputDevice::Source devType) { + return true; } //============================================================================== -class RecordTask : public TThread::Runnable -{ +class RecordTask : public TThread::Runnable { public: - TSoundInputDeviceImp *m_devImp; - int m_ByteToSample; + TSoundInputDeviceImp *m_devImp; + int m_ByteToSample; - RecordTask(TSoundInputDeviceImp *devImp, int numByte) - : TThread::Runnable(), m_devImp(devImp), m_ByteToSample(numByte){}; + RecordTask(TSoundInputDeviceImp *devImp, int numByte) + : TThread::Runnable(), m_devImp(devImp), m_ByteToSample(numByte){}; - ~RecordTask(){}; + ~RecordTask(){}; - void run(); + void run(); }; -void RecordTask::run() -{ -} +void RecordTask::run() {} //============================================================================== -TSoundInputDevice::TSoundInputDevice() : m_imp(new TSoundInputDeviceImp) -{ -} +TSoundInputDevice::TSoundInputDevice() : m_imp(new TSoundInputDeviceImp) {} //------------------------------------------------------------------------------ -TSoundInputDevice::~TSoundInputDevice() -{ -} +TSoundInputDevice::~TSoundInputDevice() {} //------------------------------------------------------------------------------ -bool TSoundInputDevice::installed() -{ - /* - if (alQueryValues(AL_SYSTEM, AL_DEFAULT_INPUT, 0, 0, 0, 0) <=0) - return false; - */ - return true; +bool TSoundInputDevice::installed() { + /* + if (alQueryValues(AL_SYSTEM, AL_DEFAULT_INPUT, 0, 0, 0, 0) <=0) +return false; +*/ + return true; } //------------------------------------------------------------------------------ -void TSoundInputDevice::record(const TSoundTrackFormat &format, TSoundInputDevice::Source type) -{ -} +void TSoundInputDevice::record(const TSoundTrackFormat &format, + TSoundInputDevice::Source type) {} //------------------------------------------------------------------------------ -void TSoundInputDevice::record(const TSoundTrackP &st, TSoundInputDevice::Source type) -{ -} +void TSoundInputDevice::record(const TSoundTrackP &st, + TSoundInputDevice::Source type) {} //------------------------------------------------------------------------------ -TSoundTrackP TSoundInputDevice::stop() -{ - TSoundTrackP st; - return st; +TSoundTrackP TSoundInputDevice::stop() { + TSoundTrackP st; + return st; } //------------------------------------------------------------------------------ -double TSoundInputDevice::getVolume() -{ - return 0.0; -} +double TSoundInputDevice::getVolume() { return 0.0; } //------------------------------------------------------------------------------ -bool TSoundInputDevice::setVolume(double volume) -{ - return true; -} +bool TSoundInputDevice::setVolume(double volume) { return true; } //------------------------------------------------------------------------------ -bool TSoundInputDevice::supportsVolume() -{ - return true; -} +bool TSoundInputDevice::supportsVolume() { return true; } //------------------------------------------------------------------------------ -TSoundTrackFormat TSoundInputDevice::getPreferredFormat( - TUINT32 sampleRate, int channelCount, int bitPerSample) -{ - TSoundTrackFormat fmt; - return fmt; +TSoundTrackFormat TSoundInputDevice::getPreferredFormat(TUINT32 sampleRate, + int channelCount, + int bitPerSample) { + TSoundTrackFormat fmt; + return fmt; } //------------------------------------------------------------------------------ -TSoundTrackFormat TSoundInputDevice::getPreferredFormat(const TSoundTrackFormat &format) -{ - /* - try { - */ - return getPreferredFormat( - format.m_sampleRate, format.m_channelCount, format.m_bitPerSample); - /*} - - catch (TSoundDeviceException &e) { - throw TSoundDeviceException( e.getType(), e.getMessage()); - } - */ +TSoundTrackFormat TSoundInputDevice::getPreferredFormat( + const TSoundTrackFormat &format) { + /* +try { +*/ + return getPreferredFormat(format.m_sampleRate, format.m_channelCount, + format.m_bitPerSample); + /*} + +catch (TSoundDeviceException &e) { +throw TSoundDeviceException( e.getType(), e.getMessage()); +} +*/ } //------------------------------------------------------------------------------ -bool TSoundInputDevice::isRecording() -{ - return m_imp->m_isRecording; -} +bool TSoundInputDevice::isRecording() { return m_imp->m_isRecording; } diff --git a/toonz/sources/common/tsound/tsound_nt.cpp b/toonz/sources/common/tsound/tsound_nt.cpp index 484927c..ee03aff 100644 --- a/toonz/sources/common/tsound/tsound_nt.cpp +++ b/toonz/sources/common/tsound/tsound_nt.cpp @@ -13,48 +13,33 @@ //========================================================= -//forward declarations +// forward declarations class TSoundOutputDeviceImp; class TSoundInputDeviceImp; //========================================================= -namespace -{ -void CALLBACK recordCB( - HWAVEIN hwi, - UINT uMsg, - DWORD dwInstance, - DWORD dwParam1, - DWORD dwParam2); +namespace { +void CALLBACK recordCB(HWAVEIN hwi, UINT uMsg, DWORD dwInstance, DWORD dwParam1, + DWORD dwParam2); bool setRecordLine(TSoundInputDevice::Source typeInput); -MMRESULT getLineInfo( - HMIXEROBJ hMixer, - DWORD dwComponentType, - MIXERLINE &mxl); +MMRESULT getLineInfo(HMIXEROBJ hMixer, DWORD dwComponentType, MIXERLINE &mxl); -MMRESULT getLineControl( - MIXERCONTROL &mxc, - HMIXEROBJ hMixer, - DWORD dwLineID, - DWORD dwControlType); +MMRESULT getLineControl(MIXERCONTROL &mxc, HMIXEROBJ hMixer, DWORD dwLineID, + DWORD dwControlType); -MMRESULT setControlDetails( - HMIXEROBJ hMixer, - DWORD dwSelectControlID, - DWORD dwMultipleItems, - MIXERCONTROLDETAILS_UNSIGNED *mxcdSelectValue); +MMRESULT setControlDetails(HMIXEROBJ hMixer, DWORD dwSelectControlID, + DWORD dwMultipleItems, + MIXERCONTROLDETAILS_UNSIGNED *mxcdSelectValue); -MMRESULT getControlDetails( - HMIXEROBJ hMixer, - DWORD dwSelectControlID, - DWORD dwMultipleItems, - MIXERCONTROLDETAILS_UNSIGNED *mxcdSelectValue); +MMRESULT getControlDetails(HMIXEROBJ hMixer, DWORD dwSelectControlID, + DWORD dwMultipleItems, + MIXERCONTROLDETAILS_UNSIGNED *mxcdSelectValue); -MMRESULT isaFormatSupported( - int sampleRate, int channelCount, int bitPerSample, bool input); +MMRESULT isaFormatSupported(int sampleRate, int channelCount, int bitPerSample, + bool input); DWORD WINAPI MyWaveOutCallbackThread(LPVOID lpParameter); void getAmplitude(int &litude, const TSoundTrackP st, TINT32 sample); @@ -64,863 +49,806 @@ void getAmplitude(int &litude, const TSoundTrackP st, TINT32 sample); // Class to send the message that a playback is completed //============================================================================== #ifndef TNZCORE_LIGHT -class EndPlayMsg : public TThread::Message -{ +class EndPlayMsg : public TThread::Message { public: - EndPlayMsg(TSoundOutputDeviceListener *notifier) - { - m_listener = notifier; - } + EndPlayMsg(TSoundOutputDeviceListener *notifier) { m_listener = notifier; } - TThread::Message *clone() const - { - return new EndPlayMsg(*this); - } + TThread::Message *clone() const { return new EndPlayMsg(*this); } - void onDeliver() - { - m_listener->onPlayCompleted(); - } + void onDeliver() { m_listener->onPlayCompleted(); } private: - TSoundOutputDeviceListener *m_listener; + TSoundOutputDeviceListener *m_listener; }; #endif -int makeDWORD(const short lo, const short hi) -{ - int dw = hi << 16; - dw |= lo; - return dw; +int makeDWORD(const short lo, const short hi) { + int dw = hi << 16; + dw |= lo; + return dw; } //============================================================================== class WavehdrQueue; -class TSoundOutputDeviceImp -{ +class TSoundOutputDeviceImp { public: - HWAVEOUT m_wout; - WavehdrQueue *m_whdrQueue; - TSoundTrackFormat m_currentFormat; - std::set m_supportedRate; + HWAVEOUT m_wout; + WavehdrQueue *m_whdrQueue; + TSoundTrackFormat m_currentFormat; + std::set m_supportedRate; - TThread::Mutex m_mutex; + TThread::Mutex m_mutex; - bool m_stopped; - bool m_isPlaying; - bool m_looped; - bool m_scrubbing; + bool m_stopped; + bool m_isPlaying; + bool m_looped; + bool m_scrubbing; - std::set m_listeners; - DWORD m_notifyThreadId; + std::set m_listeners; + DWORD m_notifyThreadId; - HANDLE m_closeDevice; + HANDLE m_closeDevice; - TSoundOutputDeviceImp(); - ~TSoundOutputDeviceImp(); + TSoundOutputDeviceImp(); + ~TSoundOutputDeviceImp(); - bool doOpenDevice(const TSoundTrackFormat &format); - bool doPlay(WAVEHDR *whdr, const TSoundTrackFormat format); - bool doCloseDevice(); + bool doOpenDevice(const TSoundTrackFormat &format); + bool doPlay(WAVEHDR *whdr, const TSoundTrackFormat format); + bool doCloseDevice(); - bool verifyRate(); - void insertAllRate(); + bool verifyRate(); + void insertAllRate(); }; //============================================================================== -class WavehdrQueue -{ +class WavehdrQueue { public: - WavehdrQueue(TSoundOutputDeviceImp *devImp, int slotCount) - : m_devImp(devImp), m_items(), m_queuedItems(), m_slotCount(slotCount), m_mutex(), m_lastOffset(0) - { - } - - ~WavehdrQueue() {} - - void put(TSoundTrackP &subTrack); - WAVEHDR *get(); - bool popFront(int count); - void pushBack(WAVEHDR *whdr, TSoundTrackP st); - int size(); - void clear(); - bool isAllQueuedItemsPlayed(); + WavehdrQueue(TSoundOutputDeviceImp *devImp, int slotCount) + : m_devImp(devImp) + , m_items() + , m_queuedItems() + , m_slotCount(slotCount) + , m_mutex() + , m_lastOffset(0) {} + + ~WavehdrQueue() {} + + void put(TSoundTrackP &subTrack); + WAVEHDR *get(); + bool popFront(int count); + void pushBack(WAVEHDR *whdr, TSoundTrackP st); + int size(); + void clear(); + bool isAllQueuedItemsPlayed(); private: - std::list> m_items; - std::list m_queuedItems; - - TThread::Mutex m_mutex; - int m_slotCount; - int m_lastOffset; - TSoundOutputDeviceImp *m_devImp; - TSoundTrackP m_lastTrack; + std::list> m_items; + std::list m_queuedItems; + + TThread::Mutex m_mutex; + int m_slotCount; + int m_lastOffset; + TSoundOutputDeviceImp *m_devImp; + TSoundTrackP m_lastTrack; }; //============================================================================== -WAVEHDR *prepareWaveHeader(HWAVEOUT wout, const TSoundTrackP &subTrack, ULONG &count) -{ - WAVEHDR *whdr = new WAVEHDR; - memset(whdr, 0, sizeof(WAVEHDR)); - whdr->dwBufferLength = subTrack->getSampleSize() * subTrack->getSampleCount(); - whdr->lpData = new char[whdr->dwBufferLength]; - whdr->dwFlags = 0; - whdr->dwUser = count; - memcpy(whdr->lpData, subTrack->getRawData(), whdr->dwBufferLength); - - MMRESULT ret = waveOutPrepareHeader(wout, whdr, sizeof(WAVEHDR)); - if (ret != MMSYSERR_NOERROR) { - delete[] whdr->lpData; - delete whdr; - return 0; - } - ++count; - return whdr; +WAVEHDR *prepareWaveHeader(HWAVEOUT wout, const TSoundTrackP &subTrack, + ULONG &count) { + WAVEHDR *whdr = new WAVEHDR; + memset(whdr, 0, sizeof(WAVEHDR)); + whdr->dwBufferLength = subTrack->getSampleSize() * subTrack->getSampleCount(); + whdr->lpData = new char[whdr->dwBufferLength]; + whdr->dwFlags = 0; + whdr->dwUser = count; + memcpy(whdr->lpData, subTrack->getRawData(), whdr->dwBufferLength); + + MMRESULT ret = waveOutPrepareHeader(wout, whdr, sizeof(WAVEHDR)); + if (ret != MMSYSERR_NOERROR) { + delete[] whdr->lpData; + delete whdr; + return 0; + } + ++count; + return whdr; } //============================================================================== -void WavehdrQueue::put(TSoundTrackP &subTrack) -{ - assert(subTrack->getRawData()); - static ULONG count = 1; - - //codice messo per tab: facendo il play al rilascio del mouse e su piu' - //colonne in cui le traccie potrebbe avere diversi formati siccome qui in - //alcune situazioni si fa subito waveOutWrite c'e' bisogno di controllare - //se il formato con cui e' stato aperto in precedenza il device e' uguale - //a quello della traccia - if (m_devImp->m_wout && m_devImp->m_currentFormat != subTrack->getFormat()) { - m_devImp->doCloseDevice(); - TSystem::sleep(300); - m_devImp->doOpenDevice(subTrack->getFormat()); - } - - TThread::MutexLocker sl(&m_mutex); - if (!m_devImp->m_scrubbing) { - WAVEHDR *whdr2 = 0; - - //traccia - whdr2 = prepareWaveHeader(m_devImp->m_wout, subTrack, count); - getAmplitude(m_lastOffset, subTrack, subTrack->getSampleCount() - 1L); - - MMRESULT ret = MMSYSERR_NOERROR; - - if (whdr2 && whdr2->dwFlags & WHDR_PREPARED) { - ret = waveOutWrite(m_devImp->m_wout, whdr2, sizeof(WAVEHDR)); - if (ret == MMSYSERR_NOERROR) { - pushBack(whdr2, subTrack); - getAmplitude(m_lastOffset, subTrack, subTrack->getSampleCount() - 1L); - TThread::MutexLocker sl(&m_devImp->m_mutex); - m_devImp->m_isPlaying = true; - m_devImp->m_stopped = false; - } - } - return; - } - - if (m_queuedItems.size() == 0) { - WAVEHDR *whdr1 = 0; - WAVEHDR *whdr2 = 0; - WAVEHDR *whdr3 = 0; - - MMRESULT ret; - TSoundTrackP riseTrack, decayTrack; - int sampleSize = subTrack->getSampleSize(); - - //cresce - riseTrack = TSop::fadeIn(subTrack, 0.9); - whdr1 = prepareWaveHeader(m_devImp->m_wout, riseTrack, count); - - //traccia - whdr2 = prepareWaveHeader(m_devImp->m_wout, subTrack, count); - - getAmplitude(m_lastOffset, subTrack, subTrack->getSampleCount() - 1L); - - //decresce - decayTrack = 0; - if (m_lastOffset) { - decayTrack = TSop::fadeOut(subTrack, 0.9); - whdr3 = prepareWaveHeader(m_devImp->m_wout, decayTrack, count); - } - - if (whdr1 && (whdr1->dwFlags & WHDR_PREPARED)) { - ret = waveOutWrite(m_devImp->m_wout, whdr1, sizeof(WAVEHDR)); - if (ret == MMSYSERR_NOERROR) { - pushBack(whdr1, riseTrack); - getAmplitude(m_lastOffset, riseTrack, riseTrack->getSampleCount() - 1L); - } - } - if (whdr2 && (whdr2->dwFlags & WHDR_PREPARED)) { - ret = waveOutWrite(m_devImp->m_wout, whdr2, sizeof(WAVEHDR)); - if (ret == MMSYSERR_NOERROR) { - pushBack(whdr2, subTrack); - getAmplitude(m_lastOffset, subTrack, subTrack->getSampleCount() - 1L); - TThread::MutexLocker sl(&m_devImp->m_mutex); - m_devImp->m_isPlaying = true; - m_devImp->m_stopped = false; - } - } - if (whdr3 && (whdr3->dwFlags & WHDR_PREPARED)) { - ret = waveOutWrite(m_devImp->m_wout, whdr3, sizeof(WAVEHDR)); - if (ret == MMSYSERR_NOERROR) { - pushBack(whdr3, decayTrack); - if (decayTrack->isSampleSigned()) - m_lastOffset = 0; - else - m_lastOffset = 127; - } - } - return; - } - - if (m_queuedItems.size() < 10) { - WAVEHDR *whdr1 = 0; - WAVEHDR *whdr2 = 0; - WAVEHDR *whdr = new WAVEHDR; - memset(whdr, 0, sizeof(WAVEHDR)); - whdr->dwBufferLength = subTrack->getSampleSize() * subTrack->getSampleCount(); - whdr->lpData = new char[whdr->dwBufferLength]; - whdr->dwFlags = 0; - memcpy(whdr->lpData, subTrack->getRawData(), whdr->dwBufferLength); - int sampleSize = subTrack->getSampleSize(); - TSoundTrackP riseTrack = 0; - - if (m_lastOffset) ///devo fare ilcross fade - { - int offset; - getAmplitude(offset, subTrack, 0L); - - offset = m_lastOffset - offset; - if (offset) { - TSoundTrackP st = TSop::crossFade(m_lastTrack, subTrack, 0.3); - memcpy(whdr->lpData, st->getRawData(), st->getSampleCount() * sampleSize); - } - } else // e' zero ma ne metto uno che cresce faccio il fadeIn - { - riseTrack = TSop::fadeIn(subTrack, 0.3); - whdr1 = prepareWaveHeader(m_devImp->m_wout, riseTrack, count); - } - - whdr->dwUser = count; - ++count; - MMRESULT ret = waveOutPrepareHeader(m_devImp->m_wout, whdr, sizeof(WAVEHDR)); - if (ret != MMSYSERR_NOERROR) { - delete[] whdr->lpData; - delete whdr; - return; - } - - getAmplitude(m_lastOffset, subTrack, subTrack->getSampleCount() - 1L); - - TSoundTrackP decayTrack = 0; - if (m_queuedItems.size() <= 7) { - if (m_lastOffset) //devo fare il fadeOut - { - decayTrack = TSop::fadeOut(subTrack, 0.3); - whdr2 = prepareWaveHeader(m_devImp->m_wout, decayTrack, count); - } - } - - if (whdr1 && whdr1->dwFlags & WHDR_PREPARED) { - ret = waveOutWrite(m_devImp->m_wout, whdr1, sizeof(WAVEHDR)); - if (ret == MMSYSERR_NOERROR) { - pushBack(whdr1, riseTrack); - getAmplitude(m_lastOffset, riseTrack, riseTrack->getSampleCount() - 1L); - } - } - - if (whdr && whdr->dwFlags & WHDR_PREPARED) { - ret = waveOutWrite(m_devImp->m_wout, whdr, sizeof(WAVEHDR)); - if (ret == MMSYSERR_NOERROR) { - pushBack(whdr, subTrack); - getAmplitude(m_lastOffset, subTrack, subTrack->getSampleCount() - 1L); - { - TThread::MutexLocker sl(&m_devImp->m_mutex); - m_devImp->m_isPlaying = true; - m_devImp->m_stopped = false; - } - } - } - - if (whdr2 && whdr2->dwFlags & WHDR_PREPARED) { - ret = waveOutWrite(m_devImp->m_wout, whdr2, sizeof(WAVEHDR)); - if (ret == MMSYSERR_NOERROR) { - pushBack(whdr2, decayTrack); - if (decayTrack->isSampleSigned()) - m_lastOffset = 0; - else - m_lastOffset = 127; - } - } - return; - } - - if ((int)m_items.size() == m_slotCount) { - WAVEHDR *item = m_items.front().first; - MMRESULT ret = waveOutUnprepareHeader( - m_devImp->m_wout, item, sizeof(WAVEHDR)); - - if (ret == MMSYSERR_NOERROR) { - delete[] item->lpData; - delete item; - } - - m_items.pop_front(); - - if (m_queuedItems.size() != 0) { - WAVEHDR *item = m_items.front().first; - int sampleSize = m_items.front().second->getSampleSize(); - int offset; - getAmplitude(offset, m_items.front().second, 0L); - - offset = m_lastOffset - offset; - if (offset) { - TSoundTrackP st = TSop::crossFade( - m_lastTrack, m_items.front().second, 0.3); - memcpy(item->lpData, st->getRawData(), st->getSampleCount() * sampleSize); - } - } - } - - WAVEHDR *whdr = prepareWaveHeader(m_devImp->m_wout, subTrack, count); - - assert(whdr && whdr->dwFlags & WHDR_PREPARED); - m_items.push_back(std::make_pair(whdr, subTrack)); - assert((int)m_items.size() <= m_slotCount); +void WavehdrQueue::put(TSoundTrackP &subTrack) { + assert(subTrack->getRawData()); + static ULONG count = 1; + + // codice messo per tab: facendo il play al rilascio del mouse e su piu' + // colonne in cui le traccie potrebbe avere diversi formati siccome qui in + // alcune situazioni si fa subito waveOutWrite c'e' bisogno di controllare + // se il formato con cui e' stato aperto in precedenza il device e' uguale + // a quello della traccia + if (m_devImp->m_wout && m_devImp->m_currentFormat != subTrack->getFormat()) { + m_devImp->doCloseDevice(); + TSystem::sleep(300); + m_devImp->doOpenDevice(subTrack->getFormat()); + } + + TThread::MutexLocker sl(&m_mutex); + if (!m_devImp->m_scrubbing) { + WAVEHDR *whdr2 = 0; + + // traccia + whdr2 = prepareWaveHeader(m_devImp->m_wout, subTrack, count); + getAmplitude(m_lastOffset, subTrack, subTrack->getSampleCount() - 1L); + + MMRESULT ret = MMSYSERR_NOERROR; + + if (whdr2 && whdr2->dwFlags & WHDR_PREPARED) { + ret = waveOutWrite(m_devImp->m_wout, whdr2, sizeof(WAVEHDR)); + if (ret == MMSYSERR_NOERROR) { + pushBack(whdr2, subTrack); + getAmplitude(m_lastOffset, subTrack, subTrack->getSampleCount() - 1L); + TThread::MutexLocker sl(&m_devImp->m_mutex); + m_devImp->m_isPlaying = true; + m_devImp->m_stopped = false; + } + } + return; + } + + if (m_queuedItems.size() == 0) { + WAVEHDR *whdr1 = 0; + WAVEHDR *whdr2 = 0; + WAVEHDR *whdr3 = 0; + + MMRESULT ret; + TSoundTrackP riseTrack, decayTrack; + int sampleSize = subTrack->getSampleSize(); + + // cresce + riseTrack = TSop::fadeIn(subTrack, 0.9); + whdr1 = prepareWaveHeader(m_devImp->m_wout, riseTrack, count); + + // traccia + whdr2 = prepareWaveHeader(m_devImp->m_wout, subTrack, count); + + getAmplitude(m_lastOffset, subTrack, subTrack->getSampleCount() - 1L); + + // decresce + decayTrack = 0; + if (m_lastOffset) { + decayTrack = TSop::fadeOut(subTrack, 0.9); + whdr3 = prepareWaveHeader(m_devImp->m_wout, decayTrack, count); + } + + if (whdr1 && (whdr1->dwFlags & WHDR_PREPARED)) { + ret = waveOutWrite(m_devImp->m_wout, whdr1, sizeof(WAVEHDR)); + if (ret == MMSYSERR_NOERROR) { + pushBack(whdr1, riseTrack); + getAmplitude(m_lastOffset, riseTrack, riseTrack->getSampleCount() - 1L); + } + } + if (whdr2 && (whdr2->dwFlags & WHDR_PREPARED)) { + ret = waveOutWrite(m_devImp->m_wout, whdr2, sizeof(WAVEHDR)); + if (ret == MMSYSERR_NOERROR) { + pushBack(whdr2, subTrack); + getAmplitude(m_lastOffset, subTrack, subTrack->getSampleCount() - 1L); + TThread::MutexLocker sl(&m_devImp->m_mutex); + m_devImp->m_isPlaying = true; + m_devImp->m_stopped = false; + } + } + if (whdr3 && (whdr3->dwFlags & WHDR_PREPARED)) { + ret = waveOutWrite(m_devImp->m_wout, whdr3, sizeof(WAVEHDR)); + if (ret == MMSYSERR_NOERROR) { + pushBack(whdr3, decayTrack); + if (decayTrack->isSampleSigned()) + m_lastOffset = 0; + else + m_lastOffset = 127; + } + } + return; + } + + if (m_queuedItems.size() < 10) { + WAVEHDR *whdr1 = 0; + WAVEHDR *whdr2 = 0; + WAVEHDR *whdr = new WAVEHDR; + memset(whdr, 0, sizeof(WAVEHDR)); + whdr->dwBufferLength = + subTrack->getSampleSize() * subTrack->getSampleCount(); + whdr->lpData = new char[whdr->dwBufferLength]; + whdr->dwFlags = 0; + memcpy(whdr->lpData, subTrack->getRawData(), whdr->dwBufferLength); + int sampleSize = subTrack->getSampleSize(); + TSoundTrackP riseTrack = 0; + + if (m_lastOffset) /// devo fare ilcross fade + { + int offset; + getAmplitude(offset, subTrack, 0L); + + offset = m_lastOffset - offset; + if (offset) { + TSoundTrackP st = TSop::crossFade(m_lastTrack, subTrack, 0.3); + memcpy(whdr->lpData, st->getRawData(), + st->getSampleCount() * sampleSize); + } + } else // e' zero ma ne metto uno che cresce faccio il fadeIn + { + riseTrack = TSop::fadeIn(subTrack, 0.3); + whdr1 = prepareWaveHeader(m_devImp->m_wout, riseTrack, count); + } + + whdr->dwUser = count; + ++count; + MMRESULT ret = + waveOutPrepareHeader(m_devImp->m_wout, whdr, sizeof(WAVEHDR)); + if (ret != MMSYSERR_NOERROR) { + delete[] whdr->lpData; + delete whdr; + return; + } + + getAmplitude(m_lastOffset, subTrack, subTrack->getSampleCount() - 1L); + + TSoundTrackP decayTrack = 0; + if (m_queuedItems.size() <= 7) { + if (m_lastOffset) // devo fare il fadeOut + { + decayTrack = TSop::fadeOut(subTrack, 0.3); + whdr2 = prepareWaveHeader(m_devImp->m_wout, decayTrack, count); + } + } + + if (whdr1 && whdr1->dwFlags & WHDR_PREPARED) { + ret = waveOutWrite(m_devImp->m_wout, whdr1, sizeof(WAVEHDR)); + if (ret == MMSYSERR_NOERROR) { + pushBack(whdr1, riseTrack); + getAmplitude(m_lastOffset, riseTrack, riseTrack->getSampleCount() - 1L); + } + } + + if (whdr && whdr->dwFlags & WHDR_PREPARED) { + ret = waveOutWrite(m_devImp->m_wout, whdr, sizeof(WAVEHDR)); + if (ret == MMSYSERR_NOERROR) { + pushBack(whdr, subTrack); + getAmplitude(m_lastOffset, subTrack, subTrack->getSampleCount() - 1L); + { + TThread::MutexLocker sl(&m_devImp->m_mutex); + m_devImp->m_isPlaying = true; + m_devImp->m_stopped = false; + } + } + } + + if (whdr2 && whdr2->dwFlags & WHDR_PREPARED) { + ret = waveOutWrite(m_devImp->m_wout, whdr2, sizeof(WAVEHDR)); + if (ret == MMSYSERR_NOERROR) { + pushBack(whdr2, decayTrack); + if (decayTrack->isSampleSigned()) + m_lastOffset = 0; + else + m_lastOffset = 127; + } + } + return; + } + + if ((int)m_items.size() == m_slotCount) { + WAVEHDR *item = m_items.front().first; + MMRESULT ret = + waveOutUnprepareHeader(m_devImp->m_wout, item, sizeof(WAVEHDR)); + + if (ret == MMSYSERR_NOERROR) { + delete[] item->lpData; + delete item; + } + + m_items.pop_front(); + + if (m_queuedItems.size() != 0) { + WAVEHDR *item = m_items.front().first; + int sampleSize = m_items.front().second->getSampleSize(); + int offset; + getAmplitude(offset, m_items.front().second, 0L); + + offset = m_lastOffset - offset; + if (offset) { + TSoundTrackP st = + TSop::crossFade(m_lastTrack, m_items.front().second, 0.3); + memcpy(item->lpData, st->getRawData(), + st->getSampleCount() * sampleSize); + } + } + } + + WAVEHDR *whdr = prepareWaveHeader(m_devImp->m_wout, subTrack, count); + + assert(whdr && whdr->dwFlags & WHDR_PREPARED); + m_items.push_back(std::make_pair(whdr, subTrack)); + assert((int)m_items.size() <= m_slotCount); } //---------------------------------------------------------------------------- // restituisce il piu' vecchio WAVEHDR il cui stato e' prepared && !done -WAVEHDR *WavehdrQueue::get() -{ - TThread::MutexLocker sl(&m_mutex); - if (m_items.size() == 0) - return 0; +WAVEHDR *WavehdrQueue::get() { + TThread::MutexLocker sl(&m_mutex); + if (m_items.size() == 0) return 0; - WAVEHDR *whdr = m_items.front().first; - assert(whdr->dwFlags & WHDR_PREPARED); + WAVEHDR *whdr = m_items.front().first; + assert(whdr->dwFlags & WHDR_PREPARED); - pushBack(whdr, m_items.front().second); - getAmplitude( - m_lastOffset, m_items.front().second, m_items.front().second->getSampleCount() - 1L); - m_items.pop_front(); + pushBack(whdr, m_items.front().second); + getAmplitude(m_lastOffset, m_items.front().second, + m_items.front().second->getSampleCount() - 1L); + m_items.pop_front(); - return whdr; + return whdr; } //----------------------------------------------------------------------------- // rimuove dalla coda il piu' vecchio WAVEHDR il cui stato e' done -bool WavehdrQueue::popFront(int count) -{ - TThread::MutexLocker sl(&m_mutex); - //assert(m_queuedItems.size() > 0); - if (m_queuedItems.size() <= 0) - return false; - WAVEHDR *whdr = m_queuedItems.front(); - // controllo introdotto pr via che su win2k si perde alcune - // notifiche di WHDR_DONE - while ((DWORD)count > whdr->dwUser) { - MMRESULT ret = waveOutUnprepareHeader( - m_devImp->m_wout, whdr, sizeof(WAVEHDR)); - if (ret == MMSYSERR_NOERROR) { - m_queuedItems.pop_front(); - delete[] whdr->lpData; - delete whdr; - whdr = m_queuedItems.front(); - } - } - assert(whdr->dwFlags & WHDR_DONE); - m_queuedItems.pop_front(); - delete[] whdr->lpData; - delete whdr; - return true; +bool WavehdrQueue::popFront(int count) { + TThread::MutexLocker sl(&m_mutex); + // assert(m_queuedItems.size() > 0); + if (m_queuedItems.size() <= 0) return false; + WAVEHDR *whdr = m_queuedItems.front(); + // controllo introdotto pr via che su win2k si perde alcune + // notifiche di WHDR_DONE + while ((DWORD)count > whdr->dwUser) { + MMRESULT ret = + waveOutUnprepareHeader(m_devImp->m_wout, whdr, sizeof(WAVEHDR)); + if (ret == MMSYSERR_NOERROR) { + m_queuedItems.pop_front(); + delete[] whdr->lpData; + delete whdr; + whdr = m_queuedItems.front(); + } + } + assert(whdr->dwFlags & WHDR_DONE); + m_queuedItems.pop_front(); + delete[] whdr->lpData; + delete whdr; + return true; } //----------------------------------------------------------------------------- -void WavehdrQueue::pushBack(WAVEHDR *whdr, TSoundTrackP st) -{ - TThread::MutexLocker sl(&m_mutex); - m_queuedItems.push_back(whdr); - m_lastTrack = st; +void WavehdrQueue::pushBack(WAVEHDR *whdr, TSoundTrackP st) { + TThread::MutexLocker sl(&m_mutex); + m_queuedItems.push_back(whdr); + m_lastTrack = st; } //----------------------------------------------------------------------------- -int WavehdrQueue::size() -{ - TThread::MutexLocker sl(&m_mutex); - int size = m_queuedItems.size(); - return size; +int WavehdrQueue::size() { + TThread::MutexLocker sl(&m_mutex); + int size = m_queuedItems.size(); + return size; } //----------------------------------------------------------------------------- -void WavehdrQueue::clear() -{ - TThread::MutexLocker sl(&m_mutex); - m_items.clear(); - m_lastTrack = TSoundTrackP(); - std::list::iterator it; - for (it = m_queuedItems.begin(); it != m_queuedItems.end(); it++) { - WAVEHDR *wvhdr = *it; - delete[] wvhdr->lpData; - delete wvhdr; - } - m_queuedItems.clear(); +void WavehdrQueue::clear() { + TThread::MutexLocker sl(&m_mutex); + m_items.clear(); + m_lastTrack = TSoundTrackP(); + std::list::iterator it; + for (it = m_queuedItems.begin(); it != m_queuedItems.end(); it++) { + WAVEHDR *wvhdr = *it; + delete[] wvhdr->lpData; + delete wvhdr; + } + m_queuedItems.clear(); } //----------------------------------------------------------------------------- -bool WavehdrQueue::isAllQueuedItemsPlayed() -{ - std::list::iterator it; - bool finished = true; - for (it = m_queuedItems.begin(); it != m_queuedItems.end(); it++) { - WAVEHDR *wvhdr = *it; - finished = finished && (wvhdr->dwFlags & WHDR_DONE); - } - return finished; +bool WavehdrQueue::isAllQueuedItemsPlayed() { + std::list::iterator it; + bool finished = true; + for (it = m_queuedItems.begin(); it != m_queuedItems.end(); it++) { + WAVEHDR *wvhdr = *it; + finished = finished && (wvhdr->dwFlags & WHDR_DONE); + } + return finished; } //============================================================================== TSoundOutputDeviceImp::TSoundOutputDeviceImp() - : m_stopped(true), m_isPlaying(false), m_looped(false), m_scrubbing(false), m_wout(0) -{ - m_whdrQueue = new WavehdrQueue(this, 4); + : m_stopped(true) + , m_isPlaying(false) + , m_looped(false) + , m_scrubbing(false) + , m_wout(0) { + m_whdrQueue = new WavehdrQueue(this, 4); - insertAllRate(); - if (!verifyRate()) - throw TSoundDeviceException( - TSoundDeviceException::FailedInit, - "Unable to verify supported rates"); + insertAllRate(); + if (!verifyRate()) + throw TSoundDeviceException(TSoundDeviceException::FailedInit, + "Unable to verify supported rates"); - m_closeDevice = CreateEvent( - NULL, // no security attributes - FALSE, // auto-reset event - FALSE, // initial state is not signaled - NULL); // object not named + m_closeDevice = CreateEvent(NULL, // no security attributes + FALSE, // auto-reset event + FALSE, // initial state is not signaled + NULL); // object not named } //---------------------------------------------------------------------------- -TSoundOutputDeviceImp::~TSoundOutputDeviceImp() -{ - delete m_whdrQueue; -} +TSoundOutputDeviceImp::~TSoundOutputDeviceImp() { delete m_whdrQueue; } //---------------------------------------------------------------------------- -bool TSoundOutputDeviceImp::doOpenDevice(const TSoundTrackFormat &format) -{ - WAVEFORMATEX wf; - wf.wFormatTag = WAVE_FORMAT_PCM; - wf.nChannels = format.m_channelCount; - wf.nSamplesPerSec = format.m_sampleRate; - wf.wBitsPerSample = format.m_bitPerSample; - wf.nBlockAlign = (wf.nChannels * wf.wBitsPerSample) >> 3; - wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign; - wf.cbSize = 0; - - TThread::MutexLocker sl(&m_mutex); - CloseHandle(CreateThread(NULL, 0, MyWaveOutCallbackThread, (LPVOID) this, 0, &m_notifyThreadId)); - - MMRESULT ret; - if ((ret = waveOutOpen(&m_wout, WAVE_MAPPER, - &wf, (DWORD)m_notifyThreadId, (DWORD) this, CALLBACK_THREAD)) != MMSYSERR_NOERROR) { - while (!PostThreadMessage(m_notifyThreadId, WM_QUIT, 0, 0)) - ; - } - if (ret != MMSYSERR_NOERROR) - return false; - - if (ret != MMSYSERR_NOERROR) - return false; - m_currentFormat = format; - return (ret == MMSYSERR_NOERROR); +bool TSoundOutputDeviceImp::doOpenDevice(const TSoundTrackFormat &format) { + WAVEFORMATEX wf; + wf.wFormatTag = WAVE_FORMAT_PCM; + wf.nChannels = format.m_channelCount; + wf.nSamplesPerSec = format.m_sampleRate; + wf.wBitsPerSample = format.m_bitPerSample; + wf.nBlockAlign = (wf.nChannels * wf.wBitsPerSample) >> 3; + wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign; + wf.cbSize = 0; + + TThread::MutexLocker sl(&m_mutex); + CloseHandle(CreateThread(NULL, 0, MyWaveOutCallbackThread, (LPVOID)this, 0, + &m_notifyThreadId)); + + MMRESULT ret; + if ((ret = waveOutOpen(&m_wout, WAVE_MAPPER, &wf, (DWORD)m_notifyThreadId, + (DWORD)this, CALLBACK_THREAD)) != MMSYSERR_NOERROR) { + while (!PostThreadMessage(m_notifyThreadId, WM_QUIT, 0, 0)) + ; + } + if (ret != MMSYSERR_NOERROR) return false; + + if (ret != MMSYSERR_NOERROR) return false; + m_currentFormat = format; + return (ret == MMSYSERR_NOERROR); } //---------------------------------------------------------------------------- -bool TSoundOutputDeviceImp::doPlay(WAVEHDR *whdr, const TSoundTrackFormat format) -{ - TThread::MutexLocker sl(&m_mutex); - if (!m_wout || (m_wout && m_currentFormat != format)) - doOpenDevice(format); +bool TSoundOutputDeviceImp::doPlay(WAVEHDR *whdr, + const TSoundTrackFormat format) { + TThread::MutexLocker sl(&m_mutex); + if (!m_wout || (m_wout && m_currentFormat != format)) doOpenDevice(format); - MMRESULT ret; - ret = waveOutWrite(m_wout, whdr, sizeof(WAVEHDR)); - if (ret != MMSYSERR_NOERROR) - return false; - m_stopped = false; - m_isPlaying = true; + MMRESULT ret; + ret = waveOutWrite(m_wout, whdr, sizeof(WAVEHDR)); + if (ret != MMSYSERR_NOERROR) return false; + m_stopped = false; + m_isPlaying = true; - return true; + return true; } //---------------------------------------------------------------------------- -bool TSoundOutputDeviceImp::doCloseDevice() -{ - TThread::MutexLocker sl(&m_mutex); - if (m_wout) { - MMRESULT ret = waveOutReset(m_wout); - if (ret != MMSYSERR_NOERROR) - return false; - ret = waveOutClose(m_wout); - if (ret != MMSYSERR_NOERROR) - return false; - m_wout = 0; - m_stopped = true; - m_isPlaying = false; - m_looped = false; - } - - PostThreadMessage(m_notifyThreadId, WM_QUIT, 0, 0); - return true; +bool TSoundOutputDeviceImp::doCloseDevice() { + TThread::MutexLocker sl(&m_mutex); + if (m_wout) { + MMRESULT ret = waveOutReset(m_wout); + if (ret != MMSYSERR_NOERROR) return false; + ret = waveOutClose(m_wout); + if (ret != MMSYSERR_NOERROR) return false; + m_wout = 0; + m_stopped = true; + m_isPlaying = false; + m_looped = false; + } + + PostThreadMessage(m_notifyThreadId, WM_QUIT, 0, 0); + return true; } //---------------------------------------------------------------------------- -void TSoundOutputDeviceImp::insertAllRate() -{ - m_supportedRate.insert(8000); - m_supportedRate.insert(11025); - m_supportedRate.insert(16000); - m_supportedRate.insert(22050); - m_supportedRate.insert(32000); - m_supportedRate.insert(44100); - m_supportedRate.insert(48000); +void TSoundOutputDeviceImp::insertAllRate() { + m_supportedRate.insert(8000); + m_supportedRate.insert(11025); + m_supportedRate.insert(16000); + m_supportedRate.insert(22050); + m_supportedRate.insert(32000); + m_supportedRate.insert(44100); + m_supportedRate.insert(48000); } //---------------------------------------------------------------------------- -bool TSoundOutputDeviceImp::verifyRate() -{ - std::set::iterator it; - - for (it = m_supportedRate.begin(); - it != m_supportedRate.end();) { - MMRESULT ret; - WAVEFORMATEX wf; - - wf.wFormatTag = WAVE_FORMAT_PCM; - wf.nChannels = 1; - wf.nSamplesPerSec = *it; - wf.wBitsPerSample = 8; - wf.nBlockAlign = (wf.nChannels * wf.wBitsPerSample) >> 3; - wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign; - wf.cbSize = 0; - - ret = waveOutOpen(NULL, WAVE_MAPPER, &wf, NULL, NULL, WAVE_FORMAT_QUERY); - - if (ret == MMSYSERR_NOERROR) { - ++it; - continue; - } - if (ret == WAVERR_BADFORMAT) - it = m_supportedRate.erase(it); - else - return false; - } - if (m_supportedRate.end() == m_supportedRate.begin()) - return false; - - return true; +bool TSoundOutputDeviceImp::verifyRate() { + std::set::iterator it; + + for (it = m_supportedRate.begin(); it != m_supportedRate.end();) { + MMRESULT ret; + WAVEFORMATEX wf; + + wf.wFormatTag = WAVE_FORMAT_PCM; + wf.nChannels = 1; + wf.nSamplesPerSec = *it; + wf.wBitsPerSample = 8; + wf.nBlockAlign = (wf.nChannels * wf.wBitsPerSample) >> 3; + wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign; + wf.cbSize = 0; + + ret = waveOutOpen(NULL, WAVE_MAPPER, &wf, NULL, NULL, WAVE_FORMAT_QUERY); + + if (ret == MMSYSERR_NOERROR) { + ++it; + continue; + } + if (ret == WAVERR_BADFORMAT) + it = m_supportedRate.erase(it); + else + return false; + } + if (m_supportedRate.end() == m_supportedRate.begin()) return false; + + return true; } //============================================================================== -TSoundOutputDevice::TSoundOutputDevice() : m_imp(new TSoundOutputDeviceImp()) -{ -} +TSoundOutputDevice::TSoundOutputDevice() : m_imp(new TSoundOutputDeviceImp()) {} //------------------------------------------------------------------------------ -TSoundOutputDevice::~TSoundOutputDevice() -{ - close(); - WaitForSingleObject(m_imp->m_closeDevice, INFINITE); - CloseHandle(m_imp->m_closeDevice); +TSoundOutputDevice::~TSoundOutputDevice() { + close(); + WaitForSingleObject(m_imp->m_closeDevice, INFINITE); + CloseHandle(m_imp->m_closeDevice); } //------------------------------------------------------------------------------ -namespace -{ -DWORD WINAPI MyWaveOutCallbackThread(LPVOID lpParameter) -{ - TSoundOutputDeviceImp *devImp = (TSoundOutputDeviceImp *)lpParameter; - if (!devImp) - return 0; - - MSG msg; - BOOL bRet; - while (bRet = GetMessage(&msg, NULL, 0, 0)) { - if (bRet == -1) { - // si e' verificato un errore - break; - } - - switch (msg.message) { - case MM_WOM_DONE: { - WAVEHDR *pWaveHdr = ((WAVEHDR *)msg.lParam); - { - TThread::MutexLocker sl(&devImp->m_mutex); - if (devImp->m_looped) { - devImp->doPlay(pWaveHdr, devImp->m_currentFormat); - continue; - } - } - - WAVEHDR *whdr = 0; - if (devImp->m_whdrQueue->popFront(pWaveHdr->dwUser)) { - whdr = devImp->m_whdrQueue->get(); - if (whdr) - devImp->doPlay(whdr, devImp->m_currentFormat); - - WaitForSingleObject(devImp->m_closeDevice, INFINITE); - CloseHandle(devImp->m_closeDevice); - - MMRESULT ret = waveOutUnprepareHeader( - devImp->m_wout, pWaveHdr, sizeof(WAVEHDR)); - if (ret == MMSYSERR_NOERROR) { - delete pWaveHdr->lpData; - delete pWaveHdr; - } - } - - if (!whdr && devImp->m_whdrQueue->size() == 0) { - std::set::iterator it = devImp->m_listeners.begin(); - for (; it != devImp->m_listeners.end(); ++it) { +namespace { +DWORD WINAPI MyWaveOutCallbackThread(LPVOID lpParameter) { + TSoundOutputDeviceImp *devImp = (TSoundOutputDeviceImp *)lpParameter; + if (!devImp) return 0; + + MSG msg; + BOOL bRet; + while (bRet = GetMessage(&msg, NULL, 0, 0)) { + if (bRet == -1) { + // si e' verificato un errore + break; + } + + switch (msg.message) { + case MM_WOM_DONE: { + WAVEHDR *pWaveHdr = ((WAVEHDR *)msg.lParam); + { + TThread::MutexLocker sl(&devImp->m_mutex); + if (devImp->m_looped) { + devImp->doPlay(pWaveHdr, devImp->m_currentFormat); + continue; + } + } + + WAVEHDR *whdr = 0; + if (devImp->m_whdrQueue->popFront(pWaveHdr->dwUser)) { + whdr = devImp->m_whdrQueue->get(); + if (whdr) devImp->doPlay(whdr, devImp->m_currentFormat); + + WaitForSingleObject(devImp->m_closeDevice, INFINITE); + CloseHandle(devImp->m_closeDevice); + + MMRESULT ret = + waveOutUnprepareHeader(devImp->m_wout, pWaveHdr, sizeof(WAVEHDR)); + if (ret == MMSYSERR_NOERROR) { + delete pWaveHdr->lpData; + delete pWaveHdr; + } + } + + if (!whdr && devImp->m_whdrQueue->size() == 0) { + std::set::iterator it = + devImp->m_listeners.begin(); + for (; it != devImp->m_listeners.end(); ++it) { #ifndef TNZCORE_LIGHT - EndPlayMsg *event = new EndPlayMsg(*it); - event->send(); + EndPlayMsg *event = new EndPlayMsg(*it); + event->send(); #else - assert(false); + assert(false); #endif - } - devImp->doCloseDevice(); - } + } + devImp->doCloseDevice(); + } - continue; - } + continue; + } - case MM_WOM_CLOSE: - break; + case MM_WOM_CLOSE: + break; - default: - continue; - } - } + default: + continue; + } + } - SetEvent(devImp->m_closeDevice); - return 0; + SetEvent(devImp->m_closeDevice); + return 0; } -void getAmplitude(int &litude, const TSoundTrackP st, TINT32 sample) -{ - TSoundTrackP snd = st; - amplitude = 0; - int k = 0; - for (k = 0; k < snd->getChannelCount(); ++k) - amplitude += (int)snd->getPressure(sample, k); - amplitude /= k; +void getAmplitude(int &litude, const TSoundTrackP st, TINT32 sample) { + TSoundTrackP snd = st; + amplitude = 0; + int k = 0; + for (k = 0; k < snd->getChannelCount(); ++k) + amplitude += (int)snd->getPressure(sample, k); + amplitude /= k; } } //------------------------------------------------------------------------------ -bool TSoundOutputDevice::installed() -{ - int ndev = waveOutGetNumDevs(); - if (ndev <= 0) - return false; - return true; +bool TSoundOutputDevice::installed() { + int ndev = waveOutGetNumDevs(); + if (ndev <= 0) return false; + return true; } //------------------------------------------------------------------------------ -bool TSoundOutputDevice::open(const TSoundTrackP &st) -{ - return m_imp->doOpenDevice(st->getFormat()); +bool TSoundOutputDevice::open(const TSoundTrackP &st) { + return m_imp->doOpenDevice(st->getFormat()); } //------------------------------------------------------------------------------ -void TSoundOutputDevice::attach(TSoundOutputDeviceListener *listener) -{ - m_imp->m_listeners.insert(listener); +void TSoundOutputDevice::attach(TSoundOutputDeviceListener *listener) { + m_imp->m_listeners.insert(listener); } //------------------------------------------------------------------------------ -void TSoundOutputDevice::detach(TSoundOutputDeviceListener *listener) -{ - m_imp->m_listeners.erase(listener); +void TSoundOutputDevice::detach(TSoundOutputDeviceListener *listener) { + m_imp->m_listeners.erase(listener); } //------------------------------------------------------------------------------ -void TSoundOutputDevice::play( - const TSoundTrackP &st, TINT32 s0, TINT32 s1, bool loop, bool scrubbing) -{ - assert((scrubbing && !loop) || !scrubbing); - if (!st->getSampleCount()) - return; - TSoundTrackFormat format; - TSoundTrackP subTrack; - - { - TThread::MutexLocker sl(&m_imp->m_mutex); - if (m_imp->m_looped) - throw TSoundDeviceException( - TSoundDeviceException::Busy, - "Unable to queue another playback when the sound player is looping"); - - format = st->getFormat(); - try { - TSoundTrackFormat fmt = getPreferredFormat(format); - if (fmt != format) { - throw TSoundDeviceException( - TSoundDeviceException::UnsupportedFormat, - "Unsupported Format"); - } - } catch (TSoundDeviceException &e) { - throw TSoundDeviceException( - TSoundDeviceException::UnsupportedFormat, - e.getMessage()); - } - - assert(s1 >= s0); - subTrack = st->extract(s0, s1); - m_imp->m_looped = loop; - m_imp->m_scrubbing = scrubbing; - } - - if (!m_imp->m_wout) - m_imp->doOpenDevice(format); - - m_imp->m_whdrQueue->put(subTrack); +void TSoundOutputDevice::play(const TSoundTrackP &st, TINT32 s0, TINT32 s1, + bool loop, bool scrubbing) { + assert((scrubbing && !loop) || !scrubbing); + if (!st->getSampleCount()) return; + TSoundTrackFormat format; + TSoundTrackP subTrack; + + { + TThread::MutexLocker sl(&m_imp->m_mutex); + if (m_imp->m_looped) + throw TSoundDeviceException( + TSoundDeviceException::Busy, + "Unable to queue another playback when the sound player is looping"); + + format = st->getFormat(); + try { + TSoundTrackFormat fmt = getPreferredFormat(format); + if (fmt != format) { + throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat, + "Unsupported Format"); + } + } catch (TSoundDeviceException &e) { + throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat, + e.getMessage()); + } + + assert(s1 >= s0); + subTrack = st->extract(s0, s1); + m_imp->m_looped = loop; + m_imp->m_scrubbing = scrubbing; + } + + if (!m_imp->m_wout) m_imp->doOpenDevice(format); + + m_imp->m_whdrQueue->put(subTrack); } //------------------------------------------------------------------------------ -void TSoundOutputDevice::stop() -{ - if ((m_imp->m_wout) && m_imp->m_isPlaying) { - MMRESULT ret = waveOutReset(m_imp->m_wout); - if (ret != MMSYSERR_NOERROR) - return; +void TSoundOutputDevice::stop() { + if ((m_imp->m_wout) && m_imp->m_isPlaying) { + MMRESULT ret = waveOutReset(m_imp->m_wout); + if (ret != MMSYSERR_NOERROR) return; - TThread::MutexLocker sl(&m_imp->m_mutex); - m_imp->m_looped = false; - m_imp->m_stopped = true; - m_imp->m_isPlaying = false; - m_imp->m_whdrQueue->clear(); - } + TThread::MutexLocker sl(&m_imp->m_mutex); + m_imp->m_looped = false; + m_imp->m_stopped = true; + m_imp->m_isPlaying = false; + m_imp->m_whdrQueue->clear(); + } } //------------------------------------------------------------------------------ -bool TSoundOutputDevice::close() -{ - return m_imp->doCloseDevice(); -} +bool TSoundOutputDevice::close() { return m_imp->doCloseDevice(); } //------------------------------------------------------------------------------ -bool TSoundOutputDevice::isPlaying() const -{ - return m_imp->m_isPlaying; -} +bool TSoundOutputDevice::isPlaying() const { return m_imp->m_isPlaying; } //------------------------------------------------------------------------------ -bool TSoundOutputDevice::isAllQueuedItemsPlayed() -{ - return m_imp->m_whdrQueue->isAllQueuedItemsPlayed(); +bool TSoundOutputDevice::isAllQueuedItemsPlayed() { + return m_imp->m_whdrQueue->isAllQueuedItemsPlayed(); } //------------------------------------------------------------------------------ -bool TSoundOutputDevice::isLooping() -{ - TThread::MutexLocker sl(&m_imp->m_mutex); - return m_imp->m_looped; +bool TSoundOutputDevice::isLooping() { + TThread::MutexLocker sl(&m_imp->m_mutex); + return m_imp->m_looped; } //------------------------------------------------------------------------------ -void TSoundOutputDevice::setLooping(bool loop) -{ - TThread::MutexLocker sl(&m_imp->m_mutex); - m_imp->m_looped = loop; +void TSoundOutputDevice::setLooping(bool loop) { + TThread::MutexLocker sl(&m_imp->m_mutex); + m_imp->m_looped = loop; } //------------------------------------------------------------------------------ -TSoundTrackFormat TSoundOutputDevice::getPreferredFormat( - TUINT32 sampleRate, int channelCount, int bitPerSample) -{ - TSoundTrackFormat fmt; - - //avvvicinarsi al sample rate => dovrebbe esser OK avendo selezionato i piu' vicini - std::set::iterator it = m_imp->m_supportedRate.lower_bound(sampleRate); - if (it == m_imp->m_supportedRate.end()) { - it = std::max_element(m_imp->m_supportedRate.begin(), - m_imp->m_supportedRate.end()); - if (it != m_imp->m_supportedRate.end()) - sampleRate = *(m_imp->m_supportedRate.rbegin()); - else - throw TSoundDeviceException( - TSoundDeviceException::UnsupportedFormat, - "There isn't a supported format"); - } else - sampleRate = *it; - - if (bitPerSample <= 8) - bitPerSample = 8; - else if ((bitPerSample > 8 && bitPerSample < 16) || bitPerSample >= 16) - bitPerSample = 16; - - if (bitPerSample >= 16) - fmt.m_signedSample = true; - else - fmt.m_signedSample = false; - - //switch mono/stereo - if (channelCount <= 1) - channelCount = 1; - else - channelCount = 2; - - fmt.m_bitPerSample = bitPerSample; - fmt.m_channelCount = channelCount; - fmt.m_sampleRate = sampleRate; - - return fmt; +TSoundTrackFormat TSoundOutputDevice::getPreferredFormat(TUINT32 sampleRate, + int channelCount, + int bitPerSample) { + TSoundTrackFormat fmt; + + // avvvicinarsi al sample rate => dovrebbe esser OK avendo selezionato i piu' + // vicini + std::set::iterator it = m_imp->m_supportedRate.lower_bound(sampleRate); + if (it == m_imp->m_supportedRate.end()) { + it = std::max_element(m_imp->m_supportedRate.begin(), + m_imp->m_supportedRate.end()); + if (it != m_imp->m_supportedRate.end()) + sampleRate = *(m_imp->m_supportedRate.rbegin()); + else + throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat, + "There isn't a supported format"); + } else + sampleRate = *it; + + if (bitPerSample <= 8) + bitPerSample = 8; + else if ((bitPerSample > 8 && bitPerSample < 16) || bitPerSample >= 16) + bitPerSample = 16; + + if (bitPerSample >= 16) + fmt.m_signedSample = true; + else + fmt.m_signedSample = false; + + // switch mono/stereo + if (channelCount <= 1) + channelCount = 1; + else + channelCount = 2; + + fmt.m_bitPerSample = bitPerSample; + fmt.m_channelCount = channelCount; + fmt.m_sampleRate = sampleRate; + + return fmt; } //------------------------------------------------------------------------------ -TSoundTrackFormat TSoundOutputDevice::getPreferredFormat(const TSoundTrackFormat &format) -{ - try { - return getPreferredFormat( - format.m_sampleRate, format.m_channelCount, format.m_bitPerSample); - } catch (TSoundDeviceException &e) { - throw TSoundDeviceException( - TSoundDeviceException::UnsupportedFormat, - e.getMessage()); - } +TSoundTrackFormat TSoundOutputDevice::getPreferredFormat( + const TSoundTrackFormat &format) { + try { + return getPreferredFormat(format.m_sampleRate, format.m_channelCount, + format.m_bitPerSample); + } catch (TSoundDeviceException &e) { + throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat, + e.getMessage()); + } } //============================================================================== @@ -931,795 +859,729 @@ TSoundTrackFormat TSoundOutputDevice::getPreferredFormat(const TSoundTrackFormat //============================================================================== -class WaveFormat : public WAVEFORMATEX -{ +class WaveFormat : public WAVEFORMATEX { public: - WaveFormat(){}; - WaveFormat(unsigned char channelCount, - unsigned TINT32 sampleRate, - unsigned char bitPerSample); + WaveFormat(){}; + WaveFormat(unsigned char channelCount, unsigned TINT32 sampleRate, + unsigned char bitPerSample); - ~WaveFormat(){}; + ~WaveFormat(){}; }; -WaveFormat::WaveFormat(unsigned char channelCount, - unsigned TINT32 sampleRate, - unsigned char bitPerSample) -{ - wFormatTag = WAVE_FORMAT_PCM; - nChannels = channelCount; - nSamplesPerSec = sampleRate; - wBitsPerSample = bitPerSample; - nBlockAlign = (channelCount * bitPerSample) >> 3; - nAvgBytesPerSec = nBlockAlign * sampleRate; - cbSize = 0; +WaveFormat::WaveFormat(unsigned char channelCount, unsigned TINT32 sampleRate, + unsigned char bitPerSample) { + wFormatTag = WAVE_FORMAT_PCM; + nChannels = channelCount; + nSamplesPerSec = sampleRate; + wBitsPerSample = bitPerSample; + nBlockAlign = (channelCount * bitPerSample) >> 3; + nAvgBytesPerSec = nBlockAlign * sampleRate; + cbSize = 0; } //============================================================================== -class WinSoundInputDevice -{ +class WinSoundInputDevice { public: - WinSoundInputDevice(); - ~WinSoundInputDevice(); + WinSoundInputDevice(); + ~WinSoundInputDevice(); - void open(const WaveFormat &wf); - void close(); + void open(const WaveFormat &wf); + void close(); - void prepareHeader(char *sampleBuffer, - unsigned TINT32 sampleBufferSize, - WAVEHDR &whdr); + void prepareHeader(char *sampleBuffer, unsigned TINT32 sampleBufferSize, + WAVEHDR &whdr); - void unprepareHeader(WAVEHDR &whdr); + void unprepareHeader(WAVEHDR &whdr); - void addBlock(WAVEHDR &whdr); + void addBlock(WAVEHDR &whdr); - void start(); + void start(); - void reset(); - void stop(); + void reset(); + void stop(); - HANDLE m_hBlockDone; + HANDLE m_hBlockDone; private: - HWAVEIN m_hWaveIn; + HWAVEIN m_hWaveIn; }; //-------------------------------------------------------------------- -WinSoundInputDevice::WinSoundInputDevice() - : m_hWaveIn(0) -{ - m_hBlockDone = CreateEvent( - NULL, // no security attributes - FALSE, // auto-reset event - FALSE, // initial state is not signaled - NULL); // object not named +WinSoundInputDevice::WinSoundInputDevice() : m_hWaveIn(0) { + m_hBlockDone = CreateEvent(NULL, // no security attributes + FALSE, // auto-reset event + FALSE, // initial state is not signaled + NULL); // object not named } //-------------------------------------------------------------------- -WinSoundInputDevice::~WinSoundInputDevice() -{ - CloseHandle(m_hBlockDone); -} +WinSoundInputDevice::~WinSoundInputDevice() { CloseHandle(m_hBlockDone); } //-------------------------------------------------------------------- -void WinSoundInputDevice::open(const WaveFormat &wf) -{ - if (m_hWaveIn) - close(); +void WinSoundInputDevice::open(const WaveFormat &wf) { + if (m_hWaveIn) close(); - MMRESULT ret = waveInOpen( - &m_hWaveIn, WAVE_MAPPER, - &wf, (DWORD)recordCB, - (DWORD)m_hBlockDone, CALLBACK_FUNCTION); + MMRESULT ret = waveInOpen(&m_hWaveIn, WAVE_MAPPER, &wf, (DWORD)recordCB, + (DWORD)m_hBlockDone, CALLBACK_FUNCTION); - if (ret != MMSYSERR_NOERROR) { - throw TException("Error to open the input device"); - } + if (ret != MMSYSERR_NOERROR) { + throw TException("Error to open the input device"); + } } //-------------------------------------------------------------------- -void WinSoundInputDevice::close() -{ - if (!m_hWaveIn) - return; +void WinSoundInputDevice::close() { + if (!m_hWaveIn) return; - MMRESULT ret = waveInClose(m_hWaveIn); + MMRESULT ret = waveInClose(m_hWaveIn); - if (ret != MMSYSERR_NOERROR) { - throw TException("Error to close the input device"); - } - m_hWaveIn = 0; + if (ret != MMSYSERR_NOERROR) { + throw TException("Error to close the input device"); + } + m_hWaveIn = 0; } //-------------------------------------------------------------------- void WinSoundInputDevice::prepareHeader(char *sampleBuffer, - unsigned TINT32 sampleBufferSize, - WAVEHDR &whdr) -{ - whdr.lpData = sampleBuffer; - whdr.dwBufferLength = sampleBufferSize; // numero di byte - whdr.dwFlags = 0; - whdr.dwLoops = 0; - - MMRESULT ret = waveInPrepareHeader(m_hWaveIn, &whdr, sizeof(WAVEHDR)); - if (ret != MMSYSERR_NOERROR) { - throw TException("Unable to prepare a wave header"); - } + unsigned TINT32 sampleBufferSize, + WAVEHDR &whdr) { + whdr.lpData = sampleBuffer; + whdr.dwBufferLength = sampleBufferSize; // numero di byte + whdr.dwFlags = 0; + whdr.dwLoops = 0; + + MMRESULT ret = waveInPrepareHeader(m_hWaveIn, &whdr, sizeof(WAVEHDR)); + if (ret != MMSYSERR_NOERROR) { + throw TException("Unable to prepare a wave header"); + } } //-------------------------------------------------------------------- -void WinSoundInputDevice::unprepareHeader(WAVEHDR &whdr) -{ - MMRESULT ret = waveInUnprepareHeader(m_hWaveIn, &whdr, sizeof(WAVEHDR)); - if (ret != MMSYSERR_NOERROR) { - throw TException("Unable to unprepare a wave header"); - } +void WinSoundInputDevice::unprepareHeader(WAVEHDR &whdr) { + MMRESULT ret = waveInUnprepareHeader(m_hWaveIn, &whdr, sizeof(WAVEHDR)); + if (ret != MMSYSERR_NOERROR) { + throw TException("Unable to unprepare a wave header"); + } } //-------------------------------------------------------------------- -void WinSoundInputDevice::addBlock(WAVEHDR &whdr) -{ - MMRESULT ret = waveInAddBuffer(m_hWaveIn, &whdr, sizeof(WAVEHDR)); - if (ret != MMSYSERR_NOERROR) { - throw TException("Unable to add a waveheader"); - } +void WinSoundInputDevice::addBlock(WAVEHDR &whdr) { + MMRESULT ret = waveInAddBuffer(m_hWaveIn, &whdr, sizeof(WAVEHDR)); + if (ret != MMSYSERR_NOERROR) { + throw TException("Unable to add a waveheader"); + } } //-------------------------------------------------------------------- -void WinSoundInputDevice::start() -{ - int ret = waveInStart(m_hWaveIn); - if (ret != MMSYSERR_NOERROR) { - throw TException("Unable to add a waveheader"); - } +void WinSoundInputDevice::start() { + int ret = waveInStart(m_hWaveIn); + if (ret != MMSYSERR_NOERROR) { + throw TException("Unable to add a waveheader"); + } } //-------------------------------------------------------------------- -void WinSoundInputDevice::reset() -{ - if (!m_hWaveIn) - return; +void WinSoundInputDevice::reset() { + if (!m_hWaveIn) return; - MMRESULT ret = waveInReset(m_hWaveIn); - if (ret != MMSYSERR_NOERROR) { - throw TException("Unable to add a waveheader"); - } + MMRESULT ret = waveInReset(m_hWaveIn); + if (ret != MMSYSERR_NOERROR) { + throw TException("Unable to add a waveheader"); + } } //-------------------------------------------------------------------- -void WinSoundInputDevice::stop() -{ - MMRESULT ret = waveInStop(m_hWaveIn); - if (ret != MMSYSERR_NOERROR) { - throw TException("Unable to add a waveheader"); - } +void WinSoundInputDevice::stop() { + MMRESULT ret = waveInStop(m_hWaveIn); + if (ret != MMSYSERR_NOERROR) { + throw TException("Unable to add a waveheader"); + } } //==================================================================== #ifndef TNZCORE_LIGHT -class RecordTask : public TThread::Runnable -{ +class RecordTask : public TThread::Runnable { public: - RecordTask(std::shared_ptr dev) - : Runnable(), m_dev(std::move(dev)) {} + RecordTask(std::shared_ptr dev) + : Runnable(), m_dev(std::move(dev)) {} - ~RecordTask() {} + ~RecordTask() {} - void run(); + void run(); - std::shared_ptr m_dev; + std::shared_ptr m_dev; }; #endif //==================================================================== -class TSoundInputDeviceImp : public WinSoundInputDevice -{ +class TSoundInputDeviceImp : public WinSoundInputDevice { public: - bool m_allocateBuff; - bool m_isRecording; - bool m_supportVolume; - int m_index; - TINT32 m_byteRecorded; + bool m_allocateBuff; + bool m_isRecording; + bool m_supportVolume; + int m_index; + TINT32 m_byteRecorded; - TSoundTrackP m_st; - TSoundTrackFormat m_format; + TSoundTrackP m_st; + TSoundTrackFormat m_format; #ifndef TNZCORE_LIGHT - TThread::Executor m_executor; + TThread::Executor m_executor; #endif - std::vector m_whdr; - std::vector m_recordedBlocks; - std::set m_supportedRate; + std::vector m_whdr; + std::vector m_recordedBlocks; + std::set m_supportedRate; - HANDLE m_hLastBlockDone; + HANDLE m_hLastBlockDone; - TSoundInputDeviceImp(); - ~TSoundInputDeviceImp(); + TSoundInputDeviceImp(); + ~TSoundInputDeviceImp(); - void insertAllRate(); - bool verifyRate(); + void insertAllRate(); + bool verifyRate(); }; //------------------------------------------------------------------------------ TSoundInputDeviceImp::TSoundInputDeviceImp() - : m_allocateBuff(false), m_isRecording(false), m_supportVolume(false), m_index(0), m_byteRecorded(0), m_format(), m_whdr(3), m_recordedBlocks(), m_supportedRate() -{ - m_hLastBlockDone = CreateEvent( - NULL, // no security attributes - FALSE, // is manual-reset event? - FALSE, // is signaled? - NULL); // object not named + : m_allocateBuff(false) + , m_isRecording(false) + , m_supportVolume(false) + , m_index(0) + , m_byteRecorded(0) + , m_format() + , m_whdr(3) + , m_recordedBlocks() + , m_supportedRate() { + m_hLastBlockDone = CreateEvent(NULL, // no security attributes + FALSE, // is manual-reset event? + FALSE, // is signaled? + NULL); // object not named } //------------------------------------------------------------------------------ -TSoundInputDeviceImp::~TSoundInputDeviceImp() -{ - if (m_isRecording) { - try { - reset(); - WaitForSingleObject(m_hLastBlockDone, INFINITE); - int i; - for (i = 0; i < (int)m_recordedBlocks.size(); ++i) - delete[] m_recordedBlocks[i]; - close(); - } catch (TException &) { - } - } - CloseHandle(m_hLastBlockDone); +TSoundInputDeviceImp::~TSoundInputDeviceImp() { + if (m_isRecording) { + try { + reset(); + WaitForSingleObject(m_hLastBlockDone, INFINITE); + int i; + for (i = 0; i < (int)m_recordedBlocks.size(); ++i) + delete[] m_recordedBlocks[i]; + close(); + } catch (TException &) { + } + } + CloseHandle(m_hLastBlockDone); } //---------------------------------------------------------------------------- -void TSoundInputDeviceImp::insertAllRate() -{ - m_supportedRate.insert(8000); - m_supportedRate.insert(11025); - m_supportedRate.insert(16000); - m_supportedRate.insert(22050); - m_supportedRate.insert(32000); - m_supportedRate.insert(44100); - m_supportedRate.insert(48000); +void TSoundInputDeviceImp::insertAllRate() { + m_supportedRate.insert(8000); + m_supportedRate.insert(11025); + m_supportedRate.insert(16000); + m_supportedRate.insert(22050); + m_supportedRate.insert(32000); + m_supportedRate.insert(44100); + m_supportedRate.insert(48000); } //---------------------------------------------------------------------------- -bool TSoundInputDeviceImp::verifyRate() -{ - std::set::iterator it; - - for (it = m_supportedRate.begin(); - it != m_supportedRate.end();) { - MMRESULT ret; - WAVEFORMATEX wf; - - wf.wFormatTag = WAVE_FORMAT_PCM; - wf.nChannels = 1; - wf.nSamplesPerSec = *it; - wf.wBitsPerSample = 8; - wf.nBlockAlign = (wf.nChannels * wf.wBitsPerSample) >> 3; - wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign; - wf.cbSize = 0; - - ret = waveInOpen(NULL, WAVE_MAPPER, &wf, NULL, NULL, WAVE_FORMAT_QUERY); - - if (ret == MMSYSERR_NOERROR) { - ++it; - continue; - } - if (ret == WAVERR_BADFORMAT) - it = m_supportedRate.erase(it); - else - return false; - } - if (m_supportedRate.end() == m_supportedRate.begin()) - return false; - - return true; +bool TSoundInputDeviceImp::verifyRate() { + std::set::iterator it; + + for (it = m_supportedRate.begin(); it != m_supportedRate.end();) { + MMRESULT ret; + WAVEFORMATEX wf; + + wf.wFormatTag = WAVE_FORMAT_PCM; + wf.nChannels = 1; + wf.nSamplesPerSec = *it; + wf.wBitsPerSample = 8; + wf.nBlockAlign = (wf.nChannels * wf.wBitsPerSample) >> 3; + wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign; + wf.cbSize = 0; + + ret = waveInOpen(NULL, WAVE_MAPPER, &wf, NULL, NULL, WAVE_FORMAT_QUERY); + + if (ret == MMSYSERR_NOERROR) { + ++it; + continue; + } + if (ret == WAVERR_BADFORMAT) + it = m_supportedRate.erase(it); + else + return false; + } + if (m_supportedRate.end() == m_supportedRate.begin()) return false; + + return true; } //==================================================================== -namespace -{ -void CALLBACK recordCB( - HWAVEIN hwi, - UINT uMsg, - DWORD dwInstance, - DWORD dwParam1, - DWORD dwParam2) -{ - WAVEHDR *whdr = (WAVEHDR *)dwParam1; - HANDLE *blockDone = (HANDLE *)dwInstance; +namespace { +void CALLBACK recordCB(HWAVEIN hwi, UINT uMsg, DWORD dwInstance, DWORD dwParam1, + DWORD dwParam2) { + WAVEHDR *whdr = (WAVEHDR *)dwParam1; + HANDLE *blockDone = (HANDLE *)dwInstance; - if (uMsg != MM_WIM_DATA) - return; - SetEvent(blockDone); + if (uMsg != MM_WIM_DATA) return; + SetEvent(blockDone); } } //============================================================================== -TSoundInputDevice::TSoundInputDevice() : m_imp(new TSoundInputDeviceImp()) -{ - m_imp->insertAllRate(); - if (!m_imp->verifyRate()) - throw TSoundDeviceException( - TSoundDeviceException::FailedInit, - "Unable to verify supported rates"); - if (supportsVolume()) - m_imp->m_supportVolume = true; +TSoundInputDevice::TSoundInputDevice() : m_imp(new TSoundInputDeviceImp()) { + m_imp->insertAllRate(); + if (!m_imp->verifyRate()) + throw TSoundDeviceException(TSoundDeviceException::FailedInit, + "Unable to verify supported rates"); + if (supportsVolume()) m_imp->m_supportVolume = true; } //------------------------------------------------------------------------------ -TSoundInputDevice::~TSoundInputDevice() -{ -} +TSoundInputDevice::~TSoundInputDevice() {} //------------------------------------------------------------------------------ -bool TSoundInputDevice::installed() -{ - int ndev = waveInGetNumDevs(); - if (ndev <= 0) - return false; - return true; +bool TSoundInputDevice::installed() { + int ndev = waveInGetNumDevs(); + if (ndev <= 0) return false; + return true; } //------------------------------------------------------------------------------ #ifndef TNZCORE_LIGHT -void TSoundInputDevice::record(const TSoundTrackFormat &format, Source devtype) -{ - if (m_imp->m_isRecording) - throw TSoundDeviceException( - TSoundDeviceException::Busy, - "Just another recoding is in progress"); - - /*if ((format.m_bitPerSample == 8 && format.m_signedSample) || - (format.m_bitPerSample == 24)) - throw TException("This format is not supported for recording");*/ - try { - TSoundTrackFormat fmt = getPreferredFormat(format); - if (fmt != format) { - throw TSoundDeviceException( - TSoundDeviceException::UnsupportedFormat, - "Unsupported Format"); - } - } catch (TSoundDeviceException &e) { - throw TSoundDeviceException( - TSoundDeviceException::UnsupportedFormat, - e.getMessage()); - } - - if (!setRecordLine(devtype)) - throw TSoundDeviceException( - TSoundDeviceException::UnableSetDevice, - "Problems to set input source line to record"); - - m_imp->m_format = format; - m_imp->m_st = 0; - ResetEvent(m_imp->m_hLastBlockDone); - ResetEvent(m_imp->m_hBlockDone); - m_imp->m_allocateBuff = true; - m_imp->m_isRecording = true; - m_imp->m_index = 0; - m_imp->m_recordedBlocks.clear(); - m_imp->m_byteRecorded = 0; - TINT32 bytePerSec = format.m_sampleRate * ((format.m_bitPerSample * format.m_channelCount) >> 3); - - try { - WaveFormat wf(m_imp->m_format.m_channelCount, - m_imp->m_format.m_sampleRate, - m_imp->m_format.m_bitPerSample); - - m_imp->open(wf); - } catch (TException &e) { - m_imp->m_isRecording = false; - throw TSoundDeviceException( - TSoundDeviceException::UnableOpenDevice, e.getMessage()); - } - for (; m_imp->m_index < (int)(m_imp->m_whdr.size() - 1); ++m_imp->m_index) { - try { - m_imp->prepareHeader(new char[bytePerSec], - bytePerSec, - m_imp->m_whdr[m_imp->m_index]); - m_imp->addBlock(m_imp->m_whdr[m_imp->m_index]); - } catch (TException &e) { - m_imp->m_isRecording = false; - for (int j = 0; j < (int)(m_imp->m_whdr.size() - 1); ++j) { - if (m_imp->m_whdr[j].dwFlags & WHDR_PREPARED) { - try { - m_imp->unprepareHeader(m_imp->m_whdr[j]); - } catch (TException &e) { - throw TSoundDeviceException( - TSoundDeviceException::UnableCloseDevice, e.getMessage()); - } - delete[] m_imp->m_whdr[j].lpData; - } else if (j == m_imp->m_index) - delete[] m_imp->m_whdr[j].lpData; - } - throw TSoundDeviceException( - TSoundDeviceException::UnablePrepare, e.getMessage()); - } - } - - m_imp->m_executor.addTask(new RecordTask(m_imp)); +void TSoundInputDevice::record(const TSoundTrackFormat &format, + Source devtype) { + if (m_imp->m_isRecording) + throw TSoundDeviceException(TSoundDeviceException::Busy, + "Just another recoding is in progress"); + + /*if ((format.m_bitPerSample == 8 && format.m_signedSample) || +(format.m_bitPerSample == 24)) +throw TException("This format is not supported for recording");*/ + try { + TSoundTrackFormat fmt = getPreferredFormat(format); + if (fmt != format) { + throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat, + "Unsupported Format"); + } + } catch (TSoundDeviceException &e) { + throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat, + e.getMessage()); + } + + if (!setRecordLine(devtype)) + throw TSoundDeviceException(TSoundDeviceException::UnableSetDevice, + "Problems to set input source line to record"); + + m_imp->m_format = format; + m_imp->m_st = 0; + ResetEvent(m_imp->m_hLastBlockDone); + ResetEvent(m_imp->m_hBlockDone); + m_imp->m_allocateBuff = true; + m_imp->m_isRecording = true; + m_imp->m_index = 0; + m_imp->m_recordedBlocks.clear(); + m_imp->m_byteRecorded = 0; + TINT32 bytePerSec = format.m_sampleRate * + ((format.m_bitPerSample * format.m_channelCount) >> 3); + + try { + WaveFormat wf(m_imp->m_format.m_channelCount, m_imp->m_format.m_sampleRate, + m_imp->m_format.m_bitPerSample); + + m_imp->open(wf); + } catch (TException &e) { + m_imp->m_isRecording = false; + throw TSoundDeviceException(TSoundDeviceException::UnableOpenDevice, + e.getMessage()); + } + for (; m_imp->m_index < (int)(m_imp->m_whdr.size() - 1); ++m_imp->m_index) { + try { + m_imp->prepareHeader(new char[bytePerSec], bytePerSec, + m_imp->m_whdr[m_imp->m_index]); + m_imp->addBlock(m_imp->m_whdr[m_imp->m_index]); + } catch (TException &e) { + m_imp->m_isRecording = false; + for (int j = 0; j < (int)(m_imp->m_whdr.size() - 1); ++j) { + if (m_imp->m_whdr[j].dwFlags & WHDR_PREPARED) { + try { + m_imp->unprepareHeader(m_imp->m_whdr[j]); + } catch (TException &e) { + throw TSoundDeviceException( + TSoundDeviceException::UnableCloseDevice, e.getMessage()); + } + delete[] m_imp->m_whdr[j].lpData; + } else if (j == m_imp->m_index) + delete[] m_imp->m_whdr[j].lpData; + } + throw TSoundDeviceException(TSoundDeviceException::UnablePrepare, + e.getMessage()); + } + } + + m_imp->m_executor.addTask(new RecordTask(m_imp)); } //------------------------------------------------------------------------------ -void TSoundInputDevice::record(const TSoundTrackP &st, Source devtype) -{ - if (m_imp->m_isRecording) - throw TSoundDeviceException( - TSoundDeviceException::Busy, - "Just another recoding is in progress"); - - m_imp->m_format = st->getFormat(); - /*if ((m_imp->m_format.m_bitPerSample == 8 && m_imp->m_format.m_signedSample) || - (m_imp->m_format.m_bitPerSample == 24)) - throw TException("This format is not supported for recording");*/ - try { - TSoundTrackFormat fmt = getPreferredFormat(st->getFormat()); - if (fmt != st->getFormat()) { - throw TSoundDeviceException( - TSoundDeviceException::UnsupportedFormat, - "Unsupported Format"); - } - } catch (TSoundDeviceException &e) { - throw TSoundDeviceException( - TSoundDeviceException::UnsupportedFormat, - e.getMessage()); - } - - if (!setRecordLine(devtype)) - throw TSoundDeviceException( - TSoundDeviceException::UnableSetDevice, - "Problems to set input source line to record"); - - m_imp->m_st = st; - m_imp->m_allocateBuff = false; - m_imp->m_isRecording = true; - ResetEvent(m_imp->m_hLastBlockDone); - ResetEvent(m_imp->m_hBlockDone); - m_imp->m_index = 0; - m_imp->m_recordedBlocks.clear(); - m_imp->m_byteRecorded = 0; - try { - WaveFormat wf(m_imp->m_format.m_channelCount, - m_imp->m_format.m_sampleRate, - m_imp->m_format.m_bitPerSample); - - m_imp->open(wf); - m_imp->prepareHeader((char *)st->getRawData(), - st->getSampleCount() * ((st->getBitPerSample() * st->getChannelCount()) >> 3), - m_imp->m_whdr[m_imp->m_index]); - m_imp->addBlock(m_imp->m_whdr[m_imp->m_index]); - } catch (TException &e) { - m_imp->m_isRecording = false; - if (m_imp->m_whdr[m_imp->m_index].dwFlags & WHDR_PREPARED) - m_imp->unprepareHeader(m_imp->m_whdr[m_imp->m_index]); - - throw TSoundDeviceException( - TSoundDeviceException::UnablePrepare, e.getMessage()); - } - - m_imp->m_executor.addTask(new RecordTask(m_imp)); +void TSoundInputDevice::record(const TSoundTrackP &st, Source devtype) { + if (m_imp->m_isRecording) + throw TSoundDeviceException(TSoundDeviceException::Busy, + "Just another recoding is in progress"); + + m_imp->m_format = st->getFormat(); + /*if ((m_imp->m_format.m_bitPerSample == 8 && m_imp->m_format.m_signedSample) +|| +(m_imp->m_format.m_bitPerSample == 24)) +throw TException("This format is not supported for recording");*/ + try { + TSoundTrackFormat fmt = getPreferredFormat(st->getFormat()); + if (fmt != st->getFormat()) { + throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat, + "Unsupported Format"); + } + } catch (TSoundDeviceException &e) { + throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat, + e.getMessage()); + } + + if (!setRecordLine(devtype)) + throw TSoundDeviceException(TSoundDeviceException::UnableSetDevice, + "Problems to set input source line to record"); + + m_imp->m_st = st; + m_imp->m_allocateBuff = false; + m_imp->m_isRecording = true; + ResetEvent(m_imp->m_hLastBlockDone); + ResetEvent(m_imp->m_hBlockDone); + m_imp->m_index = 0; + m_imp->m_recordedBlocks.clear(); + m_imp->m_byteRecorded = 0; + try { + WaveFormat wf(m_imp->m_format.m_channelCount, m_imp->m_format.m_sampleRate, + m_imp->m_format.m_bitPerSample); + + m_imp->open(wf); + m_imp->prepareHeader( + (char *)st->getRawData(), + st->getSampleCount() * + ((st->getBitPerSample() * st->getChannelCount()) >> 3), + m_imp->m_whdr[m_imp->m_index]); + m_imp->addBlock(m_imp->m_whdr[m_imp->m_index]); + } catch (TException &e) { + m_imp->m_isRecording = false; + if (m_imp->m_whdr[m_imp->m_index].dwFlags & WHDR_PREPARED) + m_imp->unprepareHeader(m_imp->m_whdr[m_imp->m_index]); + + throw TSoundDeviceException(TSoundDeviceException::UnablePrepare, + e.getMessage()); + } + + m_imp->m_executor.addTask(new RecordTask(m_imp)); } #endif //------------------------------------------------------------------------------ -TSoundTrackP TSoundInputDevice::stop() -{ - if (!m_imp->m_isRecording) - return 0; - - m_imp->m_isRecording = false; - try { - m_imp->reset(); - } catch (TException &e) { - for (int j = 0; j < (int)m_imp->m_whdr.size(); ++j) { - if (m_imp->m_whdr[j].dwFlags & WHDR_PREPARED) { - try { - m_imp->unprepareHeader(m_imp->m_whdr[j]); - } catch (TException &e) { - throw TSoundDeviceException( - TSoundDeviceException::UnablePrepare, e.getMessage()); - } - delete[] m_imp->m_whdr[j].lpData; - } - } - throw TSoundDeviceException( - TSoundDeviceException::UnableCloseDevice, e.getMessage()); - } - - if (m_imp->m_allocateBuff) { - WaitForSingleObject(m_imp->m_hLastBlockDone, INFINITE); - - TSoundTrackP st = TSoundTrack::create( - m_imp->m_format, - m_imp->m_byteRecorded / ((m_imp->m_format.m_bitPerSample * m_imp->m_format.m_channelCount) >> 3)); - - TINT32 bytePerSec = m_imp->m_format.m_sampleRate * - ((m_imp->m_format.m_bitPerSample * m_imp->m_format.m_channelCount) >> 3); - - int i; - for (i = 0; i < (int)(m_imp->m_recordedBlocks.size() - 1); ++i) { - memcpy( - (void *)(st->getRawData() + bytePerSec * i), - m_imp->m_recordedBlocks[i], - bytePerSec); - delete[] m_imp->m_recordedBlocks[i]; - } - - TINT32 lastBlockSize = m_imp->m_byteRecorded - (bytePerSec * i); - - if (lastBlockSize != 0) { - memcpy((void *)(st->getRawData() + bytePerSec * i), - m_imp->m_recordedBlocks[i], - lastBlockSize); - delete[] m_imp->m_recordedBlocks[i]; - } - - try { - m_imp->close(); - } catch (TException &e) { - throw TSoundDeviceException( - TSoundDeviceException::UnableCloseDevice, e.getMessage()); - } - return st; - } else { - WaitForSingleObject(m_imp->m_hLastBlockDone, INFINITE); - try { - m_imp->close(); - } catch (TException &e) { - throw TSoundDeviceException( - TSoundDeviceException::UnableCloseDevice, e.getMessage()); - } - return m_imp->m_st; - } +TSoundTrackP TSoundInputDevice::stop() { + if (!m_imp->m_isRecording) return 0; + + m_imp->m_isRecording = false; + try { + m_imp->reset(); + } catch (TException &e) { + for (int j = 0; j < (int)m_imp->m_whdr.size(); ++j) { + if (m_imp->m_whdr[j].dwFlags & WHDR_PREPARED) { + try { + m_imp->unprepareHeader(m_imp->m_whdr[j]); + } catch (TException &e) { + throw TSoundDeviceException(TSoundDeviceException::UnablePrepare, + e.getMessage()); + } + delete[] m_imp->m_whdr[j].lpData; + } + } + throw TSoundDeviceException(TSoundDeviceException::UnableCloseDevice, + e.getMessage()); + } + + if (m_imp->m_allocateBuff) { + WaitForSingleObject(m_imp->m_hLastBlockDone, INFINITE); + + TSoundTrackP st = TSoundTrack::create( + m_imp->m_format, + m_imp->m_byteRecorded / ((m_imp->m_format.m_bitPerSample * + m_imp->m_format.m_channelCount) >> + 3)); + + TINT32 bytePerSec = + m_imp->m_format.m_sampleRate * + ((m_imp->m_format.m_bitPerSample * m_imp->m_format.m_channelCount) >> + 3); + + int i; + for (i = 0; i < (int)(m_imp->m_recordedBlocks.size() - 1); ++i) { + memcpy((void *)(st->getRawData() + bytePerSec * i), + m_imp->m_recordedBlocks[i], bytePerSec); + delete[] m_imp->m_recordedBlocks[i]; + } + + TINT32 lastBlockSize = m_imp->m_byteRecorded - (bytePerSec * i); + + if (lastBlockSize != 0) { + memcpy((void *)(st->getRawData() + bytePerSec * i), + m_imp->m_recordedBlocks[i], lastBlockSize); + delete[] m_imp->m_recordedBlocks[i]; + } + + try { + m_imp->close(); + } catch (TException &e) { + throw TSoundDeviceException(TSoundDeviceException::UnableCloseDevice, + e.getMessage()); + } + return st; + } else { + WaitForSingleObject(m_imp->m_hLastBlockDone, INFINITE); + try { + m_imp->close(); + } catch (TException &e) { + throw TSoundDeviceException(TSoundDeviceException::UnableCloseDevice, + e.getMessage()); + } + return m_imp->m_st; + } } //------------------------------------------------------------------------------ #ifndef TNZCORE_LIGHT -void RecordTask::run() -{ - m_dev->start(); - - if (m_dev->m_allocateBuff) { - TINT32 bytePerSec = m_dev->m_format.m_sampleRate * - ((m_dev->m_format.m_bitPerSample * m_dev->m_format.m_channelCount) >> 3); - - while (m_dev->m_whdr[(m_dev->m_index + 1) % m_dev->m_whdr.size()].dwFlags & WHDR_PREPARED) { - if (m_dev->m_isRecording) - WaitForSingleObject(m_dev->m_hBlockDone, INFINITE); - int indexToPrepare = m_dev->m_index; - - // calcolo l'indice successivo per far l'unprepare - m_dev->m_index = (m_dev->m_index + 1) % m_dev->m_whdr.size(); - if (m_dev->m_whdr[m_dev->m_index].dwFlags & WHDR_DONE) { - TINT32 byteRecorded = m_dev->m_whdr[m_dev->m_index].dwBytesRecorded; - if (byteRecorded) { - m_dev->m_recordedBlocks.push_back(m_dev->m_whdr[m_dev->m_index].lpData); - m_dev->m_byteRecorded += byteRecorded; - } - - try { - m_dev->unprepareHeader(m_dev->m_whdr[m_dev->m_index]); - } catch (TException &) { - for (int i = 0; i < (int)m_dev->m_recordedBlocks.size(); ++i) - delete[] m_dev->m_recordedBlocks[i]; - return; - } - - if (byteRecorded == 0) { - delete[] m_dev->m_whdr[m_dev->m_index].lpData; - } - - // con questo controllo si evita che vengano accodati nuovi blocchi - // dopo che e' stata chiamata la waveInReset - if (m_dev->m_isRecording) { - try { - m_dev->prepareHeader(new char[bytePerSec], - bytePerSec, - m_dev->m_whdr[indexToPrepare]); - - m_dev->addBlock(m_dev->m_whdr[indexToPrepare]); - } catch (TException &) { - m_dev->m_isRecording = false; - for (int i = 0; i < (int)m_dev->m_recordedBlocks.size(); ++i) - delete[] m_dev->m_recordedBlocks[i]; - return; - } - } - - } else - m_dev->m_index = indexToPrepare; - } - } else { - if (m_dev->m_isRecording) - WaitForSingleObject(m_dev->m_hBlockDone, INFINITE); - try { - m_dev->unprepareHeader(m_dev->m_whdr[m_dev->m_index]); - m_dev->m_isRecording = false; - } catch (TException &) { - m_dev->m_isRecording = false; - return; - } - } - - SetEvent(m_dev->m_hLastBlockDone); - return; +void RecordTask::run() { + m_dev->start(); + + if (m_dev->m_allocateBuff) { + TINT32 bytePerSec = + m_dev->m_format.m_sampleRate * + ((m_dev->m_format.m_bitPerSample * m_dev->m_format.m_channelCount) >> + 3); + + while (m_dev->m_whdr[(m_dev->m_index + 1) % m_dev->m_whdr.size()].dwFlags & + WHDR_PREPARED) { + if (m_dev->m_isRecording) + WaitForSingleObject(m_dev->m_hBlockDone, INFINITE); + int indexToPrepare = m_dev->m_index; + + // calcolo l'indice successivo per far l'unprepare + m_dev->m_index = (m_dev->m_index + 1) % m_dev->m_whdr.size(); + if (m_dev->m_whdr[m_dev->m_index].dwFlags & WHDR_DONE) { + TINT32 byteRecorded = m_dev->m_whdr[m_dev->m_index].dwBytesRecorded; + if (byteRecorded) { + m_dev->m_recordedBlocks.push_back( + m_dev->m_whdr[m_dev->m_index].lpData); + m_dev->m_byteRecorded += byteRecorded; + } + + try { + m_dev->unprepareHeader(m_dev->m_whdr[m_dev->m_index]); + } catch (TException &) { + for (int i = 0; i < (int)m_dev->m_recordedBlocks.size(); ++i) + delete[] m_dev->m_recordedBlocks[i]; + return; + } + + if (byteRecorded == 0) { + delete[] m_dev->m_whdr[m_dev->m_index].lpData; + } + + // con questo controllo si evita che vengano accodati nuovi blocchi + // dopo che e' stata chiamata la waveInReset + if (m_dev->m_isRecording) { + try { + m_dev->prepareHeader(new char[bytePerSec], bytePerSec, + m_dev->m_whdr[indexToPrepare]); + + m_dev->addBlock(m_dev->m_whdr[indexToPrepare]); + } catch (TException &) { + m_dev->m_isRecording = false; + for (int i = 0; i < (int)m_dev->m_recordedBlocks.size(); ++i) + delete[] m_dev->m_recordedBlocks[i]; + return; + } + } + + } else + m_dev->m_index = indexToPrepare; + } + } else { + if (m_dev->m_isRecording) + WaitForSingleObject(m_dev->m_hBlockDone, INFINITE); + try { + m_dev->unprepareHeader(m_dev->m_whdr[m_dev->m_index]); + m_dev->m_isRecording = false; + } catch (TException &) { + m_dev->m_isRecording = false; + return; + } + } + + SetEvent(m_dev->m_hLastBlockDone); + return; } //------------------------------------------------------------------------------ #endif -double TSoundInputDevice::getVolume() -{ - DWORD dwVolumeControlID; +double TSoundInputDevice::getVolume() { + DWORD dwVolumeControlID; - UINT nNumMixers; - MMRESULT ret; - MIXERLINE mxl; + UINT nNumMixers; + MMRESULT ret; + MIXERLINE mxl; - nNumMixers = mixerGetNumDevs(); + nNumMixers = mixerGetNumDevs(); - if (nNumMixers == 0) - throw TSoundDeviceException( - TSoundDeviceException::NoMixer, - "Doesn't exist a audio mixer device"); + if (nNumMixers == 0) + throw TSoundDeviceException(TSoundDeviceException::NoMixer, + "Doesn't exist a audio mixer device"); - // get dwLineID - ret = getLineInfo((HMIXEROBJ)0, MIXERLINE_COMPONENTTYPE_DST_WAVEIN, mxl); - if (ret != MMSYSERR_NOERROR) - throw TSoundDeviceException( - TSoundDeviceException::UnableVolume, - "Error to obtain info by mixer"); + // get dwLineID + ret = getLineInfo((HMIXEROBJ)0, MIXERLINE_COMPONENTTYPE_DST_WAVEIN, mxl); + if (ret != MMSYSERR_NOERROR) + throw TSoundDeviceException(TSoundDeviceException::UnableVolume, + "Error to obtain info by mixer"); - // get dwControlID - MIXERCONTROL mxc; - ret = getLineControl(mxc, (HMIXEROBJ)0, mxl.dwLineID, MIXERCONTROL_CONTROLTYPE_VOLUME); - if (ret == MIXERR_INVALCONTROL) - throw TSoundDeviceException( - TSoundDeviceException::UnableVolume, - "Is not possible to obtain info of volume by mixer"); + // get dwControlID + MIXERCONTROL mxc; + ret = getLineControl(mxc, (HMIXEROBJ)0, mxl.dwLineID, + MIXERCONTROL_CONTROLTYPE_VOLUME); + if (ret == MIXERR_INVALCONTROL) + throw TSoundDeviceException( + TSoundDeviceException::UnableVolume, + "Is not possible to obtain info of volume by mixer"); - if (ret != MMSYSERR_NOERROR) - throw TSoundDeviceException( - TSoundDeviceException::UnableVolume, - "Error to obtain info by mixer"); + if (ret != MMSYSERR_NOERROR) + throw TSoundDeviceException(TSoundDeviceException::UnableVolume, + "Error to obtain info by mixer"); - dwVolumeControlID = mxc.dwControlID; + dwVolumeControlID = mxc.dwControlID; - MIXERCONTROLDETAILS_UNSIGNED mxcdVolume; + MIXERCONTROLDETAILS_UNSIGNED mxcdVolume; - ret = getControlDetails((HMIXEROBJ)0, - dwVolumeControlID, - mxc.cMultipleItems, - &mxcdVolume); - if (ret != MMSYSERR_NOERROR) - throw TSoundDeviceException( - TSoundDeviceException::UnableVolume, - "Error to obtain info by mixer"); + ret = getControlDetails((HMIXEROBJ)0, dwVolumeControlID, mxc.cMultipleItems, + &mxcdVolume); + if (ret != MMSYSERR_NOERROR) + throw TSoundDeviceException(TSoundDeviceException::UnableVolume, + "Error to obtain info by mixer"); - DWORD dwVal = mxcdVolume.dwValue; + DWORD dwVal = mxcdVolume.dwValue; - return (double)dwVal * 10.0 / (double)mxc.Bounds.dwMaximum; + return (double)dwVal * 10.0 / (double)mxc.Bounds.dwMaximum; } //------------------------------------------------------------------------------ -bool TSoundInputDevice::setVolume(double value) -{ - DWORD dwVolumeControlID, - dwMaximum; - - UINT nNumMixers; - MMRESULT ret; - MIXERLINE mxl; - - nNumMixers = mixerGetNumDevs(); - - if (nNumMixers == 0) - throw TSoundDeviceException( - TSoundDeviceException::NoMixer, - "Doesn't exist a audio mixer device"); - - // get dwLineID - ret = getLineInfo((HMIXEROBJ)0, MIXERLINE_COMPONENTTYPE_DST_WAVEIN, mxl); - if (ret != MMSYSERR_NOERROR) - throw TException("Error to obtain info by mixer"); - - // get dwControlID - MIXERCONTROL mxc; - ret = getLineControl(mxc, (HMIXEROBJ)0, mxl.dwLineID, MIXERCONTROL_CONTROLTYPE_VOLUME); - if (ret != MMSYSERR_NOERROR) - throw TSoundDeviceException( - TSoundDeviceException::UnableVolume, - "Error to obtain info by mixer"); - - dwMaximum = mxc.Bounds.dwMaximum; - dwVolumeControlID = mxc.dwControlID; - - int newValue; - double fattProp = ((double)(mxc.Metrics.cSteps - 1) * value) / 10; - double delta = (double)(dwMaximum / (mxc.Metrics.cSteps - 1)); - newValue = (int)(tround(fattProp) * delta); - - MIXERCONTROLDETAILS_UNSIGNED mxcdVolume = {newValue}; - ret = setControlDetails((HMIXEROBJ)0, - dwVolumeControlID, - mxc.cMultipleItems, - &mxcdVolume); - if (ret != MMSYSERR_NOERROR) - throw TSoundDeviceException( - TSoundDeviceException::UnableVolume, - "Error to obtain info by mixer"); - return true; +bool TSoundInputDevice::setVolume(double value) { + DWORD dwVolumeControlID, dwMaximum; + + UINT nNumMixers; + MMRESULT ret; + MIXERLINE mxl; + + nNumMixers = mixerGetNumDevs(); + + if (nNumMixers == 0) + throw TSoundDeviceException(TSoundDeviceException::NoMixer, + "Doesn't exist a audio mixer device"); + + // get dwLineID + ret = getLineInfo((HMIXEROBJ)0, MIXERLINE_COMPONENTTYPE_DST_WAVEIN, mxl); + if (ret != MMSYSERR_NOERROR) + throw TException("Error to obtain info by mixer"); + + // get dwControlID + MIXERCONTROL mxc; + ret = getLineControl(mxc, (HMIXEROBJ)0, mxl.dwLineID, + MIXERCONTROL_CONTROLTYPE_VOLUME); + if (ret != MMSYSERR_NOERROR) + throw TSoundDeviceException(TSoundDeviceException::UnableVolume, + "Error to obtain info by mixer"); + + dwMaximum = mxc.Bounds.dwMaximum; + dwVolumeControlID = mxc.dwControlID; + + int newValue; + double fattProp = ((double)(mxc.Metrics.cSteps - 1) * value) / 10; + double delta = (double)(dwMaximum / (mxc.Metrics.cSteps - 1)); + newValue = (int)(tround(fattProp) * delta); + + MIXERCONTROLDETAILS_UNSIGNED mxcdVolume = {newValue}; + ret = setControlDetails((HMIXEROBJ)0, dwVolumeControlID, mxc.cMultipleItems, + &mxcdVolume); + if (ret != MMSYSERR_NOERROR) + throw TSoundDeviceException(TSoundDeviceException::UnableVolume, + "Error to obtain info by mixer"); + return true; } //------------------------------------------------------------------------------ -bool TSoundInputDevice::supportsVolume() -{ - UINT nNumMixers; - MMRESULT ret; - MIXERLINE mxl; +bool TSoundInputDevice::supportsVolume() { + UINT nNumMixers; + MMRESULT ret; + MIXERLINE mxl; - nNumMixers = mixerGetNumDevs(); + nNumMixers = mixerGetNumDevs(); - if (nNumMixers == 0) - throw TSoundDeviceException( - TSoundDeviceException::NoMixer, - "Doesn't exist a audio mixer device"); + if (nNumMixers == 0) + throw TSoundDeviceException(TSoundDeviceException::NoMixer, + "Doesn't exist a audio mixer device"); - // get dwLineID - ret = getLineInfo((HMIXEROBJ)0, MIXERLINE_COMPONENTTYPE_DST_WAVEIN, mxl); - if (ret != MMSYSERR_NOERROR) - throw TSoundDeviceException( - TSoundDeviceException::UnableVolume, - "Error to obtain info by mixer"); + // get dwLineID + ret = getLineInfo((HMIXEROBJ)0, MIXERLINE_COMPONENTTYPE_DST_WAVEIN, mxl); + if (ret != MMSYSERR_NOERROR) + throw TSoundDeviceException(TSoundDeviceException::UnableVolume, + "Error to obtain info by mixer"); - // get dwControlID - MIXERCONTROL mxc; - ret = getLineControl(mxc, (HMIXEROBJ)0, mxl.dwLineID, MIXERCONTROL_CONTROLTYPE_VOLUME); - if (ret == MIXERR_INVALCONTROL) - return false; + // get dwControlID + MIXERCONTROL mxc; + ret = getLineControl(mxc, (HMIXEROBJ)0, mxl.dwLineID, + MIXERCONTROL_CONTROLTYPE_VOLUME); + if (ret == MIXERR_INVALCONTROL) return false; - if (ret != MMSYSERR_NOERROR) - throw TSoundDeviceException( - TSoundDeviceException::UnableVolume, - "Error to obtain info by mixer"); + if (ret != MMSYSERR_NOERROR) + throw TSoundDeviceException(TSoundDeviceException::UnableVolume, + "Error to obtain info by mixer"); - return true; + return true; } //------------------------------------------------------------------------------ -bool TSoundInputDevice::isRecording() -{ - return m_imp->m_isRecording; -} +bool TSoundInputDevice::isRecording() { return m_imp->m_isRecording; } //------------------------------------------------------------------------------ @@ -1728,7 +1590,7 @@ bool TSoundInputDevice::isRecording() { MMRESULT ret; TSoundTrackFormat fmt; - + ret = isaFormatSupported(sampleRate, channelCount, bitPerSample, true); if (ret == MMSYSERR_NOERROR) @@ -1745,14 +1607,15 @@ bool TSoundInputDevice::isRecording() } if (ret == WAVERR_BADFORMAT) { - //avvvicinarsi al sample rate => dovrebbe esser OK avendo selezionato i piu' vicini + //avvvicinarsi al sample rate => dovrebbe esser OK avendo selezionato i piu' +vicini std::set::iterator it = m_imp->m_supportedRate.lower_bound(sampleRate); if (it == m_imp->m_supportedRate.end()) { - it = std::max_element(m_imp->m_supportedRate.begin(), - m_imp->m_supportedRate.end()); - if (it != m_imp->m_supportedRate.end()) - sampleRate = *(m_imp->m_supportedRate.rbegin()); + it = std::max_element(m_imp->m_supportedRate.begin(), + m_imp->m_supportedRate.end()); + if (it != m_imp->m_supportedRate.end()) + sampleRate = *(m_imp->m_supportedRate.rbegin()); else throw TSoundDeviceException( TSoundDeviceException::UnsupportedFormat, @@ -1799,9 +1662,9 @@ bool TSoundInputDevice::isRecording() //switch mono/stereo if (channelCount <= 1) channelCount = 1; - else + else channelCount = 2; - + ret = isaFormatSupported(sampleRate, channelCount, bitPerSample, true); if (ret == MMSYSERR_NOERROR) { @@ -1829,60 +1692,59 @@ bool TSoundInputDevice::isRecording() "Error to query supported format"); } */ -TSoundTrackFormat TSoundInputDevice::getPreferredFormat( - TUINT32 sampleRate, int channelCount, int bitPerSample) -{ - TSoundTrackFormat fmt; - - //avvvicinarsi al sample rate => dovrebbe esser OK avendo selezionato i piu' vicini - std::set::iterator it = m_imp->m_supportedRate.lower_bound(sampleRate); - if (it == m_imp->m_supportedRate.end()) { - it = std::max_element(m_imp->m_supportedRate.begin(), - m_imp->m_supportedRate.end()); - if (it != m_imp->m_supportedRate.end()) - sampleRate = *(m_imp->m_supportedRate.rbegin()); - else - throw TSoundDeviceException( - TSoundDeviceException::UnsupportedFormat, - "There isn't a supported format"); - } else - sampleRate = *it; - - if (bitPerSample <= 8) - bitPerSample = 8; - else if ((bitPerSample > 8 && bitPerSample < 16) || bitPerSample >= 16) - bitPerSample = 16; - - if (bitPerSample >= 16) - fmt.m_signedSample = true; - else - fmt.m_signedSample = false; - - //switch mono/stereo - if (channelCount <= 1) - channelCount = 1; - else - channelCount = 2; - - fmt.m_bitPerSample = bitPerSample; - fmt.m_channelCount = channelCount; - fmt.m_sampleRate = sampleRate; - - return fmt; +TSoundTrackFormat TSoundInputDevice::getPreferredFormat(TUINT32 sampleRate, + int channelCount, + int bitPerSample) { + TSoundTrackFormat fmt; + + // avvvicinarsi al sample rate => dovrebbe esser OK avendo selezionato i piu' + // vicini + std::set::iterator it = m_imp->m_supportedRate.lower_bound(sampleRate); + if (it == m_imp->m_supportedRate.end()) { + it = std::max_element(m_imp->m_supportedRate.begin(), + m_imp->m_supportedRate.end()); + if (it != m_imp->m_supportedRate.end()) + sampleRate = *(m_imp->m_supportedRate.rbegin()); + else + throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat, + "There isn't a supported format"); + } else + sampleRate = *it; + + if (bitPerSample <= 8) + bitPerSample = 8; + else if ((bitPerSample > 8 && bitPerSample < 16) || bitPerSample >= 16) + bitPerSample = 16; + + if (bitPerSample >= 16) + fmt.m_signedSample = true; + else + fmt.m_signedSample = false; + + // switch mono/stereo + if (channelCount <= 1) + channelCount = 1; + else + channelCount = 2; + + fmt.m_bitPerSample = bitPerSample; + fmt.m_channelCount = channelCount; + fmt.m_sampleRate = sampleRate; + + return fmt; } //------------------------------------------------------------------------------ -TSoundTrackFormat TSoundInputDevice::getPreferredFormat(const TSoundTrackFormat &format) -{ - try { - return getPreferredFormat( - format.m_sampleRate, format.m_channelCount, format.m_bitPerSample); - } catch (TSoundDeviceException &e) { - throw TSoundDeviceException( - TSoundDeviceException::UnsupportedFormat, - e.getMessage()); - } +TSoundTrackFormat TSoundInputDevice::getPreferredFormat( + const TSoundTrackFormat &format) { + try { + return getPreferredFormat(format.m_sampleRate, format.m_channelCount, + format.m_bitPerSample); + } catch (TSoundDeviceException &e) { + throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat, + e.getMessage()); + } } //============================================================================== @@ -1891,190 +1753,167 @@ TSoundTrackFormat TSoundInputDevice::getPreferredFormat(const TSoundTrackFormat //============================================================================== //============================================================================== -namespace -{ +namespace { // restituisce dentro la struttura mxc le informazioni relative // al controllo di tipo dwControlType associato alla linea // identificata da dwLineID -MMRESULT getLineControl(MIXERCONTROL &mxc, - HMIXEROBJ hMixer, - DWORD dwLineID, - DWORD dwControlType) -{ - MIXERLINECONTROLS mxlc; - mxlc.cbStruct = sizeof(MIXERLINECONTROLS); - mxlc.dwLineID = dwLineID; - mxlc.dwControlType = dwControlType; - mxlc.cControls = 1; - mxlc.cbmxctrl = sizeof(MIXERCONTROL); - mxlc.pamxctrl = &mxc; - MMRESULT ret = mixerGetLineControls((HMIXEROBJ)hMixer, - &mxlc, - MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE); - return ret; +MMRESULT getLineControl(MIXERCONTROL &mxc, HMIXEROBJ hMixer, DWORD dwLineID, + DWORD dwControlType) { + MIXERLINECONTROLS mxlc; + mxlc.cbStruct = sizeof(MIXERLINECONTROLS); + mxlc.dwLineID = dwLineID; + mxlc.dwControlType = dwControlType; + mxlc.cControls = 1; + mxlc.cbmxctrl = sizeof(MIXERCONTROL); + mxlc.pamxctrl = &mxc; + MMRESULT ret = mixerGetLineControls( + (HMIXEROBJ)hMixer, &mxlc, + MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE); + return ret; } //------------------------------------------------------------------------------ // restituisce nella struttura mxl le informazioni relative alla linea // sorgente individuata dagli estremi destination e source -MMRESULT getLineInfo(HMIXEROBJ hMixer, - MIXERLINE &mxl, - DWORD destination, - DWORD source) -{ - MMRESULT ret; +MMRESULT getLineInfo(HMIXEROBJ hMixer, MIXERLINE &mxl, DWORD destination, + DWORD source) { + MMRESULT ret; - mxl.cbStruct = sizeof(mxl); - mxl.dwDestination = destination; - mxl.dwSource = source; - ret = mixerGetLineInfo(0, &mxl, MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_SOURCE); - return ret; + mxl.cbStruct = sizeof(mxl); + mxl.dwDestination = destination; + mxl.dwSource = source; + ret = mixerGetLineInfo(0, &mxl, + MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_SOURCE); + return ret; } //------------------------------------------------------------------------------ // restituisce nella struttura mxl le informazioni relative alla linea // individuata da dwLineID -MMRESULT getLineInfo(HMIXEROBJ hMixer, - MIXERLINE &mxl, - DWORD dwLineID) -{ - MMRESULT ret; +MMRESULT getLineInfo(HMIXEROBJ hMixer, MIXERLINE &mxl, DWORD dwLineID) { + MMRESULT ret; - mxl.cbStruct = sizeof(mxl); - mxl.dwLineID = dwLineID; - ret = mixerGetLineInfo((HMIXEROBJ)hMixer, - &mxl, - MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_LINEID); - return ret; + mxl.cbStruct = sizeof(mxl); + mxl.dwLineID = dwLineID; + ret = mixerGetLineInfo((HMIXEROBJ)hMixer, &mxl, + MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_LINEID); + return ret; } //------------------------------------------------------------------------------ // restituisce nella struttura mxl le informazioni relative alla linea // individuata dal tipo specificato in dwComponentType -MMRESULT getLineInfo(HMIXEROBJ hMixer, - DWORD dwComponentType, - MIXERLINE &mxl) -{ - MMRESULT ret; +MMRESULT getLineInfo(HMIXEROBJ hMixer, DWORD dwComponentType, MIXERLINE &mxl) { + MMRESULT ret; - mxl.cbStruct = sizeof(MIXERLINE); - mxl.dwComponentType = dwComponentType; - ret = mixerGetLineInfo((HMIXEROBJ)hMixer, - &mxl, - MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE); - return ret; + mxl.cbStruct = sizeof(MIXERLINE); + mxl.dwComponentType = dwComponentType; + ret = + mixerGetLineInfo((HMIXEROBJ)hMixer, &mxl, + MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE); + return ret; } //------------------------------------------------------------------------------ // consente di settare il valore booleano specificato in mxcdSelectValue // relativo al controllo specificato in dwSelectControlID -MMRESULT setControlDetails(HMIXEROBJ hMixer, - DWORD dwSelectControlID, - DWORD dwMultipleItems, - MIXERCONTROLDETAILS_BOOLEAN *mxcdSelectValue) -{ - MMRESULT ret; - MIXERCONTROLDETAILS mxcd; - mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS); - mxcd.dwControlID = dwSelectControlID; - mxcd.cChannels = 1; - mxcd.cMultipleItems = dwMultipleItems; - mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN); - mxcd.paDetails = mxcdSelectValue; - ret = mixerSetControlDetails((HMIXEROBJ)hMixer, - &mxcd, - MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE); - return ret; +MMRESULT setControlDetails(HMIXEROBJ hMixer, DWORD dwSelectControlID, + DWORD dwMultipleItems, + MIXERCONTROLDETAILS_BOOLEAN *mxcdSelectValue) { + MMRESULT ret; + MIXERCONTROLDETAILS mxcd; + mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS); + mxcd.dwControlID = dwSelectControlID; + mxcd.cChannels = 1; + mxcd.cMultipleItems = dwMultipleItems; + mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN); + mxcd.paDetails = mxcdSelectValue; + ret = mixerSetControlDetails( + (HMIXEROBJ)hMixer, &mxcd, + MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE); + return ret; } //------------------------------------------------------------------------------ // consente di settare il valore UNSIGNED specificato in mxcdSelectValue // relativo al controllo specificato in dwSelectControlID -MMRESULT setControlDetails(HMIXEROBJ hMixer, - DWORD dwSelectControlID, - DWORD dwMultipleItems, - MIXERCONTROLDETAILS_UNSIGNED *mxcdSelectValue) -{ - MMRESULT ret; - MIXERCONTROLDETAILS mxcd; - mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS); - mxcd.dwControlID = dwSelectControlID; - mxcd.cChannels = 1; - mxcd.cMultipleItems = dwMultipleItems; - mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED); - mxcd.paDetails = mxcdSelectValue; - ret = mixerSetControlDetails((HMIXEROBJ)hMixer, - &mxcd, - MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE); - return ret; +MMRESULT setControlDetails(HMIXEROBJ hMixer, DWORD dwSelectControlID, + DWORD dwMultipleItems, + MIXERCONTROLDETAILS_UNSIGNED *mxcdSelectValue) { + MMRESULT ret; + MIXERCONTROLDETAILS mxcd; + mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS); + mxcd.dwControlID = dwSelectControlID; + mxcd.cChannels = 1; + mxcd.cMultipleItems = dwMultipleItems; + mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED); + mxcd.paDetails = mxcdSelectValue; + ret = mixerSetControlDetails( + (HMIXEROBJ)hMixer, &mxcd, + MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE); + return ret; } //------------------------------------------------------------------------------ // consente di ottenere il valore UNSIGNED specificato in mxcdSelectValue // relativo al controllo specificato in dwSelectControlID -MMRESULT getControlDetails(HMIXEROBJ hMixer, - DWORD dwSelectControlID, - DWORD dwMultipleItems, - MIXERCONTROLDETAILS_UNSIGNED *mxcdSelectValue) -{ - MMRESULT ret; - MIXERCONTROLDETAILS mxcd; - mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS); - mxcd.dwControlID = dwSelectControlID; - mxcd.cChannels = 1; - mxcd.cMultipleItems = dwMultipleItems; - mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED); - mxcd.paDetails = mxcdSelectValue; - ret = mixerGetControlDetails((HMIXEROBJ)hMixer, - &mxcd, - MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE); - return ret; +MMRESULT getControlDetails(HMIXEROBJ hMixer, DWORD dwSelectControlID, + DWORD dwMultipleItems, + MIXERCONTROLDETAILS_UNSIGNED *mxcdSelectValue) { + MMRESULT ret; + MIXERCONTROLDETAILS mxcd; + mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS); + mxcd.dwControlID = dwSelectControlID; + mxcd.cChannels = 1; + mxcd.cMultipleItems = dwMultipleItems; + mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED); + mxcd.paDetails = mxcdSelectValue; + ret = mixerGetControlDetails( + (HMIXEROBJ)hMixer, &mxcd, + MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE); + return ret; } //------------------------------------------------------------------------------ // consente di ottenere la lista di informazioni in pmxcdSelectText // relativo al controllo specificato in dwSelectControlID -MMRESULT getControlDetails(HMIXEROBJ hMixer, - DWORD dwSelectControlID, - DWORD dwMultipleItems, - MIXERCONTROLDETAILS_LISTTEXT *pmxcdSelectText) -{ - MMRESULT ret; - MIXERCONTROLDETAILS mxcd; +MMRESULT getControlDetails(HMIXEROBJ hMixer, DWORD dwSelectControlID, + DWORD dwMultipleItems, + MIXERCONTROLDETAILS_LISTTEXT *pmxcdSelectText) { + MMRESULT ret; + MIXERCONTROLDETAILS mxcd; - mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS); - mxcd.dwControlID = dwSelectControlID; - mxcd.cChannels = 1; - mxcd.cMultipleItems = dwMultipleItems; - mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_LISTTEXT); - mxcd.paDetails = pmxcdSelectText; - ret = mixerGetControlDetails((HMIXEROBJ)0, - &mxcd, - MIXER_GETCONTROLDETAILSF_LISTTEXT); - return ret; + mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS); + mxcd.dwControlID = dwSelectControlID; + mxcd.cChannels = 1; + mxcd.cMultipleItems = dwMultipleItems; + mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_LISTTEXT); + mxcd.paDetails = pmxcdSelectText; + ret = mixerGetControlDetails((HMIXEROBJ)0, &mxcd, + MIXER_GETCONTROLDETAILSF_LISTTEXT); + return ret; } //------------------------------------------------------------------------------ // restituiscei l nome della linea identificata da lineID -std::string getMixerLineName(DWORD lineID) -{ - MIXERLINE mxl; - MMRESULT ret; +std::string getMixerLineName(DWORD lineID) { + MIXERLINE mxl; + MMRESULT ret; - ret = getLineInfo((HMIXEROBJ)0, mxl, lineID); + ret = getLineInfo((HMIXEROBJ)0, mxl, lineID); #ifdef TNZCORE_LIGHT - assert(false); - return ""; + assert(false); + return ""; #else - return std::string(mxl.szName); + return std::string(mxl.szName); #endif } @@ -2082,270 +1921,255 @@ std::string getMixerLineName(DWORD lineID) // restituisce la lista degli identificativi delle linee sorgente associate // alla destinazione di tipo dstComponentType -std::list getMixerSrcLines(DWORD dstComponentType) -{ - std::list srcList; - MMRESULT ret; - MIXERLINE mxl; +std::list getMixerSrcLines(DWORD dstComponentType) { + std::list srcList; + MMRESULT ret; + MIXERLINE mxl; - ret = getLineInfo((HMIXEROBJ)0, MIXERLINE_COMPONENTTYPE_DST_WAVEIN, mxl); - if (ret != MMSYSERR_NOERROR) - //forse bisognerebbe lanciare un'eccezione - return srcList; //non ha linea di dst per la registrazione + ret = getLineInfo((HMIXEROBJ)0, MIXERLINE_COMPONENTTYPE_DST_WAVEIN, mxl); + if (ret != MMSYSERR_NOERROR) + // forse bisognerebbe lanciare un'eccezione + return srcList; // non ha linea di dst per la registrazione - int v; - for (v = 0; v < (int)mxl.cConnections; v++) { - MIXERLINE mxl1; + int v; + for (v = 0; v < (int)mxl.cConnections; v++) { + MIXERLINE mxl1; - ret = getLineInfo((HMIXEROBJ)0, mxl1, mxl.dwDestination, v); - if (ret == MMSYSERR_NOERROR) - srcList.push_back(mxl1.dwLineID); - } - return srcList; + ret = getLineInfo((HMIXEROBJ)0, mxl1, mxl.dwDestination, v); + if (ret == MMSYSERR_NOERROR) srcList.push_back(mxl1.dwLineID); + } + return srcList; } //------------------------------------------------------------------------------ // restituisce la lista degli identificativi delle linee sorgente di tipo // srcComponentType associate alla destinazione di tipo dstComponentType -std::list getMixerSrcLines(DWORD dstComponentType, DWORD srcComponentType) -{ - std::list srcList; - MMRESULT ret; - MIXERLINE mxl; +std::list getMixerSrcLines(DWORD dstComponentType, + DWORD srcComponentType) { + std::list srcList; + MMRESULT ret; + MIXERLINE mxl; - ret = getLineInfo((HMIXEROBJ)0, MIXERLINE_COMPONENTTYPE_DST_WAVEIN, mxl); - if (ret != MMSYSERR_NOERROR) - //forse bisognerebbe lanciare un'eccezione - return srcList; //non ha linea di dst per la registrazione + ret = getLineInfo((HMIXEROBJ)0, MIXERLINE_COMPONENTTYPE_DST_WAVEIN, mxl); + if (ret != MMSYSERR_NOERROR) + // forse bisognerebbe lanciare un'eccezione + return srcList; // non ha linea di dst per la registrazione - int v; - for (v = 0; v < (int)mxl.cConnections; v++) { - MIXERLINE mxl1; + int v; + for (v = 0; v < (int)mxl.cConnections; v++) { + MIXERLINE mxl1; - ret = getLineInfo((HMIXEROBJ)0, mxl1, mxl.dwDestination, v); - if (ret == MMSYSERR_NOERROR) - if (mxl1.dwComponentType == srcComponentType) - srcList.push_back(mxl1.dwLineID); - } - return srcList; + ret = getLineInfo((HMIXEROBJ)0, mxl1, mxl.dwDestination, v); + if (ret == MMSYSERR_NOERROR) + if (mxl1.dwComponentType == srcComponentType) + srcList.push_back(mxl1.dwLineID); + } + return srcList; } //------------------------------------------------------------------------------ // restituisce true sse la linea destinazione di tipo dstComponentType // supporta una linea sorgente di tipo srcComponentType -bool isSrcLineSupported(DWORD dstComponentType, DWORD srcComponentType) -{ - // ci possono essere piu' linee sorgente dello stesso tipo in - // corrispondenza di una data linea destinazione ? - MMRESULT ret; - MIXERLINE mxl; +bool isSrcLineSupported(DWORD dstComponentType, DWORD srcComponentType) { + // ci possono essere piu' linee sorgente dello stesso tipo in + // corrispondenza di una data linea destinazione ? + MMRESULT ret; + MIXERLINE mxl; - ret = getLineInfo((HMIXEROBJ)0, MIXERLINE_COMPONENTTYPE_DST_WAVEIN, mxl); - if (ret != MMSYSERR_NOERROR) - return false; //non ha linea di dst per la registrazione + ret = getLineInfo((HMIXEROBJ)0, MIXERLINE_COMPONENTTYPE_DST_WAVEIN, mxl); + if (ret != MMSYSERR_NOERROR) + return false; // non ha linea di dst per la registrazione - int v; - for (v = 0; v < (int)mxl.cConnections; v++) { - MIXERLINE mxl1; + int v; + for (v = 0; v < (int)mxl.cConnections; v++) { + MIXERLINE mxl1; - ret = getLineInfo((HMIXEROBJ)0, mxl1, mxl.dwDestination, v); - if (ret == MMSYSERR_NOERROR) - if (mxl1.dwComponentType == srcComponentType) - return true; - } + ret = getLineInfo((HMIXEROBJ)0, mxl1, mxl.dwDestination, v); + if (ret == MMSYSERR_NOERROR) + if (mxl1.dwComponentType == srcComponentType) return true; + } - return false; + return false; } //------------------------------------------------------------------------------ -bool activateSrcLine(const MIXERLINE &mxlDst, DWORD componentTypeSrc) -{ - if (!isSrcLineSupported(mxlDst.dwComponentType, componentTypeSrc)) - return false; +bool activateSrcLine(const MIXERLINE &mxlDst, DWORD componentTypeSrc) { + if (!isSrcLineSupported(mxlDst.dwComponentType, componentTypeSrc)) + return false; - bool bRetVal = true; + bool bRetVal = true; - for (DWORD v = 0; v < mxlDst.cConnections; v++) { - MIXERLINE mxlSrc; - MMRESULT ret = getLineInfo((HMIXEROBJ)0, mxlSrc, mxlDst.dwDestination, v); + for (DWORD v = 0; v < mxlDst.cConnections; v++) { + MIXERLINE mxlSrc; + MMRESULT ret = getLineInfo((HMIXEROBJ)0, mxlSrc, mxlDst.dwDestination, v); - if (ret == MMSYSERR_NOERROR) { - // chiedo il controllo di tipo MUTE della linea sorgente - MIXERCONTROL mxc; - ret = getLineControl( - mxc, (HMIXEROBJ)0, mxlSrc.dwLineID, - MIXERCONTROL_CONTROLTYPE_MUTE); + if (ret == MMSYSERR_NOERROR) { + // chiedo il controllo di tipo MUTE della linea sorgente + MIXERCONTROL mxc; + ret = getLineControl(mxc, (HMIXEROBJ)0, mxlSrc.dwLineID, + MIXERCONTROL_CONTROLTYPE_MUTE); - if (ret == MMSYSERR_NOERROR) { - MIXERCONTROLDETAILS_BOOLEAN mxcdSelectValue; - mxcdSelectValue.fValue = mxlSrc.dwComponentType == componentTypeSrc ? 0L : 1L; + if (ret == MMSYSERR_NOERROR) { + MIXERCONTROLDETAILS_BOOLEAN mxcdSelectValue; + mxcdSelectValue.fValue = + mxlSrc.dwComponentType == componentTypeSrc ? 0L : 1L; - ret = setControlDetails((HMIXEROBJ)0, mxc.dwControlID, - mxc.cMultipleItems, &mxcdSelectValue); - if (ret != MMSYSERR_NOERROR) - bRetVal = false; - } - } - } - return bRetVal; + ret = setControlDetails((HMIXEROBJ)0, mxc.dwControlID, + mxc.cMultipleItems, &mxcdSelectValue); + if (ret != MMSYSERR_NOERROR) bRetVal = false; + } + } + } + return bRetVal; } //------------------------------------------------------------------------------ -bool setSrcMixMuxControl(MIXERCONTROL mxc, DWORD componentTypeSrc) -{ - MMRESULT ret; - DWORD dwIndexLine; - bool found = false; - - // mantengo nota del ID del controllo dsst individuato e - // del numero di linee src ad esso associate - DWORD dwSelectControlID = mxc.dwControlID; - DWORD dwMultipleItems = mxc.cMultipleItems; - - if (dwMultipleItems == 0) - return false; - - // determino l'indice dell'item corrispondente alla linea sorgente - // di tipo componentTypeSrc - - std::unique_ptr - pmxcdSelectText(new MIXERCONTROLDETAILS_LISTTEXT[dwMultipleItems]); - - if (pmxcdSelectText) { - // estraggo le info su tutte le linee associate al controllo - ret = getControlDetails((HMIXEROBJ)0, dwSelectControlID, - dwMultipleItems, pmxcdSelectText.get()); - - if (ret == MMSYSERR_NOERROR) { - for (DWORD dwi = 0; dwi < dwMultipleItems; dwi++) { - // prendo le info su ogni linea e verifico se e' del giusto tipo - MIXERLINE mxl; - ret = getLineInfo((HMIXEROBJ)0, mxl, pmxcdSelectText[dwi].dwParam1); - if (ret == MMSYSERR_NOERROR && mxl.dwComponentType == componentTypeSrc) { - dwIndexLine = dwi; - found = true; - break; - } - } - } - - if (!found) - return false; - } - - if (dwIndexLine >= dwMultipleItems) - return false; - - bool bRetVal = false; - - std::unique_ptr - pmxcdSelectValue(new MIXERCONTROLDETAILS_BOOLEAN[dwMultipleItems]); - - if (pmxcdSelectValue) { - ::ZeroMemory(pmxcdSelectValue.get(), dwMultipleItems * sizeof(MIXERCONTROLDETAILS_BOOLEAN)); - - // impostazione del valore - pmxcdSelectValue[dwIndexLine].fValue = (TINT32)1; // lVal; //dovrebbe esser uno - - ret = setControlDetails((HMIXEROBJ)0, - dwSelectControlID, - dwMultipleItems, - pmxcdSelectValue.get()); - if (ret == MMSYSERR_NOERROR) - bRetVal = true; - } - return bRetVal; +bool setSrcMixMuxControl(MIXERCONTROL mxc, DWORD componentTypeSrc) { + MMRESULT ret; + DWORD dwIndexLine; + bool found = false; + + // mantengo nota del ID del controllo dsst individuato e + // del numero di linee src ad esso associate + DWORD dwSelectControlID = mxc.dwControlID; + DWORD dwMultipleItems = mxc.cMultipleItems; + + if (dwMultipleItems == 0) return false; + + // determino l'indice dell'item corrispondente alla linea sorgente + // di tipo componentTypeSrc + + std::unique_ptr pmxcdSelectText( + new MIXERCONTROLDETAILS_LISTTEXT[dwMultipleItems]); + + if (pmxcdSelectText) { + // estraggo le info su tutte le linee associate al controllo + ret = getControlDetails((HMIXEROBJ)0, dwSelectControlID, dwMultipleItems, + pmxcdSelectText.get()); + + if (ret == MMSYSERR_NOERROR) { + for (DWORD dwi = 0; dwi < dwMultipleItems; dwi++) { + // prendo le info su ogni linea e verifico se e' del giusto tipo + MIXERLINE mxl; + ret = getLineInfo((HMIXEROBJ)0, mxl, pmxcdSelectText[dwi].dwParam1); + if (ret == MMSYSERR_NOERROR && + mxl.dwComponentType == componentTypeSrc) { + dwIndexLine = dwi; + found = true; + break; + } + } + } + + if (!found) return false; + } + + if (dwIndexLine >= dwMultipleItems) return false; + + bool bRetVal = false; + + std::unique_ptr pmxcdSelectValue( + new MIXERCONTROLDETAILS_BOOLEAN[dwMultipleItems]); + + if (pmxcdSelectValue) { + ::ZeroMemory(pmxcdSelectValue.get(), + dwMultipleItems * sizeof(MIXERCONTROLDETAILS_BOOLEAN)); + + // impostazione del valore + pmxcdSelectValue[dwIndexLine].fValue = + (TINT32)1; // lVal; //dovrebbe esser uno + + ret = setControlDetails((HMIXEROBJ)0, dwSelectControlID, dwMultipleItems, + pmxcdSelectValue.get()); + if (ret == MMSYSERR_NOERROR) bRetVal = true; + } + return bRetVal; } //------------------------------------------------------------------------------ -bool setRecordLine(TSoundInputDevice::Source typeInput) -{ - DWORD dwComponentTypeSrc; +bool setRecordLine(TSoundInputDevice::Source typeInput) { + DWORD dwComponentTypeSrc; - UINT nNumMixers; - MMRESULT ret; - MIXERLINE mxl = {0}; + UINT nNumMixers; + MMRESULT ret; + MIXERLINE mxl = {0}; - switch (typeInput) { - case TSoundInputDevice::LineIn: - dwComponentTypeSrc = MIXERLINE_COMPONENTTYPE_SRC_LINE /*| + switch (typeInput) { + case TSoundInputDevice::LineIn: + dwComponentTypeSrc = MIXERLINE_COMPONENTTYPE_SRC_LINE /*| MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY | MIXERLINE_COMPONENTTYPE_SRC_ANALOG*/; - break; - case TSoundInputDevice::DigitalIn: - dwComponentTypeSrc = MIXERLINE_COMPONENTTYPE_SRC_DIGITAL; - break; - case TSoundInputDevice::CdAudio: - dwComponentTypeSrc = MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC; - break; - default: - dwComponentTypeSrc = MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE; - } - - nNumMixers = mixerGetNumDevs(); - - if (nNumMixers == 0) - return false; - - // utilizziamo il MIXER di default identificato dall'indice 0 - // vedo se il device ha una linea dst per il wave_input - ret = getLineInfo((HMIXEROBJ)0, MIXERLINE_COMPONENTTYPE_DST_WAVEIN, mxl); - if (ret != MMSYSERR_NOERROR) - return false; //non ha linea di dst per la registrazione - - //vediamo che tipo controllo ha questa linea dst - - // sara' un MIXER? - MIXERCONTROL mxc = {0}; - - ret = getLineControl(mxc, - (HMIXEROBJ)0, - mxl.dwLineID, MIXERCONTROL_CONTROLTYPE_MIXER); - - if (ret != MMSYSERR_NOERROR) { - // no mixer, try MUX - ret = getLineControl(mxc, - (HMIXEROBJ)0, - mxl.dwLineID, MIXERCONTROL_CONTROLTYPE_MUX); - - if (ret != MMSYSERR_NOERROR) { - // vediamo se e' uno di quei device ne' MIXER ne' MUX - return activateSrcLine(mxl, dwComponentTypeSrc); - } else { - // la linea ha un controllo di tipo MUX - return setSrcMixMuxControl(mxc, dwComponentTypeSrc); - } - } else { - // la linea ha un controllo di tipo MIXER - return setSrcMixMuxControl(mxc, dwComponentTypeSrc); - } + break; + case TSoundInputDevice::DigitalIn: + dwComponentTypeSrc = MIXERLINE_COMPONENTTYPE_SRC_DIGITAL; + break; + case TSoundInputDevice::CdAudio: + dwComponentTypeSrc = MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC; + break; + default: + dwComponentTypeSrc = MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE; + } + + nNumMixers = mixerGetNumDevs(); + + if (nNumMixers == 0) return false; + + // utilizziamo il MIXER di default identificato dall'indice 0 + // vedo se il device ha una linea dst per il wave_input + ret = getLineInfo((HMIXEROBJ)0, MIXERLINE_COMPONENTTYPE_DST_WAVEIN, mxl); + if (ret != MMSYSERR_NOERROR) + return false; // non ha linea di dst per la registrazione + + // vediamo che tipo controllo ha questa linea dst + + // sara' un MIXER? + MIXERCONTROL mxc = {0}; + + ret = getLineControl(mxc, (HMIXEROBJ)0, mxl.dwLineID, + MIXERCONTROL_CONTROLTYPE_MIXER); + + if (ret != MMSYSERR_NOERROR) { + // no mixer, try MUX + ret = getLineControl(mxc, (HMIXEROBJ)0, mxl.dwLineID, + MIXERCONTROL_CONTROLTYPE_MUX); + + if (ret != MMSYSERR_NOERROR) { + // vediamo se e' uno di quei device ne' MIXER ne' MUX + return activateSrcLine(mxl, dwComponentTypeSrc); + } else { + // la linea ha un controllo di tipo MUX + return setSrcMixMuxControl(mxc, dwComponentTypeSrc); + } + } else { + // la linea ha un controllo di tipo MIXER + return setSrcMixMuxControl(mxc, dwComponentTypeSrc); + } } //------------------------------------------------------------------------------ -MMRESULT isaFormatSupported( - int sampleRate, int channelCount, int bitPerSample, bool input) -{ - WAVEFORMATEX wf; - MMRESULT ret; - - wf.wFormatTag = WAVE_FORMAT_PCM; - wf.nChannels = channelCount; - wf.nSamplesPerSec = sampleRate; - wf.wBitsPerSample = bitPerSample; - wf.nBlockAlign = (wf.nChannels * wf.wBitsPerSample) >> 3; - wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign; - wf.cbSize = 0; - - if (input) - ret = waveInOpen(NULL, WAVE_MAPPER, &wf, NULL, NULL, WAVE_FORMAT_QUERY); - else - ret = waveOutOpen(NULL, WAVE_MAPPER, &wf, NULL, NULL, WAVE_FORMAT_QUERY); - return ret; +MMRESULT isaFormatSupported(int sampleRate, int channelCount, int bitPerSample, + bool input) { + WAVEFORMATEX wf; + MMRESULT ret; + + wf.wFormatTag = WAVE_FORMAT_PCM; + wf.nChannels = channelCount; + wf.nSamplesPerSec = sampleRate; + wf.wBitsPerSample = bitPerSample; + wf.nBlockAlign = (wf.nChannels * wf.wBitsPerSample) >> 3; + wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign; + wf.cbSize = 0; + + if (input) + ret = waveInOpen(NULL, WAVE_MAPPER, &wf, NULL, NULL, WAVE_FORMAT_QUERY); + else + ret = waveOutOpen(NULL, WAVE_MAPPER, &wf, NULL, NULL, WAVE_FORMAT_QUERY); + return ret; } } diff --git a/toonz/sources/common/tsound/tsound_x.cpp b/toonz/sources/common/tsound/tsound_x.cpp index b86e1ae..a1e9f21 100644 --- a/toonz/sources/common/tsound/tsound_x.cpp +++ b/toonz/sources/common/tsound/tsound_x.cpp @@ -10,9 +10,8 @@ #include #include -//forward declaration -namespace -{ +// forward declaration +namespace { bool isInterfaceSupported(int deviceType, int interfaceType); bool setDefaultInput(TSoundInputDevice::Source type); bool setDefaultOutput(); @@ -20,485 +19,456 @@ bool isChangeOutput(ULONG sampleRate); } //============================================================================== -class TSoundOutputDeviceImp -{ +class TSoundOutputDeviceImp { public: - ALport m_port; - bool m_stopped; - bool m_isPlaying; - bool m_looped; - TSoundTrackFormat m_currentFormat; - std::queue m_queuedSoundTracks; - std::set m_supportedRate; + ALport m_port; + bool m_stopped; + bool m_isPlaying; + bool m_looped; + TSoundTrackFormat m_currentFormat; + std::queue m_queuedSoundTracks; + std::set m_supportedRate; + + TThread::Executor m_executor; + TThread::Mutex m_mutex; + + TSoundOutputDeviceImp() + : m_stopped(false) + , m_isPlaying(false) + , m_looped(false) + , m_port(NULL) + , m_queuedSoundTracks() + , m_supportedRate(){}; + + ~TSoundOutputDeviceImp(){}; + + bool doOpenDevice(const TSoundTrackFormat &format); + void insertAllRate(); + bool verifyRate(); +}; - TThread::Executor m_executor; - TThread::Mutex m_mutex; +//----------------------------------------------------------------------------- - TSoundOutputDeviceImp() - : m_stopped(false), m_isPlaying(false), m_looped(false), m_port(NULL), m_queuedSoundTracks(), m_supportedRate(){}; +bool TSoundOutputDeviceImp::doOpenDevice(const TSoundTrackFormat &format) { + ALconfig config; + ALpv pvbuf[3]; - ~TSoundOutputDeviceImp(){}; + m_currentFormat = format; - bool doOpenDevice(const TSoundTrackFormat &format); - void insertAllRate(); - bool verifyRate(); -}; + // AL_MONITOR_CTL fa parte dei vecchi andrebbero trovati quelli nuovi + pvbuf[0].param = AL_PORT_COUNT; + pvbuf[1].param = AL_MONITOR_CTL; + if (alGetParams(AL_DEFAULT_OUTPUT, pvbuf, 2) < 0) + if (oserror() == AL_BAD_DEVICE_ACCESS) + return false; // throw TException("Could not access audio hardware."); -//----------------------------------------------------------------------------- + if (!isInterfaceSupported(AL_DEFAULT_OUTPUT, AL_SPEAKER_IF_TYPE)) + return false; // throw TException("Speakers are not supported"); + + int dev = alGetResourceByName(AL_SYSTEM, (char *)"Headphone/Speaker", + AL_DEVICE_TYPE); + if (!dev) return false; // throw TException("invalid device speakers"); + + pvbuf[0].param = AL_DEFAULT_OUTPUT; + pvbuf[0].value.i = dev; + alSetParams(AL_SYSTEM, pvbuf, 1); + + ALfixed buf[2] = {alDoubleToFixed(0), alDoubleToFixed(0)}; + + config = alNewConfig(); + // qui devo metterci gli altoparlanti e poi setto i valori per il default + // output + pvbuf[0].param = AL_RATE; + pvbuf[0].value.ll = alDoubleToFixed((double)format.m_sampleRate); + pvbuf[1].param = AL_GAIN; + pvbuf[1].value.ptr = buf; + pvbuf[1].sizeIn = 8; + pvbuf[2].param = AL_INTERFACE; + pvbuf[2].value.i = AL_SPEAKER_IF_TYPE; + + if (alSetParams(AL_DEFAULT_OUTPUT, pvbuf, 3) < 0) return false; + // throw TException("Unable to set params for output device"); + + if (alSetChannels(config, format.m_channelCount) == -1) + return false; // throw TException("Error to setting audio hardware."); + + int bytePerSample = format.m_bitPerSample >> 3; + switch (bytePerSample) { + case 3: + bytePerSample++; + break; + default: + break; + } -bool TSoundOutputDeviceImp::doOpenDevice(const TSoundTrackFormat &format) -{ - ALconfig config; - ALpv pvbuf[3]; - - m_currentFormat = format; - - // AL_MONITOR_CTL fa parte dei vecchi andrebbero trovati quelli nuovi - pvbuf[0].param = AL_PORT_COUNT; - pvbuf[1].param = AL_MONITOR_CTL; - if (alGetParams(AL_DEFAULT_OUTPUT, pvbuf, 2) < 0) - if (oserror() == AL_BAD_DEVICE_ACCESS) - return false; //throw TException("Could not access audio hardware."); - - if (!isInterfaceSupported(AL_DEFAULT_OUTPUT, AL_SPEAKER_IF_TYPE)) - return false; //throw TException("Speakers are not supported"); - - int dev = alGetResourceByName(AL_SYSTEM, (char *)"Headphone/Speaker", AL_DEVICE_TYPE); - if (!dev) - return false; //throw TException("invalid device speakers"); - - pvbuf[0].param = AL_DEFAULT_OUTPUT; - pvbuf[0].value.i = dev; - alSetParams(AL_SYSTEM, pvbuf, 1); - - ALfixed buf[2] = {alDoubleToFixed(0), alDoubleToFixed(0)}; - - config = alNewConfig(); - // qui devo metterci gli altoparlanti e poi setto i valori per il default output - pvbuf[0].param = AL_RATE; - pvbuf[0].value.ll = alDoubleToFixed((double)format.m_sampleRate); - pvbuf[1].param = AL_GAIN; - pvbuf[1].value.ptr = buf; - pvbuf[1].sizeIn = 8; - pvbuf[2].param = AL_INTERFACE; - pvbuf[2].value.i = AL_SPEAKER_IF_TYPE; - - if (alSetParams(AL_DEFAULT_OUTPUT, pvbuf, 3) < 0) - return false; - //throw TException("Unable to set params for output device"); - - if (alSetChannels(config, format.m_channelCount) == -1) - return false; //throw TException("Error to setting audio hardware."); - - int bytePerSample = format.m_bitPerSample >> 3; - switch (bytePerSample) { - case 3: - bytePerSample++; - break; - default: - break; - } - - if (alSetWidth(config, bytePerSample) == -1) - return false; //throw TException("Error to setting audio hardware."); - - if (alSetSampFmt(config, AL_SAMPFMT_TWOSCOMP) == -1) - return false; //throw TException("Error to setting audio hardware."); - - if (alSetQueueSize(config, (TINT32)format.m_sampleRate) == -1) - return false; //throw TException("Error to setting audio hardware."); - - m_port = alOpenPort("AudioOutput", "w", config); - if (!m_port) - return false; //throw TException("Could not open audio port."); - - alFreeConfig(config); - return true; + if (alSetWidth(config, bytePerSample) == -1) + return false; // throw TException("Error to setting audio hardware."); + + if (alSetSampFmt(config, AL_SAMPFMT_TWOSCOMP) == -1) + return false; // throw TException("Error to setting audio hardware."); + + if (alSetQueueSize(config, (TINT32)format.m_sampleRate) == -1) + return false; // throw TException("Error to setting audio hardware."); + + m_port = alOpenPort("AudioOutput", "w", config); + if (!m_port) return false; // throw TException("Could not open audio port."); + + alFreeConfig(config); + return true; } //----------------------------------------------------------------------------- -void TSoundOutputDeviceImp::insertAllRate() -{ - m_supportedRate.insert(8000); - m_supportedRate.insert(11025); - m_supportedRate.insert(16000); - m_supportedRate.insert(22050); - m_supportedRate.insert(32000); - m_supportedRate.insert(44100); - m_supportedRate.insert(48000); +void TSoundOutputDeviceImp::insertAllRate() { + m_supportedRate.insert(8000); + m_supportedRate.insert(11025); + m_supportedRate.insert(16000); + m_supportedRate.insert(22050); + m_supportedRate.insert(32000); + m_supportedRate.insert(44100); + m_supportedRate.insert(48000); } //----------------------------------------------------------------------------- -bool TSoundOutputDeviceImp::verifyRate() -{ - //Sample Rate - ALparamInfo pinfo; - int ret = alGetParamInfo(AL_DEFAULT_OUTPUT, AL_RATE, &pinfo); - if (ret != -1 && pinfo.elementType == AL_FIXED_ELEM) { - int min = (int)alFixedToDouble(pinfo.min.ll); - int max = (int)alFixedToDouble(pinfo.max.ll); - - std::set::iterator it; - for (it = m_supportedRate.begin(); it != m_supportedRate.end(); ++it) - if (*it < min || *it > max) - m_supportedRate.erase(*it); - if (m_supportedRate.end() == m_supportedRate.begin()) - return false; - } else if (ret == AL_BAD_PARAM) - return false; - else - return false; - return true; +bool TSoundOutputDeviceImp::verifyRate() { + // Sample Rate + ALparamInfo pinfo; + int ret = alGetParamInfo(AL_DEFAULT_OUTPUT, AL_RATE, &pinfo); + if (ret != -1 && pinfo.elementType == AL_FIXED_ELEM) { + int min = (int)alFixedToDouble(pinfo.min.ll); + int max = (int)alFixedToDouble(pinfo.max.ll); + + std::set::iterator it; + for (it = m_supportedRate.begin(); it != m_supportedRate.end(); ++it) + if (*it < min || *it > max) m_supportedRate.erase(*it); + if (m_supportedRate.end() == m_supportedRate.begin()) return false; + } else if (ret == AL_BAD_PARAM) + return false; + else + return false; + return true; } //============================================================================== -class PlayTask : public TThread::Runnable -{ +class PlayTask : public TThread::Runnable { public: - TSoundOutputDeviceImp *m_devImp; - TSoundTrackP m_sndtrack; + TSoundOutputDeviceImp *m_devImp; + TSoundTrackP m_sndtrack; - PlayTask(TSoundOutputDeviceImp *devImp, const TSoundTrackP &st) - : TThread::Runnable(), m_devImp(devImp), m_sndtrack(st){}; + PlayTask(TSoundOutputDeviceImp *devImp, const TSoundTrackP &st) + : TThread::Runnable(), m_devImp(devImp), m_sndtrack(st){}; - ~PlayTask(){}; + ~PlayTask(){}; - void run(); + void run(); }; -void PlayTask::run() -{ - int leftToPlay = m_sndtrack->getSampleCount(); - int i = 0; - - if (!m_devImp->m_port || - (m_devImp->m_currentFormat != m_sndtrack->getFormat()) || - isChangeOutput(m_sndtrack->getSampleRate())) - if (!m_devImp->doOpenDevice(m_sndtrack->getFormat())) - return; - - while ((leftToPlay > 0) && m_devImp->m_isPlaying) { - int fillable = alGetFillable(m_devImp->m_port); - if (!fillable) - continue; - - if (fillable < leftToPlay) { - alWriteFrames(m_devImp->m_port, (void *)(m_sndtrack->getRawData() + i), fillable); - // ricorda getSampleSize restituisce m_sampleSize che comprende gia' - // la moltiplicazione per il numero dei canali - i += fillable * m_sndtrack->getSampleSize(); - leftToPlay -= fillable; - } else { - alWriteFrames(m_devImp->m_port, (void *)(m_sndtrack->getRawData() + i), leftToPlay); - leftToPlay = 0; - } - } - - if (!m_devImp->m_stopped) { - while (ALgetfilled(m_devImp->m_port) > 0) - sginap(1); - { - TThread::ScopedLock sl(m_devImp->m_mutex); - if (!m_devImp->m_looped) - m_devImp->m_queuedSoundTracks.pop(); - if (m_devImp->m_queuedSoundTracks.empty()) { - m_devImp->m_isPlaying = false; - m_devImp->m_stopped = true; - m_devImp->m_looped = false; - } else { - m_devImp->m_executor.addTask( - new PlayTask(m_devImp, m_devImp->m_queuedSoundTracks.front())); - } - } - } else { - alDiscardFrames(m_devImp->m_port, alGetFilled(m_devImp->m_port)); - while (!m_devImp->m_queuedSoundTracks.empty()) - m_devImp->m_queuedSoundTracks.pop(); - } +void PlayTask::run() { + int leftToPlay = m_sndtrack->getSampleCount(); + int i = 0; + + if (!m_devImp->m_port || + (m_devImp->m_currentFormat != m_sndtrack->getFormat()) || + isChangeOutput(m_sndtrack->getSampleRate())) + if (!m_devImp->doOpenDevice(m_sndtrack->getFormat())) return; + + while ((leftToPlay > 0) && m_devImp->m_isPlaying) { + int fillable = alGetFillable(m_devImp->m_port); + if (!fillable) continue; + + if (fillable < leftToPlay) { + alWriteFrames(m_devImp->m_port, (void *)(m_sndtrack->getRawData() + i), + fillable); + // ricorda getSampleSize restituisce m_sampleSize che comprende gia' + // la moltiplicazione per il numero dei canali + i += fillable * m_sndtrack->getSampleSize(); + leftToPlay -= fillable; + } else { + alWriteFrames(m_devImp->m_port, (void *)(m_sndtrack->getRawData() + i), + leftToPlay); + leftToPlay = 0; + } + } + + if (!m_devImp->m_stopped) { + while (ALgetfilled(m_devImp->m_port) > 0) sginap(1); + { + TThread::ScopedLock sl(m_devImp->m_mutex); + if (!m_devImp->m_looped) m_devImp->m_queuedSoundTracks.pop(); + if (m_devImp->m_queuedSoundTracks.empty()) { + m_devImp->m_isPlaying = false; + m_devImp->m_stopped = true; + m_devImp->m_looped = false; + } else { + m_devImp->m_executor.addTask( + new PlayTask(m_devImp, m_devImp->m_queuedSoundTracks.front())); + } + } + } else { + alDiscardFrames(m_devImp->m_port, alGetFilled(m_devImp->m_port)); + while (!m_devImp->m_queuedSoundTracks.empty()) + m_devImp->m_queuedSoundTracks.pop(); + } } //============================================================================== -TSoundOutputDevice::TSoundOutputDevice() : m_imp(new TSoundOutputDeviceImp) -{ - if (!setDefaultOutput()) - throw TSoundDeviceException( - TSoundDeviceException::UnableSetDevice, "Speaker not supported"); - try { - supportsVolume(); - } catch (TSoundDeviceException &e) { - throw TSoundDeviceException(e.getType(), e.getMessage()); - } - m_imp->insertAllRate(); +TSoundOutputDevice::TSoundOutputDevice() : m_imp(new TSoundOutputDeviceImp) { + if (!setDefaultOutput()) + throw TSoundDeviceException(TSoundDeviceException::UnableSetDevice, + "Speaker not supported"); + try { + supportsVolume(); + } catch (TSoundDeviceException &e) { + throw TSoundDeviceException(e.getType(), e.getMessage()); + } + m_imp->insertAllRate(); } //------------------------------------------------------------------------------ -TSoundOutputDevice::~TSoundOutputDevice() -{ - close(); - delete m_imp; +TSoundOutputDevice::~TSoundOutputDevice() { + close(); + delete m_imp; } //------------------------------------------------------------------------------ -bool TSoundOutputDevice::installed() -{ - if (alQueryValues(AL_SYSTEM, AL_DEFAULT_OUTPUT, 0, 0, 0, 0) <= 0) - return false; - return true; +bool TSoundOutputDevice::installed() { + if (alQueryValues(AL_SYSTEM, AL_DEFAULT_OUTPUT, 0, 0, 0, 0) <= 0) + return false; + return true; } //------------------------------------------------------------------------------ -bool TSoundOutputDevice::open(const TSoundTrackP &st) -{ - if (!m_imp->doOpenDevice(st->getFormat())) - throw TSoundDeviceException( - TSoundDeviceException::UnableOpenDevice, - "Problem to open the output device or set some params"); - return true; +bool TSoundOutputDevice::open(const TSoundTrackP &st) { + if (!m_imp->doOpenDevice(st->getFormat())) + throw TSoundDeviceException( + TSoundDeviceException::UnableOpenDevice, + "Problem to open the output device or set some params"); + return true; } //------------------------------------------------------------------------------ -bool TSoundOutputDevice::close() -{ - stop(); - if (m_imp->m_port) - alClosePort(m_imp->m_port); - m_imp->m_port = NULL; +bool TSoundOutputDevice::close() { + stop(); + if (m_imp->m_port) alClosePort(m_imp->m_port); + m_imp->m_port = NULL; - return true; + return true; } //------------------------------------------------------------------------------ -void TSoundOutputDevice::play(const TSoundTrackP &st, TINT32 s0, TINT32 s1, bool loop, bool scrubbing) -{ - if (!st->getSampleCount()) - return; - - { - TThread::ScopedLock sl(m_imp->m_mutex); - if (m_imp->m_looped) - throw TSoundDeviceException( - TSoundDeviceException::Busy, - "Unable to queue another playback when the sound player is looping"); - - m_imp->m_isPlaying = true; - m_imp->m_stopped = false; - m_imp->m_looped = loop; - } - - TSoundTrackFormat fmt; - try { - fmt = getPreferredFormat(st->getFormat()); - if (fmt != st->getFormat()) { - throw TSoundDeviceException( - TSoundDeviceException::UnsupportedFormat, - "Unsupported Format"); - } - } catch (TSoundDeviceException &e) { - throw TSoundDeviceException( - TSoundDeviceException::UnsupportedFormat, - e.getMessage()); - } - - assert(s1 >= s0); - TSoundTrackP subTrack = st->extract(s0, s1); - - //far partire il thread - if (m_imp->m_queuedSoundTracks.empty()) { - m_imp->m_queuedSoundTracks.push(subTrack); - - m_imp->m_executor.addTask(new PlayTask(m_imp, subTrack)); - } else - m_imp->m_queuedSoundTracks.push(subTrack); +void TSoundOutputDevice::play(const TSoundTrackP &st, TINT32 s0, TINT32 s1, + bool loop, bool scrubbing) { + if (!st->getSampleCount()) return; + + { + TThread::ScopedLock sl(m_imp->m_mutex); + if (m_imp->m_looped) + throw TSoundDeviceException( + TSoundDeviceException::Busy, + "Unable to queue another playback when the sound player is looping"); + + m_imp->m_isPlaying = true; + m_imp->m_stopped = false; + m_imp->m_looped = loop; + } + + TSoundTrackFormat fmt; + try { + fmt = getPreferredFormat(st->getFormat()); + if (fmt != st->getFormat()) { + throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat, + "Unsupported Format"); + } + } catch (TSoundDeviceException &e) { + throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat, + e.getMessage()); + } + + assert(s1 >= s0); + TSoundTrackP subTrack = st->extract(s0, s1); + + // far partire il thread + if (m_imp->m_queuedSoundTracks.empty()) { + m_imp->m_queuedSoundTracks.push(subTrack); + + m_imp->m_executor.addTask(new PlayTask(m_imp, subTrack)); + } else + m_imp->m_queuedSoundTracks.push(subTrack); } //------------------------------------------------------------------------------ -void TSoundOutputDevice::stop() -{ - if (!m_imp->m_isPlaying) - return; +void TSoundOutputDevice::stop() { + if (!m_imp->m_isPlaying) return; - TThread::ScopedLock sl(m_imp->m_mutex); - m_imp->m_isPlaying = false; - m_imp->m_stopped = true; - m_imp->m_looped = false; + TThread::ScopedLock sl(m_imp->m_mutex); + m_imp->m_isPlaying = false; + m_imp->m_stopped = true; + m_imp->m_looped = false; } //------------------------------------------------------------------------------ -double TSoundOutputDevice::getVolume() -{ - ALpv pv[1]; - ALfixed value[2]; - - try { - supportsVolume(); - } catch (TSoundDeviceException &e) { - throw TSoundDeviceException(e.getType(), e.getMessage()); - } - - pv[0].param = AL_GAIN; - pv[0].value.ptr = value; - pv[0].sizeIn = 8; - alGetParams(AL_DEFAULT_OUTPUT, pv, 1); - - double val = (((alFixedToDouble(value[0]) + alFixedToDouble(value[1])) / 2.) + 60.) / 8.05; - return val; +double TSoundOutputDevice::getVolume() { + ALpv pv[1]; + ALfixed value[2]; + + try { + supportsVolume(); + } catch (TSoundDeviceException &e) { + throw TSoundDeviceException(e.getType(), e.getMessage()); + } + + pv[0].param = AL_GAIN; + pv[0].value.ptr = value; + pv[0].sizeIn = 8; + alGetParams(AL_DEFAULT_OUTPUT, pv, 1); + + double val = + (((alFixedToDouble(value[0]) + alFixedToDouble(value[1])) / 2.) + 60.) / + 8.05; + return val; } //------------------------------------------------------------------------------ -bool TSoundOutputDevice::setVolume(double volume) -{ - ALpv pv[1]; - ALfixed value[2]; - - try { - supportsVolume(); - } catch (TSoundDeviceException &e) { - throw TSoundDeviceException(e.getType(), e.getMessage()); - } - - double val = -60. + 8.05 * volume; - value[0] = alDoubleToFixed(val); - value[1] = alDoubleToFixed(val); - - pv[0].param = AL_GAIN; - pv[0].value.ptr = value; - pv[0].sizeIn = 8; - if (alSetParams(AL_DEFAULT_OUTPUT, pv, 1) < 0) - return false; - return true; +bool TSoundOutputDevice::setVolume(double volume) { + ALpv pv[1]; + ALfixed value[2]; + + try { + supportsVolume(); + } catch (TSoundDeviceException &e) { + throw TSoundDeviceException(e.getType(), e.getMessage()); + } + + double val = -60. + 8.05 * volume; + value[0] = alDoubleToFixed(val); + value[1] = alDoubleToFixed(val); + + pv[0].param = AL_GAIN; + pv[0].value.ptr = value; + pv[0].sizeIn = 8; + if (alSetParams(AL_DEFAULT_OUTPUT, pv, 1) < 0) return false; + return true; } //------------------------------------------------------------------------------ -bool TSoundOutputDevice::supportsVolume() -{ - ALparamInfo pinfo; - int ret; - ret = alGetParamInfo(AL_DEFAULT_OUTPUT, AL_GAIN, &pinfo); - double min = alFixedToDouble(pinfo.min.ll); - double max = alFixedToDouble(pinfo.max.ll); - if ((ret != -1) && (min != max) && (max != 0.0)) - return true; - else if ((ret == AL_BAD_PARAM) || ((min == max) && (max == 0.0))) - throw TSoundDeviceException( - TSoundDeviceException::UnableVolume, - "It is impossible to chamge setting of volume"); - else - throw TSoundDeviceException( - TSoundDeviceException::NoMixer, "Output device is not accessible"); +bool TSoundOutputDevice::supportsVolume() { + ALparamInfo pinfo; + int ret; + ret = alGetParamInfo(AL_DEFAULT_OUTPUT, AL_GAIN, &pinfo); + double min = alFixedToDouble(pinfo.min.ll); + double max = alFixedToDouble(pinfo.max.ll); + if ((ret != -1) && (min != max) && (max != 0.0)) + return true; + else if ((ret == AL_BAD_PARAM) || ((min == max) && (max == 0.0))) + throw TSoundDeviceException(TSoundDeviceException::UnableVolume, + "It is impossible to chamge setting of volume"); + else + throw TSoundDeviceException(TSoundDeviceException::NoMixer, + "Output device is not accessible"); } //------------------------------------------------------------------------------ -bool TSoundOutputDevice::isPlaying() const -{ - return m_imp->m_isPlaying; -} +bool TSoundOutputDevice::isPlaying() const { return m_imp->m_isPlaying; } //------------------------------------------------------------------------------ -bool TSoundOutputDevice::isLooping() -{ - TThread::ScopedLock sl(m_imp->m_mutex); - return m_imp->m_looped; +bool TSoundOutputDevice::isLooping() { + TThread::ScopedLock sl(m_imp->m_mutex); + return m_imp->m_looped; } //------------------------------------------------------------------------------ -void TSoundOutputDevice::setLooping(bool loop) -{ - TThread::ScopedLock sl(m_imp->m_mutex); - m_imp->m_looped = loop; +void TSoundOutputDevice::setLooping(bool loop) { + TThread::ScopedLock sl(m_imp->m_mutex); + m_imp->m_looped = loop; } //------------------------------------------------------------------------------ -TSoundTrackFormat TSoundOutputDevice::getPreferredFormat( - ULONG sampleRate, int channelCount, int bitPerSample) -{ - TSoundTrackFormat fmt; - int ret; - - if (!m_imp->verifyRate()) - throw TSoundDeviceException( - TSoundDeviceException::UnsupportedFormat, - "There isn't any support rate"); - - if (m_imp->m_supportedRate.find((int)sampleRate) == - m_imp->m_supportedRate.end()) { - std::set::iterator it = - m_imp->m_supportedRate.lower_bound((int)sampleRate); - if (it == m_imp->m_supportedRate.end()) { - it = std::max_element(m_imp->m_supportedRate.begin(), - m_imp->m_supportedRate.end()); - if (it != m_imp->m_supportedRate.end()) - sampleRate = *(m_imp->m_supportedRate.rbegin()); - else - throw TSoundDeviceException( - TSoundDeviceException::UnsupportedFormat, - "There isn't a supported rate"); - } else - sampleRate = *it; - } - - int value; - ALvalue vals[32]; - if ((ret = alQueryValues(AL_DEFAULT_OUTPUT, AL_CHANNELS, vals, 32, 0, 0)) > 0) - for (int i = 0; i < ret; ++i) - value = vals[i].i; - else if (oserror() == AL_BAD_PARAM) - throw TSoundDeviceException( - TSoundDeviceException::NoMixer, - "It is impossible ask for the max numbers of channels supported"); - else - throw TSoundDeviceException( - TSoundDeviceException::NoMixer, - "It is impossibile information about ouput device"); - - if (value > 2) - value = 2; - if (channelCount > value) - channelCount = value; - else if (channelCount <= 0) - channelCount = 1; - - if (bitPerSample <= 8) - bitPerSample = 8; - else if (bitPerSample <= 16) - bitPerSample = 16; - else - bitPerSample = 24; - - fmt.m_bitPerSample = bitPerSample; - fmt.m_channelCount = channelCount; - fmt.m_sampleRate = sampleRate; - fmt.m_signedSample = true; - - return fmt; +TSoundTrackFormat TSoundOutputDevice::getPreferredFormat(ULONG sampleRate, + int channelCount, + int bitPerSample) { + TSoundTrackFormat fmt; + int ret; + + if (!m_imp->verifyRate()) + throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat, + "There isn't any support rate"); + + if (m_imp->m_supportedRate.find((int)sampleRate) == + m_imp->m_supportedRate.end()) { + std::set::iterator it = + m_imp->m_supportedRate.lower_bound((int)sampleRate); + if (it == m_imp->m_supportedRate.end()) { + it = std::max_element(m_imp->m_supportedRate.begin(), + m_imp->m_supportedRate.end()); + if (it != m_imp->m_supportedRate.end()) + sampleRate = *(m_imp->m_supportedRate.rbegin()); + else + throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat, + "There isn't a supported rate"); + } else + sampleRate = *it; + } + + int value; + ALvalue vals[32]; + if ((ret = alQueryValues(AL_DEFAULT_OUTPUT, AL_CHANNELS, vals, 32, 0, 0)) > 0) + for (int i = 0; i < ret; ++i) value = vals[i].i; + else if (oserror() == AL_BAD_PARAM) + throw TSoundDeviceException( + TSoundDeviceException::NoMixer, + "It is impossible ask for the max numbers of channels supported"); + else + throw TSoundDeviceException( + TSoundDeviceException::NoMixer, + "It is impossibile information about ouput device"); + + if (value > 2) value = 2; + if (channelCount > value) + channelCount = value; + else if (channelCount <= 0) + channelCount = 1; + + if (bitPerSample <= 8) + bitPerSample = 8; + else if (bitPerSample <= 16) + bitPerSample = 16; + else + bitPerSample = 24; + + fmt.m_bitPerSample = bitPerSample; + fmt.m_channelCount = channelCount; + fmt.m_sampleRate = sampleRate; + fmt.m_signedSample = true; + + return fmt; } //------------------------------------------------------------------------------ -TSoundTrackFormat TSoundOutputDevice::getPreferredFormat(const TSoundTrackFormat &format) -{ - try { - return getPreferredFormat( - format.m_sampleRate, format.m_channelCount, format.m_bitPerSample); - } catch (TSoundDeviceException &e) { - throw TSoundDeviceException(e.getType(), e.getMessage()); - } +TSoundTrackFormat TSoundOutputDevice::getPreferredFormat( + const TSoundTrackFormat &format) { + try { + return getPreferredFormat(format.m_sampleRate, format.m_channelCount, + format.m_bitPerSample); + } catch (TSoundDeviceException &e) { + throw TSoundDeviceException(e.getType(), e.getMessage()); + } } //============================================================================== @@ -507,727 +477,695 @@ TSoundTrackFormat TSoundOutputDevice::getPreferredFormat(const TSoundTrackFormat //============================================================================== //============================================================================== -class TSoundInputDeviceImp -{ +class TSoundInputDeviceImp { public: - ALport m_port; - bool m_stopped; - bool m_isRecording; - bool m_oneShotRecording; - - TINT32 m_recordedSampleCount; - - vector m_recordedBlocks; - vector m_samplePerBlocks; - TSoundTrackFormat m_currentFormat; - TSoundTrackP m_st; - std::set m_supportedRate; - - TThread::Executor m_executor; - - TSoundInputDeviceImp() - : m_stopped(false), m_isRecording(false), m_port(NULL), m_recordedBlocks(), m_samplePerBlocks(), m_recordedSampleCount(0), m_oneShotRecording(false), m_st(0), m_supportedRate(){}; - - ~TSoundInputDeviceImp(){}; - - bool doOpenDevice(const TSoundTrackFormat &format, - TSoundInputDevice::Source devType); - void insertAllRate(); - bool verifyRate(); + ALport m_port; + bool m_stopped; + bool m_isRecording; + bool m_oneShotRecording; + + TINT32 m_recordedSampleCount; + + vector m_recordedBlocks; + vector m_samplePerBlocks; + TSoundTrackFormat m_currentFormat; + TSoundTrackP m_st; + std::set m_supportedRate; + + TThread::Executor m_executor; + + TSoundInputDeviceImp() + : m_stopped(false) + , m_isRecording(false) + , m_port(NULL) + , m_recordedBlocks() + , m_samplePerBlocks() + , m_recordedSampleCount(0) + , m_oneShotRecording(false) + , m_st(0) + , m_supportedRate(){}; + + ~TSoundInputDeviceImp(){}; + + bool doOpenDevice(const TSoundTrackFormat &format, + TSoundInputDevice::Source devType); + void insertAllRate(); + bool verifyRate(); }; bool TSoundInputDeviceImp::doOpenDevice(const TSoundTrackFormat &format, - TSoundInputDevice::Source devType) -{ - ALconfig config; - ALpv pvbuf[2]; + TSoundInputDevice::Source devType) { + ALconfig config; + ALpv pvbuf[2]; - m_currentFormat = format; + m_currentFormat = format; - // AL_MONITOR_CTL fa parte dei vecchi andrebbero trovati quelli nuovi - pvbuf[0].param = AL_PORT_COUNT; - pvbuf[1].param = AL_MONITOR_CTL; - if (alGetParams(AL_DEFAULT_INPUT, pvbuf, 2) < 0) - if (oserror() == AL_BAD_DEVICE_ACCESS) - return false; //throw TException("Could not access audio hardware."); + // AL_MONITOR_CTL fa parte dei vecchi andrebbero trovati quelli nuovi + pvbuf[0].param = AL_PORT_COUNT; + pvbuf[1].param = AL_MONITOR_CTL; + if (alGetParams(AL_DEFAULT_INPUT, pvbuf, 2) < 0) + if (oserror() == AL_BAD_DEVICE_ACCESS) + return false; // throw TException("Could not access audio hardware."); - config = alNewConfig(); + config = alNewConfig(); - if (!setDefaultInput(devType)) - return false; //throw TException("Could not set the input device specified"); + if (!setDefaultInput(devType)) + return false; // throw TException("Could not set the input device + // specified"); - pvbuf[0].param = AL_RATE; - pvbuf[0].value.ll = alDoubleToFixed(format.m_sampleRate); + pvbuf[0].param = AL_RATE; + pvbuf[0].value.ll = alDoubleToFixed(format.m_sampleRate); - ALfixed buf[2] = {alDoubleToFixed(0), alDoubleToFixed(0)}; - pvbuf[1].param = AL_GAIN; - pvbuf[1].value.ptr = buf; - pvbuf[1].sizeIn = 8; + ALfixed buf[2] = {alDoubleToFixed(0), alDoubleToFixed(0)}; + pvbuf[1].param = AL_GAIN; + pvbuf[1].value.ptr = buf; + pvbuf[1].sizeIn = 8; - if (alSetParams(AL_DEFAULT_INPUT, pvbuf, 2) < 0) - return false; //throw TException("Problem to set params "); + if (alSetParams(AL_DEFAULT_INPUT, pvbuf, 2) < 0) + return false; // throw TException("Problem to set params "); - if (alSetChannels(config, format.m_channelCount) == -1) - return false; //throw TException("Error to setting audio hardware."); + if (alSetChannels(config, format.m_channelCount) == -1) + return false; // throw TException("Error to setting audio hardware."); - int bytePerSample = format.m_bitPerSample >> 3; - switch (bytePerSample) { - case 3: - bytePerSample++; - break; - default: - break; - } - if (alSetWidth(config, bytePerSample) == -1) - return false; //throw TException("Error to setting audio hardware."); + int bytePerSample = format.m_bitPerSample >> 3; + switch (bytePerSample) { + case 3: + bytePerSample++; + break; + default: + break; + } + if (alSetWidth(config, bytePerSample) == -1) + return false; // throw TException("Error to setting audio hardware."); - if (alSetSampFmt(config, AL_SAMPFMT_TWOSCOMP) == -1) - return false; //throw TException("Error to setting audio hardware."); + if (alSetSampFmt(config, AL_SAMPFMT_TWOSCOMP) == -1) + return false; // throw TException("Error to setting audio hardware."); - if (alSetQueueSize(config, (TINT32)format.m_sampleRate) == -1) - return false; //throw TException("Error to setting audio hardware."); + if (alSetQueueSize(config, (TINT32)format.m_sampleRate) == -1) + return false; // throw TException("Error to setting audio hardware."); - alSetDevice(config, AL_DEFAULT_INPUT); + alSetDevice(config, AL_DEFAULT_INPUT); - m_port = alOpenPort("AudioInput", "r", config); - if (!m_port) - return false; //throw TException("Could not open audio port."); + m_port = alOpenPort("AudioInput", "r", config); + if (!m_port) return false; // throw TException("Could not open audio port."); - alFreeConfig(config); - return true; + alFreeConfig(config); + return true; } //----------------------------------------------------------------------------- -void TSoundInputDeviceImp::insertAllRate() -{ - m_supportedRate.insert(8000); - m_supportedRate.insert(11025); - m_supportedRate.insert(16000); - m_supportedRate.insert(22050); - m_supportedRate.insert(32000); - m_supportedRate.insert(44100); - m_supportedRate.insert(48000); +void TSoundInputDeviceImp::insertAllRate() { + m_supportedRate.insert(8000); + m_supportedRate.insert(11025); + m_supportedRate.insert(16000); + m_supportedRate.insert(22050); + m_supportedRate.insert(32000); + m_supportedRate.insert(44100); + m_supportedRate.insert(48000); } //----------------------------------------------------------------------------- -bool TSoundInputDeviceImp::verifyRate() -{ - //Sample Rate - ALparamInfo pinfo; - int ret = alGetParamInfo(AL_DEFAULT_INPUT, AL_RATE, &pinfo); - if (ret != -1 && pinfo.elementType == AL_FIXED_ELEM) { - int min = (int)alFixedToDouble(pinfo.min.ll); - int max = (int)alFixedToDouble(pinfo.max.ll); - - std::set::iterator it; - for (it = m_supportedRate.begin(); it != m_supportedRate.end(); ++it) - if (*it < min || *it > max) - m_supportedRate.erase(*it); - if (m_supportedRate.end() == m_supportedRate.begin()) - return false; - } else if (ret == AL_BAD_PARAM) - return false; - else - return false; - return true; +bool TSoundInputDeviceImp::verifyRate() { + // Sample Rate + ALparamInfo pinfo; + int ret = alGetParamInfo(AL_DEFAULT_INPUT, AL_RATE, &pinfo); + if (ret != -1 && pinfo.elementType == AL_FIXED_ELEM) { + int min = (int)alFixedToDouble(pinfo.min.ll); + int max = (int)alFixedToDouble(pinfo.max.ll); + + std::set::iterator it; + for (it = m_supportedRate.begin(); it != m_supportedRate.end(); ++it) + if (*it < min || *it > max) m_supportedRate.erase(*it); + if (m_supportedRate.end() == m_supportedRate.begin()) return false; + } else if (ret == AL_BAD_PARAM) + return false; + else + return false; + return true; } //============================================================================== -class RecordTask : public TThread::Runnable -{ +class RecordTask : public TThread::Runnable { public: - TSoundInputDeviceImp *m_devImp; - int m_ByteToSample; + TSoundInputDeviceImp *m_devImp; + int m_ByteToSample; - RecordTask(TSoundInputDeviceImp *devImp, int numByte) - : TThread::Runnable(), m_devImp(devImp), m_ByteToSample(numByte){}; + RecordTask(TSoundInputDeviceImp *devImp, int numByte) + : TThread::Runnable(), m_devImp(devImp), m_ByteToSample(numByte){}; - ~RecordTask(){}; + ~RecordTask(){}; - void run(); + void run(); }; -void RecordTask::run() -{ - TINT32 byteRecordedSample = 0; - int filled = alGetFilled(m_devImp->m_port); - - if (m_devImp->m_oneShotRecording) { - char *rawData = m_devImp->m_recordedBlocks.front(); - int sampleSize; - - if ((m_devImp->m_currentFormat.m_bitPerSample >> 3) == 3) - sampleSize = 4; - else - sampleSize = (m_devImp->m_currentFormat.m_bitPerSample >> 3); - - sampleSize *= m_devImp->m_currentFormat.m_channelCount; - while ((byteRecordedSample <= (m_ByteToSample - filled * sampleSize)) && m_devImp->m_isRecording) { - alReadFrames(m_devImp->m_port, (void *)(rawData + byteRecordedSample), filled); - byteRecordedSample += filled * sampleSize; - filled = alGetFilled(m_devImp->m_port); - } - - if (m_devImp->m_isRecording) { - alReadFrames(m_devImp->m_port, (void *)(rawData + byteRecordedSample), - (m_ByteToSample - byteRecordedSample) / sampleSize); - while (alGetFillable(m_devImp->m_port) > 0) - sginap(1); - } - } else { - while (m_devImp->m_isRecording) { - filled = alGetFilled(m_devImp->m_port); - if (filled > 0) { - char *dataBuffer = new char[filled * m_ByteToSample]; - m_devImp->m_recordedBlocks.push_back(dataBuffer); - m_devImp->m_samplePerBlocks.push_back(filled * m_ByteToSample); - - alReadFrames(m_devImp->m_port, (void *)dataBuffer, filled); - m_devImp->m_recordedSampleCount += filled; - } - } - while (alGetFillable(m_devImp->m_port) > 0) - sginap(1); - } - alClosePort(m_devImp->m_port); - m_devImp->m_port = 0; - m_devImp->m_stopped = true; +void RecordTask::run() { + TINT32 byteRecordedSample = 0; + int filled = alGetFilled(m_devImp->m_port); + + if (m_devImp->m_oneShotRecording) { + char *rawData = m_devImp->m_recordedBlocks.front(); + int sampleSize; + + if ((m_devImp->m_currentFormat.m_bitPerSample >> 3) == 3) + sampleSize = 4; + else + sampleSize = (m_devImp->m_currentFormat.m_bitPerSample >> 3); + + sampleSize *= m_devImp->m_currentFormat.m_channelCount; + while ((byteRecordedSample <= (m_ByteToSample - filled * sampleSize)) && + m_devImp->m_isRecording) { + alReadFrames(m_devImp->m_port, (void *)(rawData + byteRecordedSample), + filled); + byteRecordedSample += filled * sampleSize; + filled = alGetFilled(m_devImp->m_port); + } + + if (m_devImp->m_isRecording) { + alReadFrames(m_devImp->m_port, (void *)(rawData + byteRecordedSample), + (m_ByteToSample - byteRecordedSample) / sampleSize); + while (alGetFillable(m_devImp->m_port) > 0) sginap(1); + } + } else { + while (m_devImp->m_isRecording) { + filled = alGetFilled(m_devImp->m_port); + if (filled > 0) { + char *dataBuffer = new char[filled * m_ByteToSample]; + m_devImp->m_recordedBlocks.push_back(dataBuffer); + m_devImp->m_samplePerBlocks.push_back(filled * m_ByteToSample); + + alReadFrames(m_devImp->m_port, (void *)dataBuffer, filled); + m_devImp->m_recordedSampleCount += filled; + } + } + while (alGetFillable(m_devImp->m_port) > 0) sginap(1); + } + alClosePort(m_devImp->m_port); + m_devImp->m_port = 0; + m_devImp->m_stopped = true; } //============================================================================== -TSoundInputDevice::TSoundInputDevice() : m_imp(new TSoundInputDeviceImp) -{ -} +TSoundInputDevice::TSoundInputDevice() : m_imp(new TSoundInputDeviceImp) {} //------------------------------------------------------------------------------ -TSoundInputDevice::~TSoundInputDevice() -{ - if (m_imp->m_port) - alClosePort(m_imp->m_port); - delete m_imp; +TSoundInputDevice::~TSoundInputDevice() { + if (m_imp->m_port) alClosePort(m_imp->m_port); + delete m_imp; } //------------------------------------------------------------------------------ -bool TSoundInputDevice::installed() -{ - if (alQueryValues(AL_SYSTEM, AL_DEFAULT_INPUT, 0, 0, 0, 0) <= 0) - return false; - return true; +bool TSoundInputDevice::installed() { + if (alQueryValues(AL_SYSTEM, AL_DEFAULT_INPUT, 0, 0, 0, 0) <= 0) return false; + return true; } //------------------------------------------------------------------------------ -void TSoundInputDevice::record(const TSoundTrackFormat &format, TSoundInputDevice::Source type) -{ - if (m_imp->m_isRecording == true) - throw TSoundDeviceException( - TSoundDeviceException::Busy, - "Just another recoding is in progress"); - - m_imp->m_recordedBlocks.clear(); - m_imp->m_samplePerBlocks.clear(); - - //registra creando una nuova traccia - m_imp->m_oneShotRecording = false; - - if (!setDefaultInput(type)) - throw TSoundDeviceException( - TSoundDeviceException::UnableSetDevice, - "Error to set the input device"); - - m_imp->insertAllRate(); - TSoundTrackFormat fmt; - - try { - fmt = getPreferredFormat(format); - if (fmt != format) { - throw TSoundDeviceException( - TSoundDeviceException::UnsupportedFormat, - "Unsupported Format"); - } - } catch (TSoundDeviceException &e) { - throw TSoundDeviceException( - TSoundDeviceException::UnsupportedFormat, - e.getMessage()); - } - - if (!m_imp->m_port) - m_imp->doOpenDevice(format, type); - - m_imp->m_currentFormat = format; - m_imp->m_isRecording = true; - m_imp->m_stopped = false; - m_imp->m_recordedSampleCount = 0; - - int bytePerSample = format.m_bitPerSample >> 3; - switch (bytePerSample) { - case 3: - bytePerSample++; - break; - default: - break; - } - bytePerSample *= format.m_channelCount; - - //far partire il thread - /*TRecordThread *recordThread = new TRecordThread(m_imp, bytePerSample); - if (!recordThread) - { - m_imp->m_isRecording = false; - m_imp->m_stopped = true; - throw TSoundDeviceException( - TSoundDeviceException::UnablePrepare, - "Unable to create the recording thread"); - } - recordThread->start();*/ - m_imp->m_executor.addTask(new RecordTask(m_imp, bytePerSample)); +void TSoundInputDevice::record(const TSoundTrackFormat &format, + TSoundInputDevice::Source type) { + if (m_imp->m_isRecording == true) + throw TSoundDeviceException(TSoundDeviceException::Busy, + "Just another recoding is in progress"); + + m_imp->m_recordedBlocks.clear(); + m_imp->m_samplePerBlocks.clear(); + + // registra creando una nuova traccia + m_imp->m_oneShotRecording = false; + + if (!setDefaultInput(type)) + throw TSoundDeviceException(TSoundDeviceException::UnableSetDevice, + "Error to set the input device"); + + m_imp->insertAllRate(); + TSoundTrackFormat fmt; + + try { + fmt = getPreferredFormat(format); + if (fmt != format) { + throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat, + "Unsupported Format"); + } + } catch (TSoundDeviceException &e) { + throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat, + e.getMessage()); + } + + if (!m_imp->m_port) m_imp->doOpenDevice(format, type); + + m_imp->m_currentFormat = format; + m_imp->m_isRecording = true; + m_imp->m_stopped = false; + m_imp->m_recordedSampleCount = 0; + + int bytePerSample = format.m_bitPerSample >> 3; + switch (bytePerSample) { + case 3: + bytePerSample++; + break; + default: + break; + } + bytePerSample *= format.m_channelCount; + + // far partire il thread + /*TRecordThread *recordThread = new TRecordThread(m_imp, bytePerSample); + if (!recordThread) + { + m_imp->m_isRecording = false; + m_imp->m_stopped = true; +throw TSoundDeviceException( +TSoundDeviceException::UnablePrepare, +"Unable to create the recording thread"); + } +recordThread->start();*/ + m_imp->m_executor.addTask(new RecordTask(m_imp, bytePerSample)); } //------------------------------------------------------------------------------ -void TSoundInputDevice::record(const TSoundTrackP &st, TSoundInputDevice::Source type) -{ - if (m_imp->m_isRecording == true) - throw TSoundDeviceException( - TSoundDeviceException::Busy, - "Just another recoding is in progress"); - - m_imp->m_recordedBlocks.clear(); - m_imp->m_samplePerBlocks.clear(); - - if (!setDefaultInput(type)) - throw TSoundDeviceException( - TSoundDeviceException::UnableSetDevice, - "Error to set the input device"); - - m_imp->insertAllRate(); - TSoundTrackFormat fmt; - - try { - fmt = getPreferredFormat(st->getFormat()); - if (fmt != st->getFormat()) { - throw TSoundDeviceException( - TSoundDeviceException::UnsupportedFormat, - "Unsupported Format"); - } - } catch (TSoundDeviceException &e) { - throw TSoundDeviceException( - TSoundDeviceException::UnsupportedFormat, - e.getMessage()); - } - - if (!m_imp->m_port) - if (!m_imp->doOpenDevice(st->getFormat(), type)) - throw TSoundDeviceException( - TSoundDeviceException::UnableOpenDevice, - "Unable to open input device"); - - //Sovrascive un'intera o parte di traccia gia' esistente - m_imp->m_oneShotRecording = true; - m_imp->m_currentFormat = st->getFormat(); - m_imp->m_isRecording = true; - m_imp->m_stopped = false; - m_imp->m_recordedSampleCount = 0; - m_imp->m_st = st; - - m_imp->m_recordedBlocks.push_back((char *)st->getRawData()); - - int totByteToSample = st->getSampleCount() * st->getSampleSize(); - - //far partire il thread - /*TRecordThread *recordThread = new TRecordThread(m_imp, totByteToSample); - if (!recordThread) - { - m_imp->m_isRecording = false; - m_imp->m_stopped = true; - throw TSoundDeviceException( - TSoundDeviceException::UnablePrepare, - "Unable to create the recording thread"); - } - recordThread->start();*/ - m_imp->m_executor.addTask(new RecordTask(m_imp, totByteToSample)); +void TSoundInputDevice::record(const TSoundTrackP &st, + TSoundInputDevice::Source type) { + if (m_imp->m_isRecording == true) + throw TSoundDeviceException(TSoundDeviceException::Busy, + "Just another recoding is in progress"); + + m_imp->m_recordedBlocks.clear(); + m_imp->m_samplePerBlocks.clear(); + + if (!setDefaultInput(type)) + throw TSoundDeviceException(TSoundDeviceException::UnableSetDevice, + "Error to set the input device"); + + m_imp->insertAllRate(); + TSoundTrackFormat fmt; + + try { + fmt = getPreferredFormat(st->getFormat()); + if (fmt != st->getFormat()) { + throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat, + "Unsupported Format"); + } + } catch (TSoundDeviceException &e) { + throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat, + e.getMessage()); + } + + if (!m_imp->m_port) + if (!m_imp->doOpenDevice(st->getFormat(), type)) + throw TSoundDeviceException(TSoundDeviceException::UnableOpenDevice, + "Unable to open input device"); + + // Sovrascive un'intera o parte di traccia gia' esistente + m_imp->m_oneShotRecording = true; + m_imp->m_currentFormat = st->getFormat(); + m_imp->m_isRecording = true; + m_imp->m_stopped = false; + m_imp->m_recordedSampleCount = 0; + m_imp->m_st = st; + + m_imp->m_recordedBlocks.push_back((char *)st->getRawData()); + + int totByteToSample = st->getSampleCount() * st->getSampleSize(); + + // far partire il thread + /*TRecordThread *recordThread = new TRecordThread(m_imp, totByteToSample); + if (!recordThread) + { + m_imp->m_isRecording = false; + m_imp->m_stopped = true; +throw TSoundDeviceException( +TSoundDeviceException::UnablePrepare, +"Unable to create the recording thread"); + } +recordThread->start();*/ + m_imp->m_executor.addTask(new RecordTask(m_imp, totByteToSample)); } //------------------------------------------------------------------------------ -TSoundTrackP TSoundInputDevice::stop() -{ - TSoundTrackP st; +TSoundTrackP TSoundInputDevice::stop() { + TSoundTrackP st; - if (!m_imp->m_isRecording) - throw TSoundDeviceException( - TSoundDeviceException::UnablePrepare, - "No recording process is in execution"); + if (!m_imp->m_isRecording) + throw TSoundDeviceException(TSoundDeviceException::UnablePrepare, + "No recording process is in execution"); - m_imp->m_isRecording = false; + m_imp->m_isRecording = false; - alDiscardFrames(m_imp->m_port, alGetFilled(m_imp->m_port)); + alDiscardFrames(m_imp->m_port, alGetFilled(m_imp->m_port)); - while (!m_imp->m_stopped) - sginap(1); + while (!m_imp->m_stopped) sginap(1); - if (m_imp->m_oneShotRecording) - st = m_imp->m_st; - else { - st = TSoundTrack::create(m_imp->m_currentFormat, m_imp->m_recordedSampleCount); - TINT32 bytesCopied = 0; + if (m_imp->m_oneShotRecording) + st = m_imp->m_st; + else { + st = TSoundTrack::create(m_imp->m_currentFormat, + m_imp->m_recordedSampleCount); + TINT32 bytesCopied = 0; - for (int i = 0; i < (int)m_imp->m_recordedBlocks.size(); ++i) { - memcpy( - (void *)(st->getRawData() + bytesCopied), - m_imp->m_recordedBlocks[i], - m_imp->m_samplePerBlocks[i]); + for (int i = 0; i < (int)m_imp->m_recordedBlocks.size(); ++i) { + memcpy((void *)(st->getRawData() + bytesCopied), + m_imp->m_recordedBlocks[i], m_imp->m_samplePerBlocks[i]); - delete[] m_imp->m_recordedBlocks[i]; + delete[] m_imp->m_recordedBlocks[i]; - bytesCopied += m_imp->m_samplePerBlocks[i]; - } - m_imp->m_samplePerBlocks.clear(); - } - return st; + bytesCopied += m_imp->m_samplePerBlocks[i]; + } + m_imp->m_samplePerBlocks.clear(); + } + return st; } //------------------------------------------------------------------------------ -double TSoundInputDevice::getVolume() -{ - ALpv pv[1]; - ALfixed value[2]; - - try { - supportsVolume(); - } catch (TSoundDeviceException &e) { - throw TSoundDeviceException(e.getType(), e.getMessage()); - } - - pv[0].param = AL_GAIN; - pv[0].value.ptr = value; - pv[0].sizeIn = 8; - alGetParams(AL_DEFAULT_INPUT, pv, 1); - - double val = (((alFixedToDouble(value[0]) + alFixedToDouble(value[1])) / 2.) + 60.) / 8.05; - return val; +double TSoundInputDevice::getVolume() { + ALpv pv[1]; + ALfixed value[2]; + + try { + supportsVolume(); + } catch (TSoundDeviceException &e) { + throw TSoundDeviceException(e.getType(), e.getMessage()); + } + + pv[0].param = AL_GAIN; + pv[0].value.ptr = value; + pv[0].sizeIn = 8; + alGetParams(AL_DEFAULT_INPUT, pv, 1); + + double val = + (((alFixedToDouble(value[0]) + alFixedToDouble(value[1])) / 2.) + 60.) / + 8.05; + return val; } //------------------------------------------------------------------------------ -bool TSoundInputDevice::setVolume(double volume) -{ - ALpv pv[1]; - ALfixed value[2]; +bool TSoundInputDevice::setVolume(double volume) { + ALpv pv[1]; + ALfixed value[2]; - try { - supportsVolume(); - } catch (TSoundDeviceException &e) { - throw TSoundDeviceException(e.getType(), e.getMessage()); - } + try { + supportsVolume(); + } catch (TSoundDeviceException &e) { + throw TSoundDeviceException(e.getType(), e.getMessage()); + } - double val = -60. + 8.05 * volume; - value[0] = alDoubleToFixed(val); - value[1] = alDoubleToFixed(val); + double val = -60. + 8.05 * volume; + value[0] = alDoubleToFixed(val); + value[1] = alDoubleToFixed(val); - pv[0].param = AL_GAIN; - pv[0].value.ptr = value; - pv[0].sizeIn = 8; - alSetParams(AL_DEFAULT_INPUT, pv, 1); + pv[0].param = AL_GAIN; + pv[0].value.ptr = value; + pv[0].sizeIn = 8; + alSetParams(AL_DEFAULT_INPUT, pv, 1); - return true; + return true; } //------------------------------------------------------------------------------ -bool TSoundInputDevice::supportsVolume() -{ - ALparamInfo pinfo; - int ret; - ret = alGetParamInfo(AL_DEFAULT_INPUT, AL_GAIN, &pinfo); - double min = alFixedToDouble(pinfo.min.ll); - double max = alFixedToDouble(pinfo.max.ll); - if ((ret != -1) && (min != max) && (max != 0.0)) - return true; - else if ((ret == AL_BAD_PARAM) || ((min == max) && (max == 0.0))) - throw TSoundDeviceException( - TSoundDeviceException::UnableVolume, - "It is impossible to chamge setting of volume"); - else - throw TSoundDeviceException( - TSoundDeviceException::NoMixer, "Output device is not accessible"); +bool TSoundInputDevice::supportsVolume() { + ALparamInfo pinfo; + int ret; + ret = alGetParamInfo(AL_DEFAULT_INPUT, AL_GAIN, &pinfo); + double min = alFixedToDouble(pinfo.min.ll); + double max = alFixedToDouble(pinfo.max.ll); + if ((ret != -1) && (min != max) && (max != 0.0)) + return true; + else if ((ret == AL_BAD_PARAM) || ((min == max) && (max == 0.0))) + throw TSoundDeviceException(TSoundDeviceException::UnableVolume, + "It is impossible to chamge setting of volume"); + else + throw TSoundDeviceException(TSoundDeviceException::NoMixer, + "Output device is not accessible"); } //------------------------------------------------------------------------------ -TSoundTrackFormat TSoundInputDevice::getPreferredFormat( - ULONG sampleRate, int channelCount, int bitPerSample) -{ - TSoundTrackFormat fmt; - int ret; - - if (!m_imp->verifyRate()) - throw TSoundDeviceException( - TSoundDeviceException::UnsupportedFormat, - "There isn't any support rate"); - - if (m_imp->m_supportedRate.find((int)sampleRate) == - m_imp->m_supportedRate.end()) { - std::set::iterator it = - m_imp->m_supportedRate.lower_bound((int)sampleRate); - if (it == m_imp->m_supportedRate.end()) { - it = std::max_element(m_imp->m_supportedRate.begin(), - m_imp->m_supportedRate.end()); - if (it != m_imp->m_supportedRate.end()) - sampleRate = *(m_imp->m_supportedRate.rbegin()); - else - throw TSoundDeviceException( - TSoundDeviceException::UnsupportedFormat, - "There isn't a supported rate"); - } else - sampleRate = *it; - } - - int value; - ALvalue vals[32]; - if ((ret = alQueryValues(AL_DEFAULT_INPUT, AL_CHANNELS, vals, 32, 0, 0)) > 0) - for (int i = 0; i < ret; ++i) - value = vals[i].i; - else if (oserror() == AL_BAD_PARAM) - throw TSoundDeviceException( - TSoundDeviceException::NoMixer, - "It is impossible ask for the max nembers of channels supported"); - else - throw TSoundDeviceException( - TSoundDeviceException::NoMixer, - "It is impossibile information about ouput device"); - - if (value > 2) - value = 2; - if (channelCount > value) - channelCount = value; - else if (channelCount <= 0) - channelCount = 1; - - if (bitPerSample <= 8) - bitPerSample = 8; - else if (bitPerSample <= 16) - bitPerSample = 16; - else - bitPerSample = 24; - - fmt.m_bitPerSample = bitPerSample; - fmt.m_channelCount = channelCount; - fmt.m_sampleRate = sampleRate; - fmt.m_signedSample = true; - - return fmt; +TSoundTrackFormat TSoundInputDevice::getPreferredFormat(ULONG sampleRate, + int channelCount, + int bitPerSample) { + TSoundTrackFormat fmt; + int ret; + + if (!m_imp->verifyRate()) + throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat, + "There isn't any support rate"); + + if (m_imp->m_supportedRate.find((int)sampleRate) == + m_imp->m_supportedRate.end()) { + std::set::iterator it = + m_imp->m_supportedRate.lower_bound((int)sampleRate); + if (it == m_imp->m_supportedRate.end()) { + it = std::max_element(m_imp->m_supportedRate.begin(), + m_imp->m_supportedRate.end()); + if (it != m_imp->m_supportedRate.end()) + sampleRate = *(m_imp->m_supportedRate.rbegin()); + else + throw TSoundDeviceException(TSoundDeviceException::UnsupportedFormat, + "There isn't a supported rate"); + } else + sampleRate = *it; + } + + int value; + ALvalue vals[32]; + if ((ret = alQueryValues(AL_DEFAULT_INPUT, AL_CHANNELS, vals, 32, 0, 0)) > 0) + for (int i = 0; i < ret; ++i) value = vals[i].i; + else if (oserror() == AL_BAD_PARAM) + throw TSoundDeviceException( + TSoundDeviceException::NoMixer, + "It is impossible ask for the max nembers of channels supported"); + else + throw TSoundDeviceException( + TSoundDeviceException::NoMixer, + "It is impossibile information about ouput device"); + + if (value > 2) value = 2; + if (channelCount > value) + channelCount = value; + else if (channelCount <= 0) + channelCount = 1; + + if (bitPerSample <= 8) + bitPerSample = 8; + else if (bitPerSample <= 16) + bitPerSample = 16; + else + bitPerSample = 24; + + fmt.m_bitPerSample = bitPerSample; + fmt.m_channelCount = channelCount; + fmt.m_sampleRate = sampleRate; + fmt.m_signedSample = true; + + return fmt; } //------------------------------------------------------------------------------ -TSoundTrackFormat TSoundInputDevice::getPreferredFormat(const TSoundTrackFormat &format) -{ - try { - return getPreferredFormat( - format.m_sampleRate, format.m_channelCount, format.m_bitPerSample); - } catch (TSoundDeviceException &e) { - throw TSoundDeviceException(e.getType(), e.getMessage()); - } +TSoundTrackFormat TSoundInputDevice::getPreferredFormat( + const TSoundTrackFormat &format) { + try { + return getPreferredFormat(format.m_sampleRate, format.m_channelCount, + format.m_bitPerSample); + } catch (TSoundDeviceException &e) { + throw TSoundDeviceException(e.getType(), e.getMessage()); + } } //------------------------------------------------------------------------------ -bool TSoundInputDevice::isRecording() -{ - return m_imp->m_isRecording; -} +bool TSoundInputDevice::isRecording() { return m_imp->m_isRecording; } //****************************************************************************** //****************************************************************************** -// funzioni per l'interazione con la libreria audio +// funzioni per l'interazione con la libreria +//audio //****************************************************************************** //****************************************************************************** -namespace -{ -bool isInterfaceSupported(int deviceType, int interfaceType) -{ - ALvalue vals[16]; - int devNum; - - if ((devNum = alQueryValues(AL_SYSTEM, deviceType, vals, 16, 0, 0)) > 0) { - int i; - for (i = 0; i < devNum; ++i) { - ALpv quals[2]; - quals[0].param = AL_TYPE; - quals[0].value.i = interfaceType; - if (alQueryValues(vals[i].i, AL_INTERFACE, 0, 0, quals, 1) > 0) - return true; - } - } - return false; +namespace { +bool isInterfaceSupported(int deviceType, int interfaceType) { + ALvalue vals[16]; + int devNum; + + if ((devNum = alQueryValues(AL_SYSTEM, deviceType, vals, 16, 0, 0)) > 0) { + int i; + for (i = 0; i < devNum; ++i) { + ALpv quals[2]; + quals[0].param = AL_TYPE; + quals[0].value.i = interfaceType; + if (alQueryValues(vals[i].i, AL_INTERFACE, 0, 0, quals, 1) > 0) + return true; + } + } + return false; } //------------------------------------------------------------------------------ -bool setDefaultInput(TSoundInputDevice::Source type) -{ - string label; - - switch (type) { - case TSoundInputDevice::LineIn: - label = "Line In"; - break; - case TSoundInputDevice::DigitalIn: - label = "AES Input"; - break; - default: - label = "Microphone"; - } - - int dev = alGetResourceByName(AL_SYSTEM, (char *)label.c_str(), AL_DEVICE_TYPE); - if (!dev) - return false; //throw TException("Error to set input device"); - int itf; - if (itf = alGetResourceByName(AL_SYSTEM, (char *)label.c_str(), AL_INTERFACE_TYPE)) { - ALpv p; - - p.param = AL_INTERFACE; - p.value.i = itf; - if (alSetParams(dev, &p, 1) < 0 || p.sizeOut < 0) - return false; //throw TException("Error to set input device"); - } - - ALpv param; - - param.param = AL_DEFAULT_INPUT; - param.value.i = dev; - if (alSetParams(AL_SYSTEM, ¶m, 1) < 0) - return false; //throw TException("Error to set input device"); - - return true; +bool setDefaultInput(TSoundInputDevice::Source type) { + string label; + + switch (type) { + case TSoundInputDevice::LineIn: + label = "Line In"; + break; + case TSoundInputDevice::DigitalIn: + label = "AES Input"; + break; + default: + label = "Microphone"; + } + + int dev = + alGetResourceByName(AL_SYSTEM, (char *)label.c_str(), AL_DEVICE_TYPE); + if (!dev) return false; // throw TException("Error to set input device"); + int itf; + if (itf = alGetResourceByName(AL_SYSTEM, (char *)label.c_str(), + AL_INTERFACE_TYPE)) { + ALpv p; + + p.param = AL_INTERFACE; + p.value.i = itf; + if (alSetParams(dev, &p, 1) < 0 || p.sizeOut < 0) + return false; // throw TException("Error to set input device"); + } + + ALpv param; + + param.param = AL_DEFAULT_INPUT; + param.value.i = dev; + if (alSetParams(AL_SYSTEM, ¶m, 1) < 0) + return false; // throw TException("Error to set input device"); + + return true; } //------------------------------------------------------------------------------ -bool setDefaultOutput() -{ - ALpv pvbuf[1]; +bool setDefaultOutput() { + ALpv pvbuf[1]; - if (!isInterfaceSupported(AL_DEFAULT_OUTPUT, AL_SPEAKER_IF_TYPE)) - return false; //throw TException("Speakers are not supported"); + if (!isInterfaceSupported(AL_DEFAULT_OUTPUT, AL_SPEAKER_IF_TYPE)) + return false; // throw TException("Speakers are not supported"); - int dev = alGetResourceByName(AL_SYSTEM, (char *)"Headphone/Speaker", AL_DEVICE_TYPE); - if (!dev) - return false; //throw TException("invalid device speakers"); + int dev = alGetResourceByName(AL_SYSTEM, (char *)"Headphone/Speaker", + AL_DEVICE_TYPE); + if (!dev) return false; // throw TException("invalid device speakers"); - pvbuf[0].param = AL_DEFAULT_OUTPUT; - pvbuf[0].value.i = dev; - alSetParams(AL_SYSTEM, pvbuf, 1); + pvbuf[0].param = AL_DEFAULT_OUTPUT; + pvbuf[0].value.i = dev; + alSetParams(AL_SYSTEM, pvbuf, 1); - // qui devo metterci gli altoparlanti e poi setto i valori per il default output - pvbuf[0].param = AL_INTERFACE; - pvbuf[0].value.i = AL_SPEAKER_IF_TYPE; + // qui devo metterci gli altoparlanti e poi setto i valori per il default + // output + pvbuf[0].param = AL_INTERFACE; + pvbuf[0].value.i = AL_SPEAKER_IF_TYPE; - if (alSetParams(AL_DEFAULT_OUTPUT, pvbuf, 1) < 0) - return false; // throw TException("Unable to set output device params"); + if (alSetParams(AL_DEFAULT_OUTPUT, pvbuf, 1) < 0) + return false; // throw TException("Unable to set output device params"); - return true; + return true; } //------------------------------------------------------------------------------ -//return the indexes of all input device of a particular type -list getInputDevice(int deviceType) -{ - ALvalue vals[16]; - ALpv quals[1]; - list devList; - int devNum; - - quals[0].param = AL_TYPE; - quals[0].value.i = deviceType; - if ((devNum = alQueryValues(AL_SYSTEM, AL_DEFAULT_INPUT, vals, 16, quals, 1)) > 0) { - int i; - for (i = 0; i < devNum; ++i) { - int itf; - ALvalue val[16]; - if ((itf = alQueryValues(i, AL_INTERFACE, val, 16, 0, 0)) > 0) { - int j; - for (j = 0; j < itf; ++j) - devList.push_back(vals[j].i); - } - } - } - - return devList; +// return the indexes of all input device of a particular type +list getInputDevice(int deviceType) { + ALvalue vals[16]; + ALpv quals[1]; + list devList; + int devNum; + + quals[0].param = AL_TYPE; + quals[0].value.i = deviceType; + if ((devNum = alQueryValues(AL_SYSTEM, AL_DEFAULT_INPUT, vals, 16, quals, + 1)) > 0) { + int i; + for (i = 0; i < devNum; ++i) { + int itf; + ALvalue val[16]; + if ((itf = alQueryValues(i, AL_INTERFACE, val, 16, 0, 0)) > 0) { + int j; + for (j = 0; j < itf; ++j) devList.push_back(vals[j].i); + } + } + } + + return devList; } //------------------------------------------------------------------------------ -//return the indexes of all input device of a particular type and interface -list getInputDevice(int deviceType, int itfType) -{ - ALvalue vals[16]; - ALpv quals[1]; - list devList; - int devNum; - - quals[0].param = AL_TYPE; - quals[0].value.i = deviceType; - if ((devNum = alQueryValues(AL_SYSTEM, AL_DEFAULT_INPUT, vals, 16, quals, 1)) > 0) { - int i; - for (i = 0; i < devNum; ++i) { - int itf; - ALvalue val[16]; - quals[0].param = AL_TYPE; - quals[0].value.i = itfType; - if ((itf = alQueryValues(i, AL_INTERFACE, val, 16, quals, 1)) > 0) { - int j; - for (j = 0; j < itf; ++j) - devList.push_back(vals[j].i); - } - } - } - - return devList; +// return the indexes of all input device of a particular type and interface +list getInputDevice(int deviceType, int itfType) { + ALvalue vals[16]; + ALpv quals[1]; + list devList; + int devNum; + + quals[0].param = AL_TYPE; + quals[0].value.i = deviceType; + if ((devNum = alQueryValues(AL_SYSTEM, AL_DEFAULT_INPUT, vals, 16, quals, + 1)) > 0) { + int i; + for (i = 0; i < devNum; ++i) { + int itf; + ALvalue val[16]; + quals[0].param = AL_TYPE; + quals[0].value.i = itfType; + if ((itf = alQueryValues(i, AL_INTERFACE, val, 16, quals, 1)) > 0) { + int j; + for (j = 0; j < itf; ++j) devList.push_back(vals[j].i); + } + } + } + + return devList; } //------------------------------------------------------------------------------ -string getResourceLabel(int resourceID) -{ - ALpv par[1]; - char l[32]; +string getResourceLabel(int resourceID) { + ALpv par[1]; + char l[32]; - par[0].param = AL_LABEL; - par[0].value.ptr = l; - par[0].sizeIn = 32; + par[0].param = AL_LABEL; + par[0].value.ptr = l; + par[0].sizeIn = 32; - alGetParams(resourceID, par, 1); + alGetParams(resourceID, par, 1); - return string(l); + return string(l); } //------------------------------------------------------------------------------ -// verify the samplerate of the select device is changed from another application -bool isChangeOutput(ULONG sampleRate) -{ - ALpv par[2]; - char l[32]; - - par[0].param = AL_LABEL; - par[0].value.ptr = l; - par[0].sizeIn = 32; - par[1].param = AL_RATE; - - alGetParams(AL_DEFAULT_OUTPUT, par, 2); - if ((strcmp(l, "Analog Out") != 0) || (alFixedToDouble(par[1].value.ll) != sampleRate)) - return true; - else - return false; +// verify the samplerate of the select device is changed from another +// application +bool isChangeOutput(ULONG sampleRate) { + ALpv par[2]; + char l[32]; + + par[0].param = AL_LABEL; + par[0].value.ptr = l; + par[0].sizeIn = 32; + par[1].param = AL_RATE; + + alGetParams(AL_DEFAULT_OUTPUT, par, 2); + if ((strcmp(l, "Analog Out") != 0) || + (alFixedToDouble(par[1].value.ll) != sampleRate)) + return true; + else + return false; } } diff --git a/toonz/sources/common/tstepparam.h b/toonz/sources/common/tstepparam.h index 06c0c50..94c89b2 100644 --- a/toonz/sources/common/tstepparam.h +++ b/toonz/sources/common/tstepparam.h @@ -19,18 +19,17 @@ #define DVVAR DV_IMPORT_VAR #endif -class DVAPI TDoubleStepParam : public TDoubleParam -{ +class DVAPI TDoubleStepParam : public TDoubleParam { public: - TDoubleStepParam(double v = 0.0); - TDoubleStepParam(const TDoubleParam &src); - ~TDoubleStepParam(); + TDoubleStepParam(double v = 0.0); + TDoubleStepParam(const TDoubleParam &src); + ~TDoubleStepParam(); - TParam *clone() const { return new TDoubleStepParam(*this); } + TParam *clone() const { return new TDoubleStepParam(*this); } - double getValue(double frame, bool cropped = true) const; + double getValue(double frame, bool cropped = true) const; - PERSIST_DECLARATION(TDoubleStepParam) + PERSIST_DECLARATION(TDoubleStepParam) }; DEFINE_PARAM_SMARTPOINTER(TDoubleStepParam, double) diff --git a/toonz/sources/common/tstream/tpersistset.cpp b/toonz/sources/common/tstream/tpersistset.cpp index cb68252..9dd97db 100644 --- a/toonz/sources/common/tstream/tpersistset.cpp +++ b/toonz/sources/common/tstream/tpersistset.cpp @@ -20,52 +20,45 @@ PERSIST_IDENTIFIER(TPersistSet, "persistSet") //------------------------------------------------------------------ -TPersistSet::~TPersistSet() -{ - std::for_each(m_objects.begin(), m_objects.end(), - tcg::deleter()); +TPersistSet::~TPersistSet() { + std::for_each(m_objects.begin(), m_objects.end(), tcg::deleter()); } //------------------------------------------------------------------ -void TPersistSet::insert(std::auto_ptr object) -{ - struct locals { - inline static bool sameType(TPersist *a, TPersist *b) - { - return (typeid(*a) == typeid(*b)); - } - }; - - // Remove any object with the same type id - std::vector::iterator pt = std::remove_if( - m_objects.begin(), m_objects.end(), - tcg::bind1st(&locals::sameType, object.get())); - - std::for_each(pt, m_objects.end(), tcg::deleter()); - m_objects.erase(pt, m_objects.end()); - - // Push back the supplied object - m_objects.push_back(object.release()); +void TPersistSet::insert(std::auto_ptr object) { + struct locals { + inline static bool sameType(TPersist *a, TPersist *b) { + return (typeid(*a) == typeid(*b)); + } + }; + + // Remove any object with the same type id + std::vector::iterator pt = + std::remove_if(m_objects.begin(), m_objects.end(), + tcg::bind1st(&locals::sameType, object.get())); + + std::for_each(pt, m_objects.end(), tcg::deleter()); + m_objects.erase(pt, m_objects.end()); + + // Push back the supplied object + m_objects.push_back(object.release()); } //------------------------------------------------------------------ -void TPersistSet::saveData(TOStream &os) -{ - std::vector::iterator pt, pEnd = m_objects.end(); - for (pt = m_objects.begin(); pt != pEnd; ++pt) - os << *pt; +void TPersistSet::saveData(TOStream &os) { + std::vector::iterator pt, pEnd = m_objects.end(); + for (pt = m_objects.begin(); pt != pEnd; ++pt) os << *pt; } //------------------------------------------------------------------ -void TPersistSet::loadData(TIStream &is) -{ - while (!is.eos()) { - TPersist *object = 0; - is >> object; +void TPersistSet::loadData(TIStream &is) { + while (!is.eos()) { + TPersist *object = 0; + is >> object; - m_objects.push_back(object); - } + m_objects.push_back(object); + } } diff --git a/toonz/sources/common/tstream/tstream.cpp b/toonz/sources/common/tstream/tstream.cpp index e31d835..edac042 100644 --- a/toonz/sources/common/tstream/tstream.cpp +++ b/toonz/sources/common/tstream/tstream.cpp @@ -20,965 +20,870 @@ using namespace std; //=============================================================== -namespace -{ - -string escape(string v) -{ - int i = 0; - for (;;) { - i = v.find_first_of("\\\'\"", i); - if (i == (int)string::npos) - break; - string h = "\\" + v[i]; - v.insert(i, "\\"); - i = i + 2; - } - return v; +namespace { + +string escape(string v) { + int i = 0; + for (;;) { + i = v.find_first_of("\\\'\"", i); + if (i == (int)string::npos) break; + string h = "\\" + v[i]; + v.insert(i, "\\"); + i = i + 2; + } + return v; } //=============================================================== -void writeCompressedFile(TFilePath dst, const std::string &str) -{ -} +void writeCompressedFile(TFilePath dst, const std::string &str) {} //=================================================================== -void readCompressedFile(string &str, TFilePath src) -{ - TFileStatus status(src); - if (!status.doesExist()) - return; +void readCompressedFile(string &str, TFilePath src) { + TFileStatus status(src); + if (!status.doesExist()) return; - size_t in_len = status.getSize(); - char *in = (char *)malloc(in_len); - { - Tifstream is(src); - is.read((char *)in, in_len); - } + size_t in_len = status.getSize(); + char *in = (char *)malloc(in_len); + { + Tifstream is(src); + is.read((char *)in, in_len); + } - LZ4F_decompressionContext_t lz4dctx; + LZ4F_decompressionContext_t lz4dctx; - LZ4F_errorCode_t err = LZ4F_createDecompressionContext(&lz4dctx, LZ4F_VERSION); - if (LZ4F_isError(err)) - return; + LZ4F_errorCode_t err = + LZ4F_createDecompressionContext(&lz4dctx, LZ4F_VERSION); + if (LZ4F_isError(err)) return; - size_t in_len_read = 0; + size_t in_len_read = 0; - size_t out_len = 1000000, out_len_written, out_len_moved = 0; - void *out = (void *)malloc(out_len); + size_t out_len = 1000000, out_len_written, out_len_moved = 0; + void *out = (void *)malloc(out_len); - while (in_len_read < in_len) { - out_len_written = out_len; + while (in_len_read < in_len) { + out_len_written = out_len; - size_t remaining = LZ4F_decompress(lz4dctx, out, &out_len_written, in, &in_len, NULL); - if (LZ4F_isError(remaining)) - break; + size_t remaining = + LZ4F_decompress(lz4dctx, out, &out_len_written, in, &in_len, NULL); + if (LZ4F_isError(remaining)) break; - str.resize(out_len_moved + out_len_written); + str.resize(out_len_moved + out_len_written); - memcpy((void *)(str.c_str() + out_len_moved), (void *)out, out_len_written); - out_len_moved += out_len_written; - } + memcpy((void *)(str.c_str() + out_len_moved), (void *)out, out_len_written); + out_len_moved += out_len_written; + } - LZ4F_freeDecompressionContext(lz4dctx); + LZ4F_freeDecompressionContext(lz4dctx); - free(in); - free(out); + free(in); + free(out); } -namespace -{ +namespace { // TODO: Unify with tcodec.cpp's version -bool lz4decompress(LZ4F_decompressionContext_t lz4dctx, - char *out, size_t *out_len_res, - const char *in, size_t in_len) -{ - size_t out_len = *out_len_res, - in_read, out_written; +bool lz4decompress(LZ4F_decompressionContext_t lz4dctx, char *out, + size_t *out_len_res, const char *in, size_t in_len) { + size_t out_len = *out_len_res, in_read, out_written; - *out_len_res = 0; + *out_len_res = 0; - while (in_len) { - out_written = out_len; - in_read = in_len; + while (in_len) { + out_written = out_len; + in_read = in_len; - size_t res = LZ4F_decompress( - lz4dctx, (void *)out, &out_written, (const void *)in, &in_read, NULL); + size_t res = LZ4F_decompress(lz4dctx, (void *)out, &out_written, + (const void *)in, &in_read, NULL); - if (LZ4F_isError(res)) - return false; + if (LZ4F_isError(res)) return false; - *out_len_res += out_written; + *out_len_res += out_written; - out += out_written; - out_len -= out_written; + out += out_written; + out_len -= out_written; - in += in_read; - in_len -= in_read; - } + in += in_read; + in_len -= in_read; + } - return true; + return true; } -} // namespace +} // namespace //=============================================================== -class StreamTag -{ +class StreamTag { public: - string m_name; - std::map m_attributes; - enum Type { BeginTag, - EndTag, - BeginEndTag }; - Type m_type; - StreamTag() : m_type(BeginTag) {} - - operator bool() const { return m_name != ""; } - - void dump() - { - cout << "name = '" << m_name << "'" << endl; - cout << "type = "; - switch (m_type) { - case BeginTag: - cout << "begin Tag"; - break; - case EndTag: - cout << "end Tag"; - break; - case BeginEndTag: - cout << "begin/end Tag"; - break; - default: - cout << "**bad Tag**"; - break; - } - cout << endl; - std::map::iterator it; - for (it = m_attributes.begin(); it != m_attributes.end(); ++it) { - cout << " '" << it->first << "' = '" << it->second << "'" << endl; - } - } + string m_name; + std::map m_attributes; + enum Type { BeginTag, EndTag, BeginEndTag }; + Type m_type; + StreamTag() : m_type(BeginTag) {} + + operator bool() const { return m_name != ""; } + + void dump() { + cout << "name = '" << m_name << "'" << endl; + cout << "type = "; + switch (m_type) { + case BeginTag: + cout << "begin Tag"; + break; + case EndTag: + cout << "end Tag"; + break; + case BeginEndTag: + cout << "begin/end Tag"; + break; + default: + cout << "**bad Tag**"; + break; + } + cout << endl; + std::map::iterator it; + for (it = m_attributes.begin(); it != m_attributes.end(); ++it) { + cout << " '" << it->first << "' = '" << it->second << "'" << endl; + } + } }; //-------------------------------- -class TPersistFactory -{ - typedef std::map Table; - static TPersistFactory *m_factory; - Table m_table; - TPersistFactory() {} +class TPersistFactory { + typedef std::map Table; + static TPersistFactory *m_factory; + Table m_table; + TPersistFactory() {} public: - static TPersistFactory *instance() - { - if (!m_factory) - m_factory = new TPersistFactory; - return m_factory; - } - void add(string name, TPersistDeclaration *decl) - { - m_table[name] = decl; - } - TPersist *create(string name) - { - Table::iterator it = m_table.find(name); - if (it != m_table.end()) - return (it->second)->create(); - else - return 0; - } + static TPersistFactory *instance() { + if (!m_factory) m_factory = new TPersistFactory; + return m_factory; + } + void add(string name, TPersistDeclaration *decl) { m_table[name] = decl; } + TPersist *create(string name) { + Table::iterator it = m_table.find(name); + if (it != m_table.end()) + return (it->second)->create(); + else + return 0; + } }; //-------------------------------- TPersistFactory *TPersistFactory::m_factory = 0; -} // namespace +} // namespace //-------------------------------- -TPersistDeclaration::TPersistDeclaration(const std::string &id) - : m_id(id) -{ - TPersistFactory::instance()->add(id, this); +TPersistDeclaration::TPersistDeclaration(const std::string &id) : m_id(id) { + TPersistFactory::instance()->add(id, this); } //=============================================================== -TPersist *TPersist::create(const std::string &name) -{ - return TPersistFactory::instance()->create(name); +TPersist *TPersist::create(const std::string &name) { + return TPersistFactory::instance()->create(name); } //=============================================================== -class TOStream::Imp -{ +class TOStream::Imp { public: - ostream *m_os; - bool m_chanOwner; - bool m_compressed; - ostringstream m_ostringstream; - - vector m_tagStack; - int m_tab; - bool m_justStarted; - typedef map PersistTable; - PersistTable m_table; - int m_maxId; - TFilePath m_filepath; - - Imp() : m_os(0), m_chanOwner(false), m_tab(0), m_justStarted(true), m_maxId(0), m_compressed(false) {} + ostream *m_os; + bool m_chanOwner; + bool m_compressed; + ostringstream m_ostringstream; + + vector m_tagStack; + int m_tab; + bool m_justStarted; + typedef map PersistTable; + PersistTable m_table; + int m_maxId; + TFilePath m_filepath; + + Imp() + : m_os(0) + , m_chanOwner(false) + , m_tab(0) + , m_justStarted(true) + , m_maxId(0) + , m_compressed(false) {} }; //--------------------------------------------------------------- -TOStream::TOStream(const TFilePath &fp, bool compressed) - : m_imp(new Imp) -{ - m_imp->m_filepath = fp; - - if (compressed) { - m_imp->m_os = &m_imp->m_ostringstream; - m_imp->m_compressed = true; - m_imp->m_chanOwner = false; - } else { - std::auto_ptr os(new Tofstream(fp)); - m_imp->m_os = os->isOpen() ? os.release() : 0; - m_imp->m_chanOwner = true; - } - - m_imp->m_justStarted = true; +TOStream::TOStream(const TFilePath &fp, bool compressed) : m_imp(new Imp) { + m_imp->m_filepath = fp; + + if (compressed) { + m_imp->m_os = &m_imp->m_ostringstream; + m_imp->m_compressed = true; + m_imp->m_chanOwner = false; + } else { + std::auto_ptr os(new Tofstream(fp)); + m_imp->m_os = os->isOpen() ? os.release() : 0; + m_imp->m_chanOwner = true; + } + + m_imp->m_justStarted = true; } //--------------------------------------------------------------- -TOStream::TOStream(std::shared_ptr imp) - : m_imp(std::move(imp)) -{ - assert(!m_imp->m_tagStack.empty()); - ostream &os = *m_imp->m_os; - if (!m_imp->m_justStarted) - cr(); - os << "<" << m_imp->m_tagStack.back() << ">"; - m_imp->m_tab++; - cr(); - m_imp->m_justStarted = true; +TOStream::TOStream(std::shared_ptr imp) : m_imp(std::move(imp)) { + assert(!m_imp->m_tagStack.empty()); + ostream &os = *m_imp->m_os; + if (!m_imp->m_justStarted) cr(); + os << "<" << m_imp->m_tagStack.back() << ">"; + m_imp->m_tab++; + cr(); + m_imp->m_justStarted = true; } -TOStream::TOStream(TOStream&& that) - : m_imp(std::move(that.m_imp)) -{ -} +TOStream::TOStream(TOStream &&that) : m_imp(std::move(that.m_imp)) {} -TOStream& TOStream::operator = (TOStream && that) -{ - if (this != &that) { - this->m_imp = std::move(that.m_imp); - } - return *this; +TOStream &TOStream::operator=(TOStream &&that) { + if (this != &that) { + this->m_imp = std::move(that.m_imp); + } + return *this; } //--------------------------------------------------------------- -TOStream::~TOStream() -{ - if (!m_imp) { - return; - } - try { - if (!m_imp->m_tagStack.empty()) { - string tagName = m_imp->m_tagStack.back(); - m_imp->m_tagStack.pop_back(); - assert(tagName != ""); - ostream &os = *m_imp->m_os; - m_imp->m_tab--; - if (!m_imp->m_justStarted) - cr(); - os << ""; - cr(); - m_imp->m_justStarted = true; - } else { - if (m_imp->m_compressed) { - std::string tmp = m_imp->m_ostringstream.str(); - const void *in = (const void *)tmp.c_str(); - - size_t in_len = strlen((char *)in); - - size_t out_len = LZ4F_compressFrameBound(in_len, NULL); - void *out = malloc(out_len); - - out_len = LZ4F_compressFrame(out, out_len, in, in_len, NULL); - if (!LZ4F_isError(out_len)) { - Tofstream os(m_imp->m_filepath); - // TNZC - os.write("TABc", 4); - TINT32 v; - v = 0x0A0B0C0D; - os.write((char *)&v, sizeof v); - v = in_len; - os.write((char *)&v, sizeof v); - v = out_len; - os.write((char *)&v, sizeof v); - os.write((char *)out, out_len); - } - - free(out); - } - if (m_imp->m_chanOwner) - delete m_imp->m_os; - } - } catch (...) { - } +TOStream::~TOStream() { + if (!m_imp) { + return; + } + try { + if (!m_imp->m_tagStack.empty()) { + string tagName = m_imp->m_tagStack.back(); + m_imp->m_tagStack.pop_back(); + assert(tagName != ""); + ostream &os = *m_imp->m_os; + m_imp->m_tab--; + if (!m_imp->m_justStarted) cr(); + os << ""; + cr(); + m_imp->m_justStarted = true; + } else { + if (m_imp->m_compressed) { + std::string tmp = m_imp->m_ostringstream.str(); + const void *in = (const void *)tmp.c_str(); + + size_t in_len = strlen((char *)in); + + size_t out_len = LZ4F_compressFrameBound(in_len, NULL); + void *out = malloc(out_len); + + out_len = LZ4F_compressFrame(out, out_len, in, in_len, NULL); + if (!LZ4F_isError(out_len)) { + Tofstream os(m_imp->m_filepath); + // TNZC + os.write("TABc", 4); + TINT32 v; + v = 0x0A0B0C0D; + os.write((char *)&v, sizeof v); + v = in_len; + os.write((char *)&v, sizeof v); + v = out_len; + os.write((char *)&v, sizeof v); + os.write((char *)out, out_len); + } + + free(out); + } + if (m_imp->m_chanOwner) delete m_imp->m_os; + } + } catch (...) { + } } //--------------------------------------------------------------- -TFilePath TOStream::getFilePath() -{ - return m_imp->m_filepath; -} +TFilePath TOStream::getFilePath() { return m_imp->m_filepath; } //--------------------------------------------------------------- -TFilePath TOStream::getRepositoryPath() -{ - TFilePath fp = m_imp->m_filepath; - return fp.getParentDir() + (fp.getName() + "_files"); +TFilePath TOStream::getRepositoryPath() { + TFilePath fp = m_imp->m_filepath; + return fp.getParentDir() + (fp.getName() + "_files"); } //--------------------------------------------------------------- -TOStream &TOStream::operator<<(int v) -{ - *(m_imp->m_os) << v << " "; - m_imp->m_justStarted = false; - return *this; +TOStream &TOStream::operator<<(int v) { + *(m_imp->m_os) << v << " "; + m_imp->m_justStarted = false; + return *this; } //--------------------------------------------------------------- -TOStream &TOStream::operator<<(double v) -{ - if (areAlmostEqual(v, 0)) //con valori molto piccoli (es. 1.4e-310) non riesce a rileggerli! - v = 0; +TOStream &TOStream::operator<<(double v) { + if (areAlmostEqual(v, 0)) // con valori molto piccoli (es. 1.4e-310) non + // riesce a rileggerli! + v = 0; - *(m_imp->m_os) << v << " "; - m_imp->m_justStarted = false; - return *this; + *(m_imp->m_os) << v << " "; + m_imp->m_justStarted = false; + return *this; } //--------------------------------------------------------------- -TOStream &TOStream::operator<<(string v) -{ - ostream &os = *(m_imp->m_os); - int len = v.length(); - if (len == 0) { - os << "\"\"" - << " "; - m_imp->m_justStarted = false; - return *this; - } - int i; - for (i = 0; i < len; i++) - if (!iswalnum(v[i]) && v[i] != '_' && v[i] != '%') - break; - if (i == len) - os << v << " "; - else { - os << '"' << escape(v) << '"'; - } - m_imp->m_justStarted = false; - return *this; +TOStream &TOStream::operator<<(string v) { + ostream &os = *(m_imp->m_os); + int len = v.length(); + if (len == 0) { + os << "\"\"" + << " "; + m_imp->m_justStarted = false; + return *this; + } + int i; + for (i = 0; i < len; i++) + if (!iswalnum(v[i]) && v[i] != '_' && v[i] != '%') break; + if (i == len) + os << v << " "; + else { + os << '"' << escape(v) << '"'; + } + m_imp->m_justStarted = false; + return *this; } //--------------------------------------------------------------- -TOStream &TOStream::operator<<(QString _v) -{ - string v = _v.toStdString(); - - ostream &os = *(m_imp->m_os); - int len = v.length(); - if (len == 0) { - os << "\"\"" - << " "; - m_imp->m_justStarted = false; - return *this; - } - int i; - for (i = 0; i < len; i++) - if (!iswalnum(v[i]) && v[i] != '_' && v[i] != '%') - break; - if (i == len) - os << v << " "; - else { - os << '"' << escape(v) << '"'; - } - m_imp->m_justStarted = false; - return *this; -} - -//--------------------------------------------------------------- +TOStream &TOStream::operator<<(QString _v) { + string v = _v.toStdString(); -TOStream &TOStream::operator<<(std::wstring v) -{ - return operator<<(::to_string(v)); - /* ostream &os = *(m_imp->m_os); - int len = v.length(); - if(len==0) - { - os << "\"" << "\"" << " "; + int len = v.length(); + if (len == 0) { + os << "\"\"" + << " "; m_imp->m_justStarted = false; return *this; } int i; - for(i=0;im_justStarted = false; return *this; -*/ } //--------------------------------------------------------------- -TOStream &TOStream::operator<<(const TFilePath &v) -{ - return operator<<(v.getWideString()); +TOStream &TOStream::operator<<(std::wstring v) { + return operator<<(::to_string(v)); + /* +ostream &os = *(m_imp->m_os); +int len = v.length(); +if(len==0) +{ +os << "\"" << "\"" << " "; +m_imp->m_justStarted = false; +return *this; +} +int i; +for(i=0;im_justStarted = false; +return *this; +*/ } //--------------------------------------------------------------- -TOStream &TOStream::operator<<(const TPixel32 &v) -{ - ostream &os = *(m_imp->m_os); - os << (int)v.r << " " << (int)v.g << " " << (int)v.b << " " << (int)v.m << " "; - m_imp->m_justStarted = false; - return *this; +TOStream &TOStream::operator<<(const TFilePath &v) { + return operator<<(v.getWideString()); } //--------------------------------------------------------------- -TOStream &TOStream::operator<<(const TPixel64 &v) -{ - ostream &os = *(m_imp->m_os); - os << (int)v.r << " " << (int)v.g << " " << (int)v.b << " " << (int)v.m << " "; - m_imp->m_justStarted = false; - return *this; +TOStream &TOStream::operator<<(const TPixel32 &v) { + ostream &os = *(m_imp->m_os); + os << (int)v.r << " " << (int)v.g << " " << (int)v.b << " " << (int)v.m + << " "; + m_imp->m_justStarted = false; + return *this; } //--------------------------------------------------------------- -void TOStream::cr() -{ - *(m_imp->m_os) << endl; - for (int i = 0; i < m_imp->m_tab; i++) - *(m_imp->m_os) << " "; - m_imp->m_justStarted = false; +TOStream &TOStream::operator<<(const TPixel64 &v) { + ostream &os = *(m_imp->m_os); + os << (int)v.r << " " << (int)v.g << " " << (int)v.b << " " << (int)v.m + << " "; + m_imp->m_justStarted = false; + return *this; } //--------------------------------------------------------------- -TOStream::operator bool() const -{ - return (m_imp->m_os && *m_imp->m_os); +void TOStream::cr() { + *(m_imp->m_os) << endl; + for (int i = 0; i < m_imp->m_tab; i++) *(m_imp->m_os) << " "; + m_imp->m_justStarted = false; } //--------------------------------------------------------------- -TOStream TOStream::child(string tagName) -{ - assert(tagName != ""); - m_imp->m_tagStack.push_back(tagName); - return TOStream(m_imp); + +TOStream::operator bool() const { return (m_imp->m_os && *m_imp->m_os); } + +//--------------------------------------------------------------- +TOStream TOStream::child(string tagName) { + assert(tagName != ""); + m_imp->m_tagStack.push_back(tagName); + return TOStream(m_imp); } //--------------------------------------------------------------- -void TOStream::openChild(string tagName) -{ - assert(tagName != ""); - m_imp->m_tagStack.push_back(tagName); - if (m_imp->m_justStarted == false) - cr(); - *(m_imp->m_os) << "<" << m_imp->m_tagStack.back() << ">"; - m_imp->m_tab++; - cr(); - m_imp->m_justStarted = true; +void TOStream::openChild(string tagName) { + assert(tagName != ""); + m_imp->m_tagStack.push_back(tagName); + if (m_imp->m_justStarted == false) cr(); + *(m_imp->m_os) << "<" << m_imp->m_tagStack.back() << ">"; + m_imp->m_tab++; + cr(); + m_imp->m_justStarted = true; } //--------------------------------------------------------------- -void TOStream::openChild(string tagName, const map &attributes) -{ - assert(tagName != ""); - m_imp->m_tagStack.push_back(tagName); - if (m_imp->m_justStarted == false) - cr(); - *(m_imp->m_os) << "<" << m_imp->m_tagStack.back(); - for (std::map::const_iterator it = attributes.begin(); - it != attributes.end(); ++it) { - *(m_imp->m_os) << " " << it->first - << "=\"" << escape(it->second) << "\""; - } - *(m_imp->m_os) << ">"; - m_imp->m_tab++; - cr(); - m_imp->m_justStarted = true; +void TOStream::openChild(string tagName, + const map &attributes) { + assert(tagName != ""); + m_imp->m_tagStack.push_back(tagName); + if (m_imp->m_justStarted == false) cr(); + *(m_imp->m_os) << "<" << m_imp->m_tagStack.back(); + for (std::map::const_iterator it = attributes.begin(); + it != attributes.end(); ++it) { + *(m_imp->m_os) << " " << it->first << "=\"" << escape(it->second) << "\""; + } + *(m_imp->m_os) << ">"; + m_imp->m_tab++; + cr(); + m_imp->m_justStarted = true; } //--------------------------------------------------------------- -void TOStream::closeChild() -{ - assert(!m_imp->m_tagStack.empty()); - string tagName = m_imp->m_tagStack.back(); - m_imp->m_tagStack.pop_back(); - assert(tagName != ""); - //ostream &os = *m_imp->m_os; //os non e' usato - m_imp->m_tab--; - if (!m_imp->m_justStarted) - cr(); - *(m_imp->m_os) << ""; - cr(); - m_imp->m_justStarted = true; +void TOStream::closeChild() { + assert(!m_imp->m_tagStack.empty()); + string tagName = m_imp->m_tagStack.back(); + m_imp->m_tagStack.pop_back(); + assert(tagName != ""); + // ostream &os = *m_imp->m_os; //os non e' usato + m_imp->m_tab--; + if (!m_imp->m_justStarted) cr(); + *(m_imp->m_os) << ""; + cr(); + m_imp->m_justStarted = true; } //--------------------------------------------------------------- -void TOStream::openCloseChild(string tagName, const map &attributes) -{ - assert(tagName != ""); - // m_imp->m_tagStack.push_back(tagName); - if (m_imp->m_justStarted == false) - cr(); - *(m_imp->m_os) << "<" << tagName; - for (std::map::const_iterator it = attributes.begin(); - it != attributes.end(); ++it) { - *(m_imp->m_os) << " " << it->first - << "=\"" << escape(it->second) << "\""; - } - *(m_imp->m_os) << "/>"; - //m_imp->m_tab++; - cr(); - m_imp->m_justStarted = true; +void TOStream::openCloseChild(string tagName, + const map &attributes) { + assert(tagName != ""); + // m_imp->m_tagStack.push_back(tagName); + if (m_imp->m_justStarted == false) cr(); + *(m_imp->m_os) << "<" << tagName; + for (std::map::const_iterator it = attributes.begin(); + it != attributes.end(); ++it) { + *(m_imp->m_os) << " " << it->first << "=\"" << escape(it->second) << "\""; + } + *(m_imp->m_os) << "/>"; + // m_imp->m_tab++; + cr(); + m_imp->m_justStarted = true; } //--------------------------------------------------------------- -TOStream &TOStream::operator<<(TPersist &v) -{ - v.saveData(*this); - return *this; +TOStream &TOStream::operator<<(TPersist &v) { + v.saveData(*this); + return *this; } //--------------------------------------------------------------- -TOStream &TOStream::operator<<(TPersist *v) -{ - Imp::PersistTable::iterator it = m_imp->m_table.find(v); - if (it != m_imp->m_table.end()) { - *(m_imp->m_os) << "<" << v->getStreamTag() << " id='" << it->second << "'/>"; - m_imp->m_justStarted = false; - } else { - int id = ++m_imp->m_maxId; - m_imp->m_table[v] = id; - *(m_imp->m_os) << "<" << v->getStreamTag() << " id='" << id << "'>"; - m_imp->m_tab++; - cr(); - v->saveData(*this); - m_imp->m_tab--; - cr(); - *(m_imp->m_os) << "getStreamTag() << ">"; - cr(); - } - return *this; +TOStream &TOStream::operator<<(TPersist *v) { + Imp::PersistTable::iterator it = m_imp->m_table.find(v); + if (it != m_imp->m_table.end()) { + *(m_imp->m_os) << "<" << v->getStreamTag() << " id='" << it->second + << "'/>"; + m_imp->m_justStarted = false; + } else { + int id = ++m_imp->m_maxId; + m_imp->m_table[v] = id; + *(m_imp->m_os) << "<" << v->getStreamTag() << " id='" << id << "'>"; + m_imp->m_tab++; + cr(); + v->saveData(*this); + m_imp->m_tab--; + cr(); + *(m_imp->m_os) << "getStreamTag() << ">"; + cr(); + } + return *this; } //--------------------------------------------------------------- -bool TOStream::checkStatus() const -{ - if (!m_imp->m_os) - return false; +bool TOStream::checkStatus() const { + if (!m_imp->m_os) return false; - m_imp->m_os->flush(); - return m_imp->m_os->rdstate() == ios_base::goodbit; + m_imp->m_os->flush(); + return m_imp->m_os->rdstate() == ios_base::goodbit; } //=============================================================== /*! - This class contains TIStream's attributes. - It is created by memory allocation in the TIStream's constructor. + This class contains TIStream's attributes. + It is created by memory allocation in the TIStream's constructor. */ -class TIStream::Imp -{ +class TIStream::Imp { public: - istream *m_is; - bool m_chanOwner; - int m_line; - string m_strbuffer; - bool m_compressed; + istream *m_is; + bool m_chanOwner; + int m_line; + string m_strbuffer; + bool m_compressed; - vector m_tagStack; + vector m_tagStack; - typedef map PersistTable; - PersistTable m_table; + typedef map PersistTable; + PersistTable m_table; - StreamTag m_currentTag; + StreamTag m_currentTag; - TFilePath m_filepath; + TFilePath m_filepath; - VersionNumber m_versionNumber; + VersionNumber m_versionNumber; - Imp() : m_is(0), m_chanOwner(false), m_line(0), m_compressed(false), m_versionNumber(0, 0) {} + Imp() + : m_is(0) + , m_chanOwner(false) + , m_line(0) + , m_compressed(false) + , m_versionNumber(0, 0) {} - // update m_line if necessary; returns -e if eof - int getNextChar(); + // update m_line if necessary; returns -e if eof + int getNextChar(); - inline void skipBlanks(); - bool matchTag(); - inline bool match(char c); - bool matchIdent(string &ident); - bool matchValue(string &value); + inline void skipBlanks(); + bool matchTag(); + inline bool match(char c); + bool matchIdent(string &ident); + bool matchValue(string &value); - void skipCurrentTag(); + void skipCurrentTag(); }; //--------------------------------------------------------------- -TFilePath TIStream::getFilePath() -{ - return m_imp->m_filepath; -} +TFilePath TIStream::getFilePath() { return m_imp->m_filepath; } //--------------------------------------------------------------- -TFilePath TIStream::getRepositoryPath() -{ - TFilePath fp = m_imp->m_filepath; - return fp.getParentDir() + (fp.getName() + "_files"); +TFilePath TIStream::getRepositoryPath() { + TFilePath fp = m_imp->m_filepath; + return fp.getParentDir() + (fp.getName() + "_files"); } //--------------------------------------------------------------- -int TIStream::Imp::getNextChar() -{ - char c; - m_is->get(c); - if (m_is->eof()) - return -1; - if (c == '\r') - m_line++; - return c; +int TIStream::Imp::getNextChar() { + char c; + m_is->get(c); + if (m_is->eof()) return -1; + if (c == '\r') m_line++; + return c; } //--------------------------------------------------------------- -void TIStream::Imp::skipBlanks() -{ - istream &is = *m_is; - istream::int_type c; - while (c = is.peek(), (isspace(c) || c == '\r')) - getNextChar(); +void TIStream::Imp::skipBlanks() { + istream &is = *m_is; + istream::int_type c; + while (c = is.peek(), (isspace(c) || c == '\r')) getNextChar(); } //--------------------------------------------------------------- -bool TIStream::Imp::match(char c) -{ - if (m_is->peek() == c) { - getNextChar(); - return true; - } else - return false; +bool TIStream::Imp::match(char c) { + if (m_is->peek() == c) { + getNextChar(); + return true; + } else + return false; } //--------------------------------------------------------------- -bool TIStream::Imp::matchIdent(string &ident) -{ - istream &is = *m_is; - if (!isalnum(is.peek())) - return false; - ident = ""; - char c; - is.get(c); - ident.append(1, c); - while (c = is.peek(), isalnum(c) || c == '_' || c == '.' || c == '-') { - is.get(c); - ident.append(1, c); - } - return true; +bool TIStream::Imp::matchIdent(string &ident) { + istream &is = *m_is; + if (!isalnum(is.peek())) return false; + ident = ""; + char c; + is.get(c); + ident.append(1, c); + while (c = is.peek(), isalnum(c) || c == '_' || c == '.' || c == '-') { + is.get(c); + ident.append(1, c); + } + return true; } //--------------------------------------------------------------- -bool TIStream::Imp::matchValue(string &str) -{ - istream &is = *m_is; - char quote = is.peek(); - char c; - if (!is || (quote != '\'' && quote != '\"')) - return false; - is.get(c); - str = ""; - for (;;) { - is.get(c); - if (!is) - throw TException("expected '\"'"); - if (c == quote) - break; - if (c == '\\') { - is.get(c); - if (!is) - throw TException("unexpected EOF"); - if (c != '\'' && c != '\"' && c != '\\') - throw TException("bad escape sequence"); - } - str.append(1, c); - } - if (c != quote) - throw TException("missing '\"'"); - return true; +bool TIStream::Imp::matchValue(string &str) { + istream &is = *m_is; + char quote = is.peek(); + char c; + if (!is || (quote != '\'' && quote != '\"')) return false; + is.get(c); + str = ""; + for (;;) { + is.get(c); + if (!is) throw TException("expected '\"'"); + if (c == quote) break; + if (c == '\\') { + is.get(c); + if (!is) throw TException("unexpected EOF"); + if (c != '\'' && c != '\"' && c != '\\') + throw TException("bad escape sequence"); + } + str.append(1, c); + } + if (c != quote) throw TException("missing '\"'"); + return true; } //--------------------------------------------------------------- -bool TIStream::Imp::matchTag() -{ - if (m_currentTag) - return true; - StreamTag &tag = m_currentTag; - tag = StreamTag(); - skipBlanks(); - if (!match('<')) - return false; - skipBlanks(); - if (match('!')) { - skipBlanks(); - if (!match('-') || !match('-')) - throw TException("expected '" << (*it)->m_w1 << ")" << std::endl; - os << "color=(" << color.r << "," << color.g << "," << color.b << ")" << std::endl; - } - os << std::endl - << std::endl - << std::endl; + for (it = edges.begin(); it != edges.end(); ++it) { + TColorStyle *style = plt->getStyle((*it)->m_styleId); + TPixel32 color = style->getMainColor(); + os << "w0-w1:(" << (*it)->m_w0 << "-->" << (*it)->m_w1 << ")" << std::endl; + os << "color=(" << color.r << "," << color.g << "," << color.b << ")" + << std::endl; + } + os << std::endl << std::endl << std::endl; } #else #define printEdges @@ -2058,566 +2011,568 @@ void printEdges(std::ofstream &os, char *str, TPalette *plt, const std::listm_s->print(os); - } +void TVectorImage::Imp::printStrokes(std::ofstream &os) { + for (int i = 0; i < (int)m_strokes.size(); i++) { + os << "*****stroke #" << i << " *****"; + m_strokes[i]->m_s->print(os); + } } #endif //----------------------------------------------------------------------------- -TStroke *TVectorImage::removeEndpoints(int strokeIndex) -{ - return m_imp->removeEndpoints(strokeIndex); +TStroke *TVectorImage::removeEndpoints(int strokeIndex) { + return m_imp->removeEndpoints(strokeIndex); } -void TVectorImage::restoreEndpoints(int index, TStroke *oldStroke) -{ - m_imp->restoreEndpoints(index, oldStroke); +void TVectorImage::restoreEndpoints(int index, TStroke *oldStroke) { + m_imp->restoreEndpoints(index, oldStroke); } //----------------------------------------------------------------------------- -VIStroke *TVectorImage::Imp::extendStrokeSmoothly(int index, const TThickPoint &pos, int cpIndex) -{ - TStroke *stroke = m_strokes[index]->m_s; - TGroupId groupId = m_strokes[index]->m_groupId; +VIStroke *TVectorImage::Imp::extendStrokeSmoothly(int index, + const TThickPoint &pos, + int cpIndex) { + TStroke *stroke = m_strokes[index]->m_s; + TGroupId groupId = m_strokes[index]->m_groupId; - int cpCount = stroke->getControlPointCount(); - int styleId = stroke->getStyle(); - const TThickQuadratic *q = stroke->getChunk(cpIndex == 0 ? 0 : stroke->getChunkCount() - 1); + int cpCount = stroke->getControlPointCount(); + int styleId = stroke->getStyle(); + const TThickQuadratic *q = + stroke->getChunk(cpIndex == 0 ? 0 : stroke->getChunkCount() - 1); - double len = q->getLength(); - double w = exp(-len * 0.01); - TThickPoint m = q->getThickP1(); + double len = q->getLength(); + double w = exp(-len * 0.01); + TThickPoint m = q->getThickP1(); - TThickPoint p1 = (cpIndex == 0 ? q->getThickP0() : q->getThickP2()) * (1 - w) + m * w; - TThickPoint middleP = (p1 + pos) * 0.5; + TThickPoint p1 = + (cpIndex == 0 ? q->getThickP0() : q->getThickP2()) * (1 - w) + m * w; + TThickPoint middleP = (p1 + pos) * 0.5; - double angle = fabs(cross(normalize(m - middleP), normalize(pos - middleP))); - if (angle < 0.05) - middleP = (m + pos) * 0.5; + double angle = fabs(cross(normalize(m - middleP), normalize(pos - middleP))); + if (angle < 0.05) middleP = (m + pos) * 0.5; - stroke->setControlPoint(cpIndex, middleP); - if (isAlmostZero(len)) { - if (cpIndex == 0) - stroke->setControlPoint(1, middleP * 0.1 + stroke->getControlPoint(2) * 0.9); - else - stroke->setControlPoint(cpCount - 2, middleP * 0.1 + stroke->getControlPoint(cpCount - 3) * 0.9); - } + stroke->setControlPoint(cpIndex, middleP); + if (isAlmostZero(len)) { + if (cpIndex == 0) + stroke->setControlPoint(1, + middleP * 0.1 + stroke->getControlPoint(2) * 0.9); + else + stroke->setControlPoint( + cpCount - 2, + middleP * 0.1 + stroke->getControlPoint(cpCount - 3) * 0.9); + } - std::vector points(cpCount); - for (int i = 0; i < cpCount - 1; i++) - points[i] = stroke->getControlPoint((cpIndex == 0) ? cpCount - i - 1 : i); - points[cpCount - 1] = pos; + std::vector points(cpCount); + for (int i = 0; i < cpCount - 1; i++) + points[i] = stroke->getControlPoint((cpIndex == 0) ? cpCount - i - 1 : i); + points[cpCount - 1] = pos; - TStroke *newStroke = new TStroke(points); - newStroke->setStyle(styleId); - newStroke->outlineOptions() = stroke->outlineOptions(); - std::list oldEdgeList, emptyList; - computeEdgeList(newStroke, m_strokes[index]->m_edgeList, cpIndex == 0, - emptyList, 0, oldEdgeList); + TStroke *newStroke = new TStroke(points); + newStroke->setStyle(styleId); + newStroke->outlineOptions() = stroke->outlineOptions(); + std::list oldEdgeList, emptyList; + computeEdgeList(newStroke, m_strokes[index]->m_edgeList, cpIndex == 0, + emptyList, 0, oldEdgeList); - std::vector toBeDeleted; - toBeDeleted.push_back(index); - removeStrokes(toBeDeleted, true, false); + std::vector toBeDeleted; + toBeDeleted.push_back(index); + removeStrokes(toBeDeleted, true, false); - insertStrokeAt(new VIStroke(newStroke, groupId), index, false); - computeRegions(); - transferColors(oldEdgeList, m_strokes[index]->m_edgeList, true, false, true); + insertStrokeAt(new VIStroke(newStroke, groupId), index, false); + computeRegions(); + transferColors(oldEdgeList, m_strokes[index]->m_edgeList, true, false, true); - return m_strokes[index]; + return m_strokes[index]; } //----------------------------------------------------------------------------- -VIStroke *TVectorImage::Imp::extendStroke(int index, const TThickPoint &p, int cpIndex) -{ - TGroupId groupId = m_strokes[index]->m_groupId; +VIStroke *TVectorImage::Imp::extendStroke(int index, const TThickPoint &p, + int cpIndex) { + TGroupId groupId = m_strokes[index]->m_groupId; - TStroke *stroke = m_strokes[index]->m_s; + TStroke *stroke = m_strokes[index]->m_s; - TStroke *ret; - int cpCount = stroke->getControlPointCount(); - int count = 0; - std::vector points(cpCount + 2); - int i, incr = (cpIndex == 0) ? -1 : 1; - for (i = ((cpIndex == 0) ? cpCount - 1 : 0); i != cpIndex + incr; i += incr) - points[count++] = stroke->getControlPoint(i); - TThickPoint tp(p, points[count - 1].thick); - points[count++] = 0.5 * (stroke->getControlPoint(cpIndex) + tp); - points[count++] = tp; + TStroke *ret; + int cpCount = stroke->getControlPointCount(); + int count = 0; + std::vector points(cpCount + 2); + int i, incr = (cpIndex == 0) ? -1 : 1; + for (i = ((cpIndex == 0) ? cpCount - 1 : 0); i != cpIndex + incr; i += incr) + points[count++] = stroke->getControlPoint(i); + TThickPoint tp(p, points[count - 1].thick); + points[count++] = 0.5 * (stroke->getControlPoint(cpIndex) + tp); + points[count++] = tp; - TStroke *newStroke = new TStroke(points); - newStroke->setStyle(stroke->getStyle()); - newStroke->outlineOptions() = stroke->outlineOptions(); - ret = newStroke; - std::list oldEdgeList, emptyList; + TStroke *newStroke = new TStroke(points); + newStroke->setStyle(stroke->getStyle()); + newStroke->outlineOptions() = stroke->outlineOptions(); + ret = newStroke; + std::list oldEdgeList, emptyList; - if (m_computedAlmostOnce) - computeEdgeList(newStroke, m_strokes[index]->m_edgeList, cpIndex == 0, emptyList, false, oldEdgeList); + if (m_computedAlmostOnce) + computeEdgeList(newStroke, m_strokes[index]->m_edgeList, cpIndex == 0, + emptyList, false, oldEdgeList); - std::vector toBeDeleted; - toBeDeleted.push_back(index); - removeStrokes(toBeDeleted, true, false); + std::vector toBeDeleted; + toBeDeleted.push_back(index); + removeStrokes(toBeDeleted, true, false); - //removeStroke(index, false); + // removeStroke(index, false); - insertStrokeAt(new VIStroke(newStroke, groupId), index, false); + insertStrokeAt(new VIStroke(newStroke, groupId), index, false); - if (m_computedAlmostOnce) { - computeRegions(); - transferColors(oldEdgeList, m_strokes[index]->m_edgeList, true, false, true); - } - return m_strokes[index]; + if (m_computedAlmostOnce) { + computeRegions(); + transferColors(oldEdgeList, m_strokes[index]->m_edgeList, true, false, + true); + } + return m_strokes[index]; } //----------------------------------------------------------------------------- -VIStroke *TVectorImage::Imp::joinStroke(int index1, int index2, int cpIndex1, int cpIndex2) -{ - assert(m_strokes[index1]->m_groupId == m_strokes[index2]->m_groupId); - - TGroupId groupId = m_strokes[index1]->m_groupId; - - TStroke *stroke1 = m_strokes[index1]->m_s; - TStroke *stroke2 = m_strokes[index2]->m_s; - //TStroke* ret; - int cpCount1 = stroke1->getControlPointCount(); - int cpCount2 = stroke2->getControlPointCount(); - int styleId = stroke1->getStyle(); - - int count = 0; - std::vector points(cpCount1 + ((index1 != index2) ? cpCount2 : 1) + 1); - int i, incr = (cpIndex1 == 0) ? -1 : 1; - for (i = ((cpIndex1 == 0) ? cpCount1 - 1 : 0); i != cpIndex1 + incr; i += incr) - points[count++] = stroke1->getControlPoint(i); - points[count++] = 0.5 * (stroke1->getControlPoint(cpIndex1) + stroke2->getControlPoint(cpIndex2)); - if (index1 != index2) { - incr = (cpIndex2 == 0) ? 1 : -1; - for (i = cpIndex2; i != ((cpIndex2 == 0) ? cpCount2 - 1 : 0) + incr; i += incr) - points[count++] = stroke2->getControlPoint(i); - } else - points[count++] = stroke2->getControlPoint(cpIndex2); - - TStroke *newStroke = new TStroke(points); - newStroke->setStyle(styleId); - newStroke->outlineOptions() = stroke1->outlineOptions(); - //ret = newStroke; - if (index1 == index2) - newStroke->setSelfLoop(); - std::list oldEdgeList, emptyList; - - computeEdgeList(newStroke, m_strokes[index1]->m_edgeList, cpIndex1 == 0, - (index1 != index2) ? m_strokes[index2]->m_edgeList : emptyList, - cpIndex2 == 0, oldEdgeList); - - std::vector toBeDeleted; - toBeDeleted.push_back(index1); - if (index1 != index2) - toBeDeleted.push_back(index2); - removeStrokes(toBeDeleted, true, false); - - insertStrokeAt(new VIStroke(newStroke, groupId), index1, false); - computeRegions(); - transferColors(oldEdgeList, m_strokes[index1]->m_edgeList, true, false, true); - return m_strokes[index1]; -} - -//----------------------------------------------------------------------------- - -VIStroke *TVectorImage::Imp::joinStrokeSmoothly(int index1, int index2, int cpIndex1, int cpIndex2) -{ - assert(m_strokes[index1]->m_groupId == m_strokes[index2]->m_groupId); - - TGroupId groupId = m_strokes[index1]->m_groupId; - - TStroke *stroke1 = m_strokes[index1]->m_s; - TStroke *stroke2 = m_strokes[index2]->m_s; - TStroke *ret; - int cpCount1 = stroke1->getControlPointCount(); - int cpCount2 = stroke2->getControlPointCount(); - int styleId = stroke1->getStyle(); - - int qCount1 = stroke1->getChunkCount(); - int qCount2 = stroke2->getChunkCount(); - const TThickQuadratic *q1 = stroke1->getChunk(cpIndex1 == 0 ? 0 : qCount1 - 1); - const TThickQuadratic *q2 = stroke2->getChunk(cpIndex2 == 0 ? 0 : qCount2 - 1); - - double len1 = q1->getLength(); - assert(len1 >= 0); - if (len1 <= 0) - len1 = 0; - double w1 = exp(-len1 * 0.01); - - double len2 = q2->getLength(); - assert(len2 >= 0); - if (len2 <= 0) - len2 = 0; - double w2 = exp(-len2 * 0.01); - - TThickPoint extreme1 = cpIndex1 == 0 ? q1->getThickP0() : q1->getThickP2(); - TThickPoint extreme2 = cpIndex2 == 0 ? q2->getThickP0() : q2->getThickP2(); - - TThickPoint m1 = q1->getThickP1(); - TThickPoint m2 = q2->getThickP1(); - - TThickPoint p1 = extreme1 * (1 - w1) + m1 * w1; - TThickPoint p2 = extreme2 * (1 - w2) + m2 * w2; - - TThickPoint middleP = (p1 + p2) * 0.5; - - double angle = fabs(cross(normalize(m1 - middleP), normalize(m2 - middleP))); - if (angle < 0.05) - middleP = (m1 + m2) * 0.5; - - stroke1->setControlPoint(cpIndex1, middleP); - if (isAlmostZero(len1)) { - if (cpIndex1 == 0) - stroke1->setControlPoint(1, middleP * 0.1 + stroke1->getControlPoint(2) * 0.9); - else - stroke1->setControlPoint(cpCount1 - 2, middleP * 0.1 + stroke1->getControlPoint(cpCount1 - 3) * 0.9); - } - - stroke2->setControlPoint(cpIndex2, middleP); - if (isAlmostZero(len2)) { - if (cpIndex2 == 0) - stroke2->setControlPoint(1, middleP * 0.1 + stroke2->getControlPoint(2) * 0.9); - else - stroke2->setControlPoint(cpCount2 - 2, middleP * 0.1 + stroke2->getControlPoint(cpCount2 - 3) * 0.9); - } - - if (stroke1 == stroke2) { - std::list oldEdgeList, emptyList; - computeEdgeList(stroke1, m_strokes[index1]->m_edgeList, cpIndex1 == 0, - emptyList, false, oldEdgeList); - eraseIntersection(index1); - m_strokes[index1]->m_isNewForFill = true; - stroke1->setSelfLoop(); - computeRegions(); - transferColors(oldEdgeList, m_strokes[index1]->m_edgeList, true, false, true); - return m_strokes[index1]; - //nundo->m_newStroke=new TStroke(*stroke1); - //nundo->m_newStrokeId=stroke1->getId(); - } - - std::vector points; - points.reserve(cpCount1 + cpCount2 - 1); - - int incr = (cpIndex1) ? 1 : -1; - int stop = cpIndex1; - - int i = cpCount1 - 1 - cpIndex1; - for (; i != stop; i += incr) - points.push_back(stroke1->getControlPoint(i)); - - incr = (cpIndex2) ? -1 : 1; - stop = cpCount2 - 1 - cpIndex2; - - for (i = cpIndex2; i != stop; i += incr) - points.push_back(stroke2->getControlPoint(i)); - - points.push_back(stroke2->getControlPoint(stop)); - - TStroke *newStroke = new TStroke(points); - newStroke->setStyle(styleId); - newStroke->outlineOptions() = stroke1->outlineOptions(); - ret = newStroke; - //nundo->m_newStroke=new TStroke(*newStroke); - //nundo->m_newStrokeId=newStroke->getId(); - std::list oldEdgeList; - //ofstream os("c:\\temp\\edges.txt"); - - //printEdges(os, "****edgelist1", getPalette(), m_imp->m_strokes[index1]->m_edgeList); - //printEdges(os, "****edgelist2", getPalette(), m_imp->m_strokes[index2]->m_edgeList); - - computeEdgeList(newStroke, m_strokes[index1]->m_edgeList, cpIndex1 == 0, - m_strokes[index2]->m_edgeList, cpIndex2 == 0, oldEdgeList); - //printEdges(os, "****edgelist", getPalette(), oldEdgeList); - - std::vector toBeDeleted; - toBeDeleted.push_back(index1); - toBeDeleted.push_back(index2); - removeStrokes(toBeDeleted, true, false); - - insertStrokeAt(new VIStroke(newStroke, groupId), index1); - computeRegions(); - transferColors(oldEdgeList, m_strokes[index1]->m_edgeList, true, false, true); +VIStroke *TVectorImage::Imp::joinStroke(int index1, int index2, int cpIndex1, + int cpIndex2) { + assert(m_strokes[index1]->m_groupId == m_strokes[index2]->m_groupId); + + TGroupId groupId = m_strokes[index1]->m_groupId; + + TStroke *stroke1 = m_strokes[index1]->m_s; + TStroke *stroke2 = m_strokes[index2]->m_s; + // TStroke* ret; + int cpCount1 = stroke1->getControlPointCount(); + int cpCount2 = stroke2->getControlPointCount(); + int styleId = stroke1->getStyle(); + + int count = 0; + std::vector points(cpCount1 + + ((index1 != index2) ? cpCount2 : 1) + 1); + int i, incr = (cpIndex1 == 0) ? -1 : 1; + for (i = ((cpIndex1 == 0) ? cpCount1 - 1 : 0); i != cpIndex1 + incr; + i += incr) + points[count++] = stroke1->getControlPoint(i); + points[count++] = 0.5 * (stroke1->getControlPoint(cpIndex1) + + stroke2->getControlPoint(cpIndex2)); + if (index1 != index2) { + incr = (cpIndex2 == 0) ? 1 : -1; + for (i = cpIndex2; i != ((cpIndex2 == 0) ? cpCount2 - 1 : 0) + incr; + i += incr) + points[count++] = stroke2->getControlPoint(i); + } else + points[count++] = stroke2->getControlPoint(cpIndex2); + + TStroke *newStroke = new TStroke(points); + newStroke->setStyle(styleId); + newStroke->outlineOptions() = stroke1->outlineOptions(); + // ret = newStroke; + if (index1 == index2) newStroke->setSelfLoop(); + std::list oldEdgeList, emptyList; + + computeEdgeList( + newStroke, m_strokes[index1]->m_edgeList, cpIndex1 == 0, + (index1 != index2) ? m_strokes[index2]->m_edgeList : emptyList, + cpIndex2 == 0, oldEdgeList); + + std::vector toBeDeleted; + toBeDeleted.push_back(index1); + if (index1 != index2) toBeDeleted.push_back(index2); + removeStrokes(toBeDeleted, true, false); + + insertStrokeAt(new VIStroke(newStroke, groupId), index1, false); + computeRegions(); + transferColors(oldEdgeList, m_strokes[index1]->m_edgeList, true, false, true); + return m_strokes[index1]; +} + +//----------------------------------------------------------------------------- + +VIStroke *TVectorImage::Imp::joinStrokeSmoothly(int index1, int index2, + int cpIndex1, int cpIndex2) { + assert(m_strokes[index1]->m_groupId == m_strokes[index2]->m_groupId); + + TGroupId groupId = m_strokes[index1]->m_groupId; + + TStroke *stroke1 = m_strokes[index1]->m_s; + TStroke *stroke2 = m_strokes[index2]->m_s; + TStroke *ret; + int cpCount1 = stroke1->getControlPointCount(); + int cpCount2 = stroke2->getControlPointCount(); + int styleId = stroke1->getStyle(); + + int qCount1 = stroke1->getChunkCount(); + int qCount2 = stroke2->getChunkCount(); + const TThickQuadratic *q1 = + stroke1->getChunk(cpIndex1 == 0 ? 0 : qCount1 - 1); + const TThickQuadratic *q2 = + stroke2->getChunk(cpIndex2 == 0 ? 0 : qCount2 - 1); + + double len1 = q1->getLength(); + assert(len1 >= 0); + if (len1 <= 0) len1 = 0; + double w1 = exp(-len1 * 0.01); + + double len2 = q2->getLength(); + assert(len2 >= 0); + if (len2 <= 0) len2 = 0; + double w2 = exp(-len2 * 0.01); + + TThickPoint extreme1 = cpIndex1 == 0 ? q1->getThickP0() : q1->getThickP2(); + TThickPoint extreme2 = cpIndex2 == 0 ? q2->getThickP0() : q2->getThickP2(); + + TThickPoint m1 = q1->getThickP1(); + TThickPoint m2 = q2->getThickP1(); + + TThickPoint p1 = extreme1 * (1 - w1) + m1 * w1; + TThickPoint p2 = extreme2 * (1 - w2) + m2 * w2; + + TThickPoint middleP = (p1 + p2) * 0.5; + + double angle = fabs(cross(normalize(m1 - middleP), normalize(m2 - middleP))); + if (angle < 0.05) middleP = (m1 + m2) * 0.5; + + stroke1->setControlPoint(cpIndex1, middleP); + if (isAlmostZero(len1)) { + if (cpIndex1 == 0) + stroke1->setControlPoint( + 1, middleP * 0.1 + stroke1->getControlPoint(2) * 0.9); + else + stroke1->setControlPoint( + cpCount1 - 2, + middleP * 0.1 + stroke1->getControlPoint(cpCount1 - 3) * 0.9); + } + + stroke2->setControlPoint(cpIndex2, middleP); + if (isAlmostZero(len2)) { + if (cpIndex2 == 0) + stroke2->setControlPoint( + 1, middleP * 0.1 + stroke2->getControlPoint(2) * 0.9); + else + stroke2->setControlPoint( + cpCount2 - 2, + middleP * 0.1 + stroke2->getControlPoint(cpCount2 - 3) * 0.9); + } - return m_strokes[index1]; + if (stroke1 == stroke2) { + std::list oldEdgeList, emptyList; + computeEdgeList(stroke1, m_strokes[index1]->m_edgeList, cpIndex1 == 0, + emptyList, false, oldEdgeList); + eraseIntersection(index1); + m_strokes[index1]->m_isNewForFill = true; + stroke1->setSelfLoop(); + computeRegions(); + transferColors(oldEdgeList, m_strokes[index1]->m_edgeList, true, false, + true); + return m_strokes[index1]; + // nundo->m_newStroke=new TStroke(*stroke1); + // nundo->m_newStrokeId=stroke1->getId(); + } + + std::vector points; + points.reserve(cpCount1 + cpCount2 - 1); + + int incr = (cpIndex1) ? 1 : -1; + int stop = cpIndex1; + + int i = cpCount1 - 1 - cpIndex1; + for (; i != stop; i += incr) points.push_back(stroke1->getControlPoint(i)); + + incr = (cpIndex2) ? -1 : 1; + stop = cpCount2 - 1 - cpIndex2; + + for (i = cpIndex2; i != stop; i += incr) + points.push_back(stroke2->getControlPoint(i)); + + points.push_back(stroke2->getControlPoint(stop)); - // TUndoManager::manager()->add(nundo); + TStroke *newStroke = new TStroke(points); + newStroke->setStyle(styleId); + newStroke->outlineOptions() = stroke1->outlineOptions(); + ret = newStroke; + // nundo->m_newStroke=new TStroke(*newStroke); + // nundo->m_newStrokeId=newStroke->getId(); + std::list oldEdgeList; + // ofstream os("c:\\temp\\edges.txt"); + + // printEdges(os, "****edgelist1", getPalette(), + // m_imp->m_strokes[index1]->m_edgeList); + // printEdges(os, "****edgelist2", getPalette(), + // m_imp->m_strokes[index2]->m_edgeList); + + computeEdgeList(newStroke, m_strokes[index1]->m_edgeList, cpIndex1 == 0, + m_strokes[index2]->m_edgeList, cpIndex2 == 0, oldEdgeList); + // printEdges(os, "****edgelist", getPalette(), oldEdgeList); + + std::vector toBeDeleted; + toBeDeleted.push_back(index1); + toBeDeleted.push_back(index2); + removeStrokes(toBeDeleted, true, false); + + insertStrokeAt(new VIStroke(newStroke, groupId), index1); + computeRegions(); + transferColors(oldEdgeList, m_strokes[index1]->m_edgeList, true, false, true); + + return m_strokes[index1]; + + // TUndoManager::manager()->add(nundo); } //----------------------------------------------------------------------------- -VIStroke *TVectorImage::joinStroke(int index1, int index2, int cpIndex1, int cpIndex2, bool isSmooth) +VIStroke *TVectorImage::joinStroke(int index1, int index2, int cpIndex1, + int cpIndex2, bool isSmooth) { + int finalStyle = -1; + + if (index1 > index2) { + finalStyle = getStroke(index1)->getStyle(); + tswap(index1, index2); + tswap(cpIndex1, cpIndex2); + } + /* +if (index1==index2) //selfLoop! { - int finalStyle = -1; - - if (index1 > index2) { - finalStyle = getStroke(index1)->getStyle(); - tswap(index1, index2); - tswap(cpIndex1, cpIndex2); - } - /* - if (index1==index2) //selfLoop! - { - if (index1>0 && index1<(int)getStrokeCount()-1 && - !getStroke(index1-1)->isSelfLoop() && - !getStroke(index1+1)->isSelfLoop()) - { - for (UINT i = index1+2; iisSelfLoop(); i++) - ; - moveStroke(index1, i-1); - index1 = index2 = i-1; - } - } - */ - VIStroke *ret; - if (isSmooth) - ret = m_imp->joinStrokeSmoothly(index1, index2, cpIndex1, cpIndex2); - else - ret = m_imp->joinStroke(index1, index2, cpIndex1, cpIndex2); +if (index1>0 && index1<(int)getStrokeCount()-1 && + !getStroke(index1-1)->isSelfLoop() && + !getStroke(index1+1)->isSelfLoop()) +{ +for (UINT i = index1+2; iisSelfLoop(); i++) + ; +moveStroke(index1, i-1); +index1 = index2 = i-1; +} +} +*/ + VIStroke *ret; + if (isSmooth) + ret = m_imp->joinStrokeSmoothly(index1, index2, cpIndex1, cpIndex2); + else + ret = m_imp->joinStroke(index1, index2, cpIndex1, cpIndex2); - if (finalStyle != -1) - getStroke(index1)->setStyle(finalStyle); - return ret; + if (finalStyle != -1) getStroke(index1)->setStyle(finalStyle); + return ret; } //----------------------------------------------------------------------------- -VIStroke *TVectorImage::extendStroke(int index, const TThickPoint &p, int cpIndex, bool isSmooth) -{ - - if (isSmooth) - return m_imp->extendStrokeSmoothly(index, p, cpIndex); - else - return m_imp->extendStroke(index, p, cpIndex); +VIStroke *TVectorImage::extendStroke(int index, const TThickPoint &p, + int cpIndex, bool isSmooth) { + if (isSmooth) + return m_imp->extendStrokeSmoothly(index, p, cpIndex); + else + return m_imp->extendStroke(index, p, cpIndex); } //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -TInputStreamInterface &TInputStreamInterface::operator>>(TPixel32 &pixel) -{ - return *this >> pixel.r >> pixel.g >> pixel.b >> pixel.m; +TInputStreamInterface &TInputStreamInterface::operator>>(TPixel32 &pixel) { + return *this >> pixel.r >> pixel.g >> pixel.b >> pixel.m; } //------------------------------------------------------------------- -TOutputStreamInterface &TOutputStreamInterface::operator<<(const TPixel32 &pixel) -{ - return *this << pixel.r << pixel.g << pixel.b << pixel.m; +TOutputStreamInterface &TOutputStreamInterface::operator<<( + const TPixel32 &pixel) { + return *this << pixel.r << pixel.g << pixel.b << pixel.m; } //------------------------------------------------------------------- -void TVectorImage::setAutocloseTolerance(double val) -{ - m_imp->m_autocloseTolerance = val; +void TVectorImage::setAutocloseTolerance(double val) { + m_imp->m_autocloseTolerance = val; } //------------------------------------------------------------------- -double TVectorImage::getAutocloseTolerance() const -{ - return m_imp->m_autocloseTolerance; +double TVectorImage::getAutocloseTolerance() const { + return m_imp->m_autocloseTolerance; } //------------------------------------------------------------------- -TThread::Mutex *TVectorImage::getMutex() const -{ - return m_imp->m_mutex; -} +TThread::Mutex *TVectorImage::getMutex() const { return m_imp->m_mutex; } //------------------------------------------------------------------- -void TVectorImage::areaFill(TStroke *stroke, int index, bool m_onlyUnfilled) -{ - TVectorImage v; - v.addStroke(stroke); - v.findRegions(); +void TVectorImage::areaFill(TStroke *stroke, int index, bool m_onlyUnfilled) { + TVectorImage v; + v.addStroke(stroke); + v.findRegions(); - for (UINT i = 0; i < v.getRegionCount(); i++) - for (UINT j = 0; j < getRegionCount(); j++) { - if (m_imp->m_insideGroup != TGroupId() && !m_imp->m_insideGroup.isParentOf(m_imp->m_strokes[getRegion(j)->getEdge(0)->m_index]->m_groupId)) - continue; + for (UINT i = 0; i < v.getRegionCount(); i++) + for (UINT j = 0; j < getRegionCount(); j++) { + if (m_imp->m_insideGroup != TGroupId() && + !m_imp->m_insideGroup.isParentOf( + m_imp->m_strokes[getRegion(j)->getEdge(0)->m_index]->m_groupId)) + continue; - if (v.getRegion(i)->contains(*getRegion(j))) - getRegion(j)->setStyle(index); - } + if (v.getRegion(i)->contains(*getRegion(j))) + getRegion(j)->setStyle(index); + } - v.removeStroke(0); + v.removeStroke(0); } -VIStroke *cloneVIStroke(VIStroke *vs) -{ - return new VIStroke(*vs); -} +VIStroke *cloneVIStroke(VIStroke *vs) { return new VIStroke(*vs); } -void deleteVIStroke(VIStroke *vs) -{ - delete vs; - vs = 0; +void deleteVIStroke(VIStroke *vs) { + delete vs; + vs = 0; } //------------------------------------------------------------------- -bool TVectorImage::sameSubGroup(int index0, int index1) const -{ - if (index0 < 0 || index1 < 0) - return 0; - return m_imp->m_strokes[index0]->m_groupId.getCommonParentDepth(m_imp->m_strokes[index1]->m_groupId) > m_imp->m_insideGroup.getDepth(); +bool TVectorImage::sameSubGroup(int index0, int index1) const { + if (index0 < 0 || index1 < 0) return 0; + return m_imp->m_strokes[index0]->m_groupId.getCommonParentDepth( + m_imp->m_strokes[index1]->m_groupId) > + m_imp->m_insideGroup.getDepth(); } //------------------------------------------------------------------- -int TVectorImage::getCommonGroupDepth(int index0, int index1) const -{ - if (index0 < 0 || index1 < 0) - return 0; - return m_imp->m_strokes[index0]->m_groupId.getCommonParentDepth(m_imp->m_strokes[index1]->m_groupId); +int TVectorImage::getCommonGroupDepth(int index0, int index1) const { + if (index0 < 0 || index1 < 0) return 0; + return m_imp->m_strokes[index0]->m_groupId.getCommonParentDepth( + m_imp->m_strokes[index1]->m_groupId); } //------------------------------------------------------------------- -int TVectorImage::ungroup(int fromIndex) -{ - m_imp->m_insideGroup = TGroupId(); +int TVectorImage::ungroup(int fromIndex) { + m_imp->m_insideGroup = TGroupId(); - assert(m_imp->m_strokes[fromIndex]->m_groupId.isGrouped() != 0); - std::vector changedStrokes; + assert(m_imp->m_strokes[fromIndex]->m_groupId.isGrouped() != 0); + std::vector changedStrokes; - int toIndex = fromIndex + 1; + int toIndex = fromIndex + 1; - while (toIndex < (int)m_imp->m_strokes.size() && m_imp->m_strokes[fromIndex]->m_groupId.getCommonParentDepth(m_imp->m_strokes[toIndex]->m_groupId) >= 1) - toIndex++; + while (toIndex < (int)m_imp->m_strokes.size() && + m_imp->m_strokes[fromIndex]->m_groupId.getCommonParentDepth( + m_imp->m_strokes[toIndex]->m_groupId) >= 1) + toIndex++; - toIndex--; + toIndex--; - TGroupId groupId; + TGroupId groupId; - if (fromIndex > 0 && m_imp->m_strokes[fromIndex - 1]->m_groupId.isGrouped(true) != 0) - groupId = m_imp->m_strokes[fromIndex - 1]->m_groupId; - else if (toIndex < (int)m_imp->m_strokes.size() - 1 && m_imp->m_strokes[toIndex + 1]->m_groupId.isGrouped(true) != 0) - groupId = m_imp->m_strokes[toIndex + 1]->m_groupId; - else - groupId = TGroupId(this, true); + if (fromIndex > 0 && + m_imp->m_strokes[fromIndex - 1]->m_groupId.isGrouped(true) != 0) + groupId = m_imp->m_strokes[fromIndex - 1]->m_groupId; + else if (toIndex < (int)m_imp->m_strokes.size() - 1 && + m_imp->m_strokes[toIndex + 1]->m_groupId.isGrouped(true) != 0) + groupId = m_imp->m_strokes[toIndex + 1]->m_groupId; + else + groupId = TGroupId(this, true); - for (int i = fromIndex; i <= toIndex || (i < (int)m_imp->m_strokes.size() && m_imp->m_strokes[i]->m_groupId.isGrouped(true) != 0); i++) { - m_imp->m_strokes[i]->m_groupId.ungroup(groupId); - changedStrokes.push_back(i); - } + for (int i = fromIndex; + i <= toIndex || (i < (int)m_imp->m_strokes.size() && + m_imp->m_strokes[i]->m_groupId.isGrouped(true) != 0); + i++) { + m_imp->m_strokes[i]->m_groupId.ungroup(groupId); + changedStrokes.push_back(i); + } - notifyChangedStrokes(changedStrokes, std::vector(), false); + notifyChangedStrokes(changedStrokes, std::vector(), false); - return toIndex - fromIndex + 1; + return toIndex - fromIndex + 1; } //------------------------------------------------------------------- -bool TVectorImage::isEnteredGroupStroke(int index) const -{ - return m_imp->m_insideGroup.isParentOf(getVIStroke(index)->m_groupId); +bool TVectorImage::isEnteredGroupStroke(int index) const { + return m_imp->m_insideGroup.isParentOf(getVIStroke(index)->m_groupId); } //------------------------------------------------------------------- -bool TVectorImage::enterGroup(int index) -{ - VIStroke *vs = getVIStroke(index); +bool TVectorImage::enterGroup(int index) { + VIStroke *vs = getVIStroke(index); - if (!vs->m_groupId.isGrouped()) - return false; + if (!vs->m_groupId.isGrouped()) return false; - int newDepth = vs->m_groupId.getCommonParentDepth(m_imp->m_insideGroup) + 1; + int newDepth = vs->m_groupId.getCommonParentDepth(m_imp->m_insideGroup) + 1; - TGroupId newGroupId = vs->m_groupId; + TGroupId newGroupId = vs->m_groupId; - while (newGroupId.getDepth() > newDepth) - newGroupId = newGroupId.getParent(); + while (newGroupId.getDepth() > newDepth) newGroupId = newGroupId.getParent(); - if (newGroupId == m_imp->m_insideGroup) - return false; + if (newGroupId == m_imp->m_insideGroup) return false; - m_imp->m_insideGroup = newGroupId; - return true; + m_imp->m_insideGroup = newGroupId; + return true; } //------------------------------------------------------------------- -int TVectorImage::exitGroup() -{ - if (m_imp->m_insideGroup == TGroupId()) - return -1; +int TVectorImage::exitGroup() { + if (m_imp->m_insideGroup == TGroupId()) return -1; - int i, ret = -1; - for (i = 0; i < (int)m_imp->m_strokes.size(); i++) { - if (m_imp->m_strokes[i]->m_groupId.getCommonParentDepth(m_imp->m_insideGroup) >= m_imp->m_insideGroup.getDepth()) { - ret = i; - break; - } - } + int i, ret = -1; + for (i = 0; i < (int)m_imp->m_strokes.size(); i++) { + if (m_imp->m_strokes[i]->m_groupId.getCommonParentDepth( + m_imp->m_insideGroup) >= m_imp->m_insideGroup.getDepth()) { + ret = i; + break; + } + } - assert(i != m_imp->m_strokes.size()); + assert(i != m_imp->m_strokes.size()); - m_imp->m_insideGroup = m_imp->m_insideGroup.getParent(); - return ret; + m_imp->m_insideGroup = m_imp->m_insideGroup.getParent(); + return ret; } //------------------------------------------------------------------- -void TVectorImage::group(int fromIndex, int count) -{ - int i; - assert(count >= 0); - std::vector changedStroke; +void TVectorImage::group(int fromIndex, int count) { + int i; + assert(count >= 0); + std::vector changedStroke; - TGroupId parent = TGroupId(this, false); + TGroupId parent = TGroupId(this, false); - for (i = 0; i < count; i++) { - m_imp->m_strokes[fromIndex + i]->m_groupId = TGroupId(parent, m_imp->m_strokes[fromIndex + i]->m_groupId); - changedStroke.push_back(fromIndex + i); - } + for (i = 0; i < count; i++) { + m_imp->m_strokes[fromIndex + i]->m_groupId = + TGroupId(parent, m_imp->m_strokes[fromIndex + i]->m_groupId); + changedStroke.push_back(fromIndex + i); + } - m_imp->rearrangeMultiGroup(); //see method's comment + m_imp->rearrangeMultiGroup(); // see method's comment - m_imp->regroupGhosts(changedStroke); + m_imp->regroupGhosts(changedStroke); - notifyChangedStrokes(changedStroke, std::vector(), false); + notifyChangedStrokes(changedStroke, std::vector(), false); #ifdef _DEBUG - m_imp->checkGroups(); + m_imp->checkGroups(); #endif } //------------------------------------------------------------------- -int TVectorImage::getGroupDepth(UINT index) const -{ - assert(index < m_imp->m_strokes.size()); +int TVectorImage::getGroupDepth(UINT index) const { + assert(index < m_imp->m_strokes.size()); - return m_imp->m_strokes[index]->m_groupId.isGrouped(); + return m_imp->m_strokes[index]->m_groupId.isGrouped(); } //------------------------------------------------------------------- -int TVectorImage::areDifferentGroup(UINT index1, bool isRegion1, UINT index2, bool isRegion2) const -{ - return m_imp->areDifferentGroup(index1, isRegion1, index2, isRegion2); +int TVectorImage::areDifferentGroup(UINT index1, bool isRegion1, UINT index2, + bool isRegion2) const { + return m_imp->areDifferentGroup(index1, isRegion1, index2, isRegion2); } //------------------------------------------------------------------- /*this method is tricky. it is not allow to have not-adiacent strokes of same group. -but it can happen when you group some already-grouped strokes creating sub-groups. +but it can happen when you group some already-grouped strokes creating +sub-groups. example: vi made of 5 strokes, before grouping (N=no group) N @@ -2643,98 +2598,96 @@ so after calling rearrangeMultiGroup the vi became: */ -void TVectorImage::Imp::rearrangeMultiGroup() -{ - UINT i, j, k; - if (m_strokes.size() <= 0) - return; - for (i = 0; i < m_strokes.size() - 1; i++) { - if (m_strokes[i]->m_groupId.isGrouped() && m_strokes[i + 1]->m_groupId.isGrouped() && m_strokes[i]->m_groupId != m_strokes[i + 1]->m_groupId) { - TGroupId &prevId = m_strokes[i]->m_groupId; - TGroupId &idToMove = m_strokes[i + 1]->m_groupId; - for (j = i + 1; j < m_strokes.size() && m_strokes[j]->m_groupId == idToMove; j++) - ; - if (j != m_strokes.size()) { - j--; //now range i+1-j contains the strokes to be moved. - //let's compute where to move them (after last - for (k = j; k < m_strokes.size() && m_strokes[k]->m_groupId != prevId; k++) - ; - if (k < m_strokes.size()) { - for (; k < m_strokes.size() && m_strokes[k]->m_groupId == prevId; k++) - ; - moveStrokes(i + 1, j - i, k, false); - rearrangeMultiGroup(); - return; - } - } - } - } +void TVectorImage::Imp::rearrangeMultiGroup() { + UINT i, j, k; + if (m_strokes.size() <= 0) return; + for (i = 0; i < m_strokes.size() - 1; i++) { + if (m_strokes[i]->m_groupId.isGrouped() && + m_strokes[i + 1]->m_groupId.isGrouped() && + m_strokes[i]->m_groupId != m_strokes[i + 1]->m_groupId) { + TGroupId &prevId = m_strokes[i]->m_groupId; + TGroupId &idToMove = m_strokes[i + 1]->m_groupId; + for (j = i + 1; + j < m_strokes.size() && m_strokes[j]->m_groupId == idToMove; j++) + ; + if (j != m_strokes.size()) { + j--; // now range i+1-j contains the strokes to be moved. + // let's compute where to move them (after last + for (k = j; k < m_strokes.size() && m_strokes[k]->m_groupId != prevId; + k++) + ; + if (k < m_strokes.size()) { + for (; k < m_strokes.size() && m_strokes[k]->m_groupId == prevId; k++) + ; + moveStrokes(i + 1, j - i, k, false); + rearrangeMultiGroup(); + return; + } + } + } + } } //------------------------------------------------------------------- -int TVectorImage::Imp::areDifferentGroup(UINT index1, bool isRegion1, UINT index2, bool isRegion2) const -{ - TGroupId group1, group2; - - if (isRegion1) { - TRegion *r = m_regions[index1]; - for (UINT i = 0; i < r->getEdgeCount(); i++) - if (r->getEdge(i)->m_index >= 0) { - group1 = m_strokes[r->getEdge(i)->m_index]->m_groupId; - break; - } - } else - group1 = m_strokes[index1]->m_groupId; - if (isRegion2) { - TRegion *r = m_regions[index2]; - for (UINT i = 0; i < r->getEdgeCount(); i++) - if (r->getEdge(i)->m_index >= 0) { - group2 = m_strokes[r->getEdge(i)->m_index]->m_groupId; - break; - } - } else - group2 = m_strokes[index2]->m_groupId; - - if (!group1 && !group2) - return 0; - - if (group1 == group2) - return -1; - else - return group1.getCommonParentDepth(group2); +int TVectorImage::Imp::areDifferentGroup(UINT index1, bool isRegion1, + UINT index2, bool isRegion2) const { + TGroupId group1, group2; + + if (isRegion1) { + TRegion *r = m_regions[index1]; + for (UINT i = 0; i < r->getEdgeCount(); i++) + if (r->getEdge(i)->m_index >= 0) { + group1 = m_strokes[r->getEdge(i)->m_index]->m_groupId; + break; + } + } else + group1 = m_strokes[index1]->m_groupId; + if (isRegion2) { + TRegion *r = m_regions[index2]; + for (UINT i = 0; i < r->getEdgeCount(); i++) + if (r->getEdge(i)->m_index >= 0) { + group2 = m_strokes[r->getEdge(i)->m_index]->m_groupId; + break; + } + } else + group2 = m_strokes[index2]->m_groupId; + + if (!group1 && !group2) return 0; + + if (group1 == group2) + return -1; + else + return group1.getCommonParentDepth(group2); } //------------------------------------------------------------------- -int TGroupId::getCommonParentDepth(const TGroupId &id) const -{ - int size1 = m_id.size(); - int size2 = id.m_id.size(); - int count; +int TGroupId::getCommonParentDepth(const TGroupId &id) const { + int size1 = m_id.size(); + int size2 = id.m_id.size(); + int count; - for (count = 0; count < std::min(size1, size2); count++) - if (m_id[size1 - count - 1] != id.m_id[size2 - count - 1]) - break; + for (count = 0; count < std::min(size1, size2); count++) + if (m_id[size1 - count - 1] != id.m_id[size2 - count - 1]) break; - return count; + return count; } //------------------------------------------------------------------- -TGroupId::TGroupId(const TGroupId &parent, const TGroupId &id) -{ - assert(parent.m_id[0] > 0); - assert(id.m_id.size() > 0); - - if (id.isGrouped(true) != 0) - m_id.push_back(parent.m_id[0]); - else { - m_id = id.m_id; - int i; - for (i = 0; i < (int)parent.m_id.size(); i++) - m_id.push_back(parent.m_id[i]); - } +TGroupId::TGroupId(const TGroupId &parent, const TGroupId &id) { + assert(parent.m_id[0] > 0); + assert(id.m_id.size() > 0); + + if (id.isGrouped(true) != 0) + m_id.push_back(parent.m_id[0]); + else { + m_id = id.m_id; + int i; + for (i = 0; i < (int)parent.m_id.size(); i++) + m_id.push_back(parent.m_id[i]); + } } /* @@ -2745,392 +2698,382 @@ return m_id.back()==id.m_id.back(); } */ -TGroupId TGroupId::getParent() const -{ - if (m_id.size() <= 1) - return TGroupId(); +TGroupId TGroupId::getParent() const { + if (m_id.size() <= 1) return TGroupId(); - TGroupId ret = *this; - ret.m_id.erase(ret.m_id.begin()); - return ret; + TGroupId ret = *this; + ret.m_id.erase(ret.m_id.begin()); + return ret; } -void TGroupId::ungroup(const TGroupId &id) -{ - assert(id.isGrouped(true) != 0); - assert(!m_id.empty()); +void TGroupId::ungroup(const TGroupId &id) { + assert(id.isGrouped(true) != 0); + assert(!m_id.empty()); - if (m_id.size() == 1) - m_id[0] = id.m_id[0]; - else - m_id.pop_back(); + if (m_id.size() == 1) + m_id[0] = id.m_id[0]; + else + m_id.pop_back(); } -bool TGroupId::operator==(const TGroupId &id) const -{ - if (m_id.size() != id.m_id.size()) - return false; - UINT i; - for (i = 0; i < m_id.size(); i++) - if (m_id[i] != id.m_id[i]) - return false; +bool TGroupId::operator==(const TGroupId &id) const { + if (m_id.size() != id.m_id.size()) return false; + UINT i; + for (i = 0; i < m_id.size(); i++) + if (m_id[i] != id.m_id[i]) return false; - return true; + return true; } -bool TGroupId::operator<(const TGroupId &id) const -{ - assert(!m_id.empty() && !id.m_id.empty()); - int size1 = m_id.size(); - int size2 = id.m_id.size(); - int i; - for (i = 0; i < std::min(size1, size2); i++) - if (m_id[size1 - i - 1] != id.m_id[size2 - i - 1]) - return m_id[size1 - i - 1] < id.m_id[size2 - i - 1]; +bool TGroupId::operator<(const TGroupId &id) const { + assert(!m_id.empty() && !id.m_id.empty()); + int size1 = m_id.size(); + int size2 = id.m_id.size(); + int i; + for (i = 0; i < std::min(size1, size2); i++) + if (m_id[size1 - i - 1] != id.m_id[size2 - i - 1]) + return m_id[size1 - i - 1] < id.m_id[size2 - i - 1]; - return size1 < size2; + return size1 < size2; } //------------------------------------------------------------------- -int TGroupId::isGrouped(bool implicit) const -{ - assert(!m_id.empty()); - assert(m_id[0] != 0); - if (implicit) - return (m_id[0] < 0) ? 1 : 0; - else - return (m_id[0] > 0) ? m_id.size() : 0; +int TGroupId::isGrouped(bool implicit) const { + assert(!m_id.empty()); + assert(m_id[0] != 0); + if (implicit) + return (m_id[0] < 0) ? 1 : 0; + else + return (m_id[0] > 0) ? m_id.size() : 0; } //------------------------------------------------------------------- -TGroupId::TGroupId(TVectorImage *vi, bool isGhost) -{ - m_id.push_back((isGhost) ? -(++vi->m_imp->m_maxGhostGroupId) : ++vi->m_imp->m_maxGroupId); +TGroupId::TGroupId(TVectorImage *vi, bool isGhost) { + m_id.push_back((isGhost) ? -(++vi->m_imp->m_maxGhostGroupId) + : ++vi->m_imp->m_maxGroupId); } #ifdef _DEBUG -void TVectorImage::Imp::checkGroups() -{ - TGroupId currGroupId; - std::set groupSet; - std::set::iterator it; - UINT i = 0; - - while (i < m_strokes.size()) { - //assert(m_strokes[i]->m_groupId!=currGroupId); - //assert(i==0 || m_strokes[i-1]->m_groupId.isGrouped()!=m_strokes[i]->m_groupId.isGrouped()!=0 || - // (m_strokes[i]->m_groupId.isGrouped()!=0 && m_strokes[i-1]->m_groupId!=m_strokes[i]->m_groupId)); - - currGroupId = m_strokes[i]->m_groupId; - it = groupSet.find(currGroupId); - if (it != groupSet.end()) //esisteva gia un gruppo con questo id! - assert(!"errore: due gruppi con lo stesso id!"); - else - groupSet.insert(currGroupId); - - while (i < m_strokes.size() && m_strokes[i]->m_groupId == currGroupId) - i++; - } +void TVectorImage::Imp::checkGroups() { + TGroupId currGroupId; + std::set groupSet; + std::set::iterator it; + UINT i = 0; + + while (i < m_strokes.size()) { + // assert(m_strokes[i]->m_groupId!=currGroupId); + // assert(i==0 || + // m_strokes[i-1]->m_groupId.isGrouped()!=m_strokes[i]->m_groupId.isGrouped()!=0 + // || + // (m_strokes[i]->m_groupId.isGrouped()!=0 && + // m_strokes[i-1]->m_groupId!=m_strokes[i]->m_groupId)); + + currGroupId = m_strokes[i]->m_groupId; + it = groupSet.find(currGroupId); + if (it != groupSet.end()) // esisteva gia un gruppo con questo id! + assert(!"errore: due gruppi con lo stesso id!"); + else + groupSet.insert(currGroupId); + + while (i < m_strokes.size() && m_strokes[i]->m_groupId == currGroupId) i++; + } } #endif //------------------------------------------------------------------- -bool TVectorImage::canMoveStrokes(int strokeIndex, int count, int moveBefore) const -{ - return m_imp->canMoveStrokes(strokeIndex, count, moveBefore); +bool TVectorImage::canMoveStrokes(int strokeIndex, int count, + int moveBefore) const { + return m_imp->canMoveStrokes(strokeIndex, count, moveBefore); } //------------------------------------------------------------------- -//verifica se si possono spostare le stroke da strokeindex a strokeindex+count-1 prima della posizione moveBefore; -//per fare questo fa un vettore in cui mette tutti i gruppi nella posizione dopo lo -//spostamento e verifica che sia un configurazione di gruppi ammessa. - -bool TVectorImage::Imp::canMoveStrokes(int strokeIndex, int count, int moveBefore) const -{ - if (m_maxGroupId <= 1) //non ci sono gruppi! - return true; +// verifica se si possono spostare le stroke da strokeindex a +// strokeindex+count-1 prima della posizione moveBefore; +// per fare questo fa un vettore in cui mette tutti i gruppi nella posizione +// dopo lo +// spostamento e verifica che sia un configurazione di gruppi ammessa. - int i, j = 0; +bool TVectorImage::Imp::canMoveStrokes(int strokeIndex, int count, + int moveBefore) const { + if (m_maxGroupId <= 1) // non ci sono gruppi! + return true; - std::vector groupsAfterMoving(m_strokes.size()); - if (strokeIndex < moveBefore) { - for (i = 0; i < strokeIndex; i++) - groupsAfterMoving[j++] = m_strokes[i]->m_groupId; + int i, j = 0; - for (i = strokeIndex + count; i < moveBefore; i++) - groupsAfterMoving[j++] = m_strokes[i]->m_groupId; + std::vector groupsAfterMoving(m_strokes.size()); + if (strokeIndex < moveBefore) { + for (i = 0; i < strokeIndex; i++) + groupsAfterMoving[j++] = m_strokes[i]->m_groupId; - for (i = strokeIndex; i < strokeIndex + count; i++) - groupsAfterMoving[j++] = m_strokes[i]->m_groupId; + for (i = strokeIndex + count; i < moveBefore; i++) + groupsAfterMoving[j++] = m_strokes[i]->m_groupId; - for (i = moveBefore; i < (int)m_strokes.size(); i++) - groupsAfterMoving[j++] = m_strokes[i]->m_groupId; - } else { - for (i = 0; i < moveBefore; i++) - groupsAfterMoving[j++] = m_strokes[i]->m_groupId; + for (i = strokeIndex; i < strokeIndex + count; i++) + groupsAfterMoving[j++] = m_strokes[i]->m_groupId; - for (i = strokeIndex; i < strokeIndex + count; i++) - groupsAfterMoving[j++] = m_strokes[i]->m_groupId; + for (i = moveBefore; i < (int)m_strokes.size(); i++) + groupsAfterMoving[j++] = m_strokes[i]->m_groupId; + } else { + for (i = 0; i < moveBefore; i++) + groupsAfterMoving[j++] = m_strokes[i]->m_groupId; - for (i = moveBefore; i < strokeIndex; i++) - groupsAfterMoving[j++] = m_strokes[i]->m_groupId; + for (i = strokeIndex; i < strokeIndex + count; i++) + groupsAfterMoving[j++] = m_strokes[i]->m_groupId; - for (i = strokeIndex + count; i < (int)m_strokes.size(); i++) - groupsAfterMoving[j++] = m_strokes[i]->m_groupId; - } + for (i = moveBefore; i < strokeIndex; i++) + groupsAfterMoving[j++] = m_strokes[i]->m_groupId; - assert(j == (int)m_strokes.size()); + for (i = strokeIndex + count; i < (int)m_strokes.size(); i++) + groupsAfterMoving[j++] = m_strokes[i]->m_groupId; + } - i = 0; - TGroupId currGroupId; - std::set groupSet; + assert(j == (int)m_strokes.size()); - while (i < (int)groupsAfterMoving.size()) { - currGroupId = groupsAfterMoving[i]; - if (groupSet.find(currGroupId) != groupSet.end()) //esisteva gia un gruppo con questo id! - { - if (!currGroupId.isGrouped(true)) //i gruppi impliciti non contano - return false; - } else - groupSet.insert(currGroupId); + i = 0; + TGroupId currGroupId; + std::set groupSet; - while (i < (int)groupsAfterMoving.size() && groupsAfterMoving[i] == currGroupId) - i++; - } + while (i < (int)groupsAfterMoving.size()) { + currGroupId = groupsAfterMoving[i]; + if (groupSet.find(currGroupId) != + groupSet.end()) // esisteva gia un gruppo con questo id! + { + if (!currGroupId.isGrouped(true)) // i gruppi impliciti non contano + return false; + } else + groupSet.insert(currGroupId); + + while (i < (int)groupsAfterMoving.size() && + groupsAfterMoving[i] == currGroupId) + i++; + } - return true; + return true; } //----------------------------------------------------------------- -void TVectorImage::Imp::regroupGhosts(std::vector &changedStrokes) -{ - TGroupId currGroupId; - std::set groupMap; - std::set::iterator it; - UINT i = 0; - - while (i < m_strokes.size()) { - assert(m_strokes[i]->m_groupId != currGroupId); - assert(i == 0 || m_strokes[i - 1]->m_groupId.isGrouped() != m_strokes[i]->m_groupId.isGrouped() != 0 || - (m_strokes[i]->m_groupId.isGrouped() != 0 && m_strokes[i - 1]->m_groupId != m_strokes[i]->m_groupId)); - - currGroupId = m_strokes[i]->m_groupId; - it = groupMap.find(currGroupId); - if (it != groupMap.end()) //esisteva gia un gruppo con questo id! - { - if (currGroupId.isGrouped() != 0) - assert(!"errore: due gruppi con lo stesso id!"); - else //gruppo ghost; gli do un nuovo id - { - TGroupId newGroup(m_vi, true); - - while (i < m_strokes.size() && m_strokes[i]->m_groupId.isGrouped(true) != 0) { - m_strokes[i]->m_groupId = newGroup; - changedStrokes.push_back(i); - i++; - } - } - } else { - groupMap.insert(currGroupId); - while (i < m_strokes.size() && - ((currGroupId.isGrouped(false) != 0 && m_strokes[i]->m_groupId == currGroupId) || - currGroupId.isGrouped(true) != 0 && m_strokes[i]->m_groupId.isGrouped(true) != 0)) { - if (m_strokes[i]->m_groupId != currGroupId) { - m_strokes[i]->m_groupId = currGroupId; - changedStrokes.push_back(i); - } - i++; - } - } - } +void TVectorImage::Imp::regroupGhosts(std::vector &changedStrokes) { + TGroupId currGroupId; + std::set groupMap; + std::set::iterator it; + UINT i = 0; + + while (i < m_strokes.size()) { + assert(m_strokes[i]->m_groupId != currGroupId); + assert(i == 0 || + m_strokes[i - 1]->m_groupId.isGrouped() != + m_strokes[i]->m_groupId.isGrouped() != 0 || + (m_strokes[i]->m_groupId.isGrouped() != 0 && + m_strokes[i - 1]->m_groupId != m_strokes[i]->m_groupId)); + + currGroupId = m_strokes[i]->m_groupId; + it = groupMap.find(currGroupId); + if (it != groupMap.end()) // esisteva gia un gruppo con questo id! + { + if (currGroupId.isGrouped() != 0) + assert(!"errore: due gruppi con lo stesso id!"); + else // gruppo ghost; gli do un nuovo id + { + TGroupId newGroup(m_vi, true); + + while (i < m_strokes.size() && + m_strokes[i]->m_groupId.isGrouped(true) != 0) { + m_strokes[i]->m_groupId = newGroup; + changedStrokes.push_back(i); + i++; + } + } + } else { + groupMap.insert(currGroupId); + while (i < m_strokes.size() && + ((currGroupId.isGrouped(false) != 0 && + m_strokes[i]->m_groupId == currGroupId) || + currGroupId.isGrouped(true) != 0 && + m_strokes[i]->m_groupId.isGrouped(true) != 0)) { + if (m_strokes[i]->m_groupId != currGroupId) { + m_strokes[i]->m_groupId = currGroupId; + changedStrokes.push_back(i); + } + i++; + } + } + } } //-------------------------------------------------------------- -bool TVectorImage::canEnterGroup(int strokeIndex) const -{ - VIStroke *vs = m_imp->m_strokes[strokeIndex]; +bool TVectorImage::canEnterGroup(int strokeIndex) const { + VIStroke *vs = m_imp->m_strokes[strokeIndex]; - if (!vs->m_groupId.isGrouped()) - return false; + if (!vs->m_groupId.isGrouped()) return false; - return m_imp->m_insideGroup == TGroupId() || - vs->m_groupId != m_imp->m_insideGroup; + return m_imp->m_insideGroup == TGroupId() || + vs->m_groupId != m_imp->m_insideGroup; } //-------------------------------------------------------------- -bool TVectorImage::inCurrentGroup(int strokeIndex) const -{ - return m_imp->inCurrentGroup(strokeIndex); +bool TVectorImage::inCurrentGroup(int strokeIndex) const { + return m_imp->inCurrentGroup(strokeIndex); } //---------------------------------------------------------------------------------- -bool TVectorImage::Imp::inCurrentGroup(int strokeIndex) const -{ - return m_insideGroup == TGroupId() || m_insideGroup.isParentOf(m_strokes[strokeIndex]->m_groupId); +bool TVectorImage::Imp::inCurrentGroup(int strokeIndex) const { + return m_insideGroup == TGroupId() || + m_insideGroup.isParentOf(m_strokes[strokeIndex]->m_groupId); } //-------------------------------------------------------------------------------------------------- -bool TVectorImage::selectable(int strokeIndex) const -{ - return (m_imp->m_insideGroup != m_imp->m_strokes[strokeIndex]->m_groupId && - inCurrentGroup(strokeIndex)); +bool TVectorImage::selectable(int strokeIndex) const { + return (m_imp->m_insideGroup != m_imp->m_strokes[strokeIndex]->m_groupId && + inCurrentGroup(strokeIndex)); } //-------------------------------------------------------------------------------------------------- -namespace -{ - -bool containsNoSubregion(const TRegion *r, const TPointD &p) -{ +namespace { - if (r->contains(p)) { - for (unsigned int i = 0; i < r->getSubregionCount(); i++) - if (r->getSubregion(i)->contains(p)) - return false; - return true; - } else - return false; +bool containsNoSubregion(const TRegion *r, const TPointD &p) { + if (r->contains(p)) { + for (unsigned int i = 0; i < r->getSubregionCount(); i++) + if (r->getSubregion(i)->contains(p)) return false; + return true; + } else + return false; } }; //------------------------------------------------------ -int TVectorImage::getGroupByStroke(UINT index) const -{ - VIStroke *viStroke = getVIStroke(index); - return viStroke->m_groupId.m_id.back(); +int TVectorImage::getGroupByStroke(UINT index) const { + VIStroke *viStroke = getVIStroke(index); + return viStroke->m_groupId.m_id.back(); } //------------------------------------------------------ -int TVectorImage::getGroupByRegion(UINT index) const -{ - TRegion *r = m_imp->m_regions[index]; - for (UINT i = 0; i < r->getEdgeCount(); i++) - if (r->getEdge(i)->m_index >= 0) { - return m_imp->m_strokes[r->getEdge(i)->m_index]->m_groupId.m_id.back(); - } +int TVectorImage::getGroupByRegion(UINT index) const { + TRegion *r = m_imp->m_regions[index]; + for (UINT i = 0; i < r->getEdgeCount(); i++) + if (r->getEdge(i)->m_index >= 0) { + return m_imp->m_strokes[r->getEdge(i)->m_index]->m_groupId.m_id.back(); + } - return -1; + return -1; } //------------------------------------------------------ -int TVectorImage::pickGroup(const TPointD &pos, bool onEnteredGroup) const -{ - if (onEnteredGroup && isInsideGroup() == 0) - return -1; - - //double maxDist2 = 50*tglGetPixelSize2(); - - int strokeIndex = getStrokeCount() - 1; - - while (strokeIndex >= 0) // ogni ciclo di while esplora un gruppo; ciclo sugli stroke - { - if (!isStrokeGrouped(strokeIndex)) { - strokeIndex--; - continue; - } - - bool entered = isInsideGroup() > 0 && isEnteredGroupStroke(strokeIndex); - - if ((onEnteredGroup || entered) && - (!onEnteredGroup || !entered)) { - strokeIndex--; - continue; - } - - int currStrokeIndex = strokeIndex; - - while (strokeIndex >= 0 && getCommonGroupDepth(strokeIndex, currStrokeIndex) > 0) { - TStroke *s = getStroke(strokeIndex); - double outT; - int chunkIndex; - double dist2; - bool ret = s->getNearestChunk(pos, outT, chunkIndex, dist2); - if (ret) { - TThickPoint p = s->getChunk(chunkIndex)->getThickPoint(outT); - if (p.thick < 0.1) - p.thick = 1; - if (sqrt(dist2) <= 1.5 * p.thick) - return strokeIndex; - } - - /*TThickPoint p = s->getThickPoint(s->getW(pos)); - - double dist = tdistance( TThickPoint(pos,0), p); - if (dist<1.2*p.thick/2.0) - return strokeIndex;*/ - strokeIndex--; - } - } - - strokeIndex = getStrokeCount() - 1; - int ret = -1; - - while (strokeIndex >= 0) // ogni ciclo di while esplora un gruppo; ciclo sulle regions - { - if (!isStrokeGrouped(strokeIndex)) { - strokeIndex--; - continue; - } - - bool entered = isInsideGroup() > 0 && isEnteredGroupStroke(strokeIndex); - - if ((onEnteredGroup || entered) && - (!onEnteredGroup || !entered)) { - strokeIndex--; - continue; - } - - TRegion *currR = 0; - for (UINT regionIndex = 0; regionIndex < getRegionCount(); regionIndex++) { - TRegion *r = getRegion(regionIndex); - - int i, regionStrokeIndex = -1; - for (i = 0; i < (int)r->getEdgeCount() && regionStrokeIndex < 0; i++) - regionStrokeIndex = r->getEdge(i)->m_index; - - if (regionStrokeIndex >= 0 && sameSubGroup(regionStrokeIndex, strokeIndex) && containsNoSubregion(r, pos)) { - if (!currR || currR->contains(*r)) { - currR = r; - ret = regionStrokeIndex; - } - } - } - if (currR != 0) { - assert(m_palette); - const TSolidColorStyle *st = dynamic_cast(m_palette->getStyle(currR->getStyle())); - if (!st || st->getMainColor() != TPixel::Transparent) - return ret; - } - - while (strokeIndex > 0 && getCommonGroupDepth(strokeIndex, strokeIndex - 1) > 0) - strokeIndex--; - strokeIndex--; - } - - return -1; +int TVectorImage::pickGroup(const TPointD &pos, bool onEnteredGroup) const { + if (onEnteredGroup && isInsideGroup() == 0) return -1; + + // double maxDist2 = 50*tglGetPixelSize2(); + + int strokeIndex = getStrokeCount() - 1; + + while (strokeIndex >= + 0) // ogni ciclo di while esplora un gruppo; ciclo sugli stroke + { + if (!isStrokeGrouped(strokeIndex)) { + strokeIndex--; + continue; + } + + bool entered = isInsideGroup() > 0 && isEnteredGroupStroke(strokeIndex); + + if ((onEnteredGroup || entered) && (!onEnteredGroup || !entered)) { + strokeIndex--; + continue; + } + + int currStrokeIndex = strokeIndex; + + while (strokeIndex >= 0 && + getCommonGroupDepth(strokeIndex, currStrokeIndex) > 0) { + TStroke *s = getStroke(strokeIndex); + double outT; + int chunkIndex; + double dist2; + bool ret = s->getNearestChunk(pos, outT, chunkIndex, dist2); + if (ret) { + TThickPoint p = s->getChunk(chunkIndex)->getThickPoint(outT); + if (p.thick < 0.1) p.thick = 1; + if (sqrt(dist2) <= 1.5 * p.thick) return strokeIndex; + } + + /*TThickPoint p = s->getThickPoint(s->getW(pos)); + +double dist = tdistance( TThickPoint(pos,0), p); +if (dist<1.2*p.thick/2.0) +return strokeIndex;*/ + strokeIndex--; + } + } + + strokeIndex = getStrokeCount() - 1; + int ret = -1; + + while (strokeIndex >= + 0) // ogni ciclo di while esplora un gruppo; ciclo sulle regions + { + if (!isStrokeGrouped(strokeIndex)) { + strokeIndex--; + continue; + } + + bool entered = isInsideGroup() > 0 && isEnteredGroupStroke(strokeIndex); + + if ((onEnteredGroup || entered) && (!onEnteredGroup || !entered)) { + strokeIndex--; + continue; + } + + TRegion *currR = 0; + for (UINT regionIndex = 0; regionIndex < getRegionCount(); regionIndex++) { + TRegion *r = getRegion(regionIndex); + + int i, regionStrokeIndex = -1; + for (i = 0; i < (int)r->getEdgeCount() && regionStrokeIndex < 0; i++) + regionStrokeIndex = r->getEdge(i)->m_index; + + if (regionStrokeIndex >= 0 && + sameSubGroup(regionStrokeIndex, strokeIndex) && + containsNoSubregion(r, pos)) { + if (!currR || currR->contains(*r)) { + currR = r; + ret = regionStrokeIndex; + } + } + } + if (currR != 0) { + assert(m_palette); + const TSolidColorStyle *st = dynamic_cast( + m_palette->getStyle(currR->getStyle())); + if (!st || st->getMainColor() != TPixel::Transparent) return ret; + } + + while (strokeIndex > 0 && + getCommonGroupDepth(strokeIndex, strokeIndex - 1) > 0) + strokeIndex--; + strokeIndex--; + } + + return -1; } //------------------------------------------------------------------------------------ -int TVectorImage::pickGroup(const TPointD &pos) const -{ - int index; - if ((index = pickGroup(pos, true)) == -1) - return pickGroup(pos, false); +int TVectorImage::pickGroup(const TPointD &pos) const { + int index; + if ((index = pickGroup(pos, true)) == -1) return pickGroup(pos, false); - return index; + return index; } //-------------------------------------------------------------------------------------------------- diff --git a/toonz/sources/common/tvectorimage/tvectorimageP.h b/toonz/sources/common/tvectorimage/tvectorimageP.h index b862059..6b9b3fe 100644 --- a/toonz/sources/common/tvectorimage/tvectorimageP.h +++ b/toonz/sources/common/tvectorimage/tvectorimageP.h @@ -17,104 +17,102 @@ class VIStroke; class VIStroke; -class TGroupId -{ - +class TGroupId { public: - std::vector m_id; //m_id[i-1] e' parent di m_id[i] - TGroupId() - : m_id() {} + std::vector m_id; // m_id[i-1] e' parent di m_id[i] + TGroupId() : m_id() {} - //ghost group sono i gruppi impliciti: tutti gli stroke che non fanno parte di nessun gruppo ma - //che stanno tra due gruppi fanno parte di un gruppo implicito. per convenzione un ghostGroup ha id<0 + // ghost group sono i gruppi impliciti: tutti gli stroke che non fanno parte + // di nessun gruppo ma + // che stanno tra due gruppi fanno parte di un gruppo implicito. per + // convenzione un ghostGroup ha id<0 - TGroupId(TVectorImage *vi, bool isGhost); + TGroupId(TVectorImage *vi, bool isGhost); - TGroupId(const TGroupId &strokeGroup) : m_id(strokeGroup.m_id){}; + TGroupId(const TGroupId &strokeGroup) : m_id(strokeGroup.m_id){}; - //costruisce un gruppo partendo da un parent e da un id esistente. - TGroupId(const TGroupId &parent, const TGroupId &id); + // costruisce un gruppo partendo da un parent e da un id esistente. + TGroupId(const TGroupId &parent, const TGroupId &id); - bool operator==(const TGroupId &id) const; - bool operator!=(const TGroupId &id) const { return !(*this == id); } + bool operator==(const TGroupId &id) const; + bool operator!=(const TGroupId &id) const { return !(*this == id); } - //TGroupId makeGroup(vector strokes, bool recomputeRegions=false); - //void unmakeGroup(vector strokes); + // TGroupId makeGroup(vector strokes, bool recomputeRegions=false); + // void unmakeGroup(vector strokes); - //ritrona la depth del gruppo. (0->not grouped) - int isGrouped(bool implicit = false) const; + // ritrona la depth del gruppo. (0->not grouped) + int isGrouped(bool implicit = false) const; - //toglie il parent; se nera gruppo semplice, gli assegna il parametro id. - void ungroup(const TGroupId &id); - //bool sameParent(const TGroupId& id) const; + // toglie il parent; se nera gruppo semplice, gli assegna il parametro id. + void ungroup(const TGroupId &id); + // bool sameParent(const TGroupId& id) const; - bool operator!() const { return m_id.empty() || m_id[0] == 0; }; - bool operator<(const TGroupId &id) const; + bool operator!() const { return m_id.empty() || m_id[0] == 0; }; + bool operator<(const TGroupId &id) const; - int getDepth() const { return m_id.size(); } - int getCommonParentDepth(const TGroupId &id) const; - TGroupId getParent() const; + int getDepth() const { return m_id.size(); } + int getCommonParentDepth(const TGroupId &id) const; + TGroupId getParent() const; - int isParentOf(const TGroupId &id) const { return getCommonParentDepth(id) == getDepth(); } + int isParentOf(const TGroupId &id) const { + return getCommonParentDepth(id) == getDepth(); + } }; -class VIStroke -{ +class VIStroke { public: - TStroke *m_s; - bool m_isPoint; - bool m_isNewForFill; - std::list m_edgeList; - TGroupId m_groupId; - - VIStroke(TStroke *s, const TGroupId &StrokeId) - : m_s(s), m_isPoint(false), m_isNewForFill(true), m_groupId(StrokeId){}; - - VIStroke(const VIStroke &s, bool sameId = true); - - ~VIStroke() - { - delete m_s; - - std::list::iterator it, it_b = m_edgeList.begin(), it_e = m_edgeList.end(); - for (it = it_b; it != it_e; ++it) - if ((*it)->m_toBeDeleted) - delete *it; - } - - void inline addEdge(TEdge *e) { m_edgeList.push_back(e); } - - bool inline removeEdge(TEdge *e) - { - std::list::iterator it = m_edgeList.begin(); - while (it != m_edgeList.end() && *it != e) - it++; - if (*it == e) { - m_edgeList.erase(it); - return true; - } - return false; - } + TStroke *m_s; + bool m_isPoint; + bool m_isNewForFill; + std::list m_edgeList; + TGroupId m_groupId; + + VIStroke(TStroke *s, const TGroupId &StrokeId) + : m_s(s), m_isPoint(false), m_isNewForFill(true), m_groupId(StrokeId){}; + + VIStroke(const VIStroke &s, bool sameId = true); + + ~VIStroke() { + delete m_s; + + std::list::iterator it, it_b = m_edgeList.begin(), + it_e = m_edgeList.end(); + for (it = it_b; it != it_e; ++it) + if ((*it)->m_toBeDeleted) delete *it; + } + + void inline addEdge(TEdge *e) { m_edgeList.push_back(e); } + + bool inline removeEdge(TEdge *e) { + std::list::iterator it = m_edgeList.begin(); + while (it != m_edgeList.end() && *it != e) it++; + if (*it == e) { + m_edgeList.erase(it); + return true; + } + return false; + } }; //----------------------------------------------------------------------------- class IntersectionData; class Intersection; -//class IntersectStroke; +// class IntersectStroke; #ifdef LEVO -class TAutocloseEdge : public TGeneralEdge -{ +class TAutocloseEdge : public TGeneralEdge { public: - TSegment m_segment; - int m_nextStrokeIndex; - double m_nextStrokeW; - - TAutocloseEdge(const TSegment &segment, int nextStrokeIndex, double nextStrokeW) - : TGeneralEdge(eAutoclose), m_segment(segment), m_nextStrokeIndex(nextStrokeIndex), m_nextStrokeW(nextStrokeW) - { - } + TSegment m_segment; + int m_nextStrokeIndex; + double m_nextStrokeW; + + TAutocloseEdge(const TSegment &segment, int nextStrokeIndex, + double nextStrokeW) + : TGeneralEdge(eAutoclose) + , m_segment(segment) + , m_nextStrokeIndex(nextStrokeIndex) + , m_nextStrokeW(nextStrokeW) {} }; #endif @@ -122,127 +120,148 @@ public: //--------------------------------------------------------------------------------------------------- class TRegionFinder; -class TVectorImage::Imp -{ - TVectorImage *m_vi; +class TVectorImage::Imp { + TVectorImage *m_vi; public: - int m_maxGroupId; - int m_maxGhostGroupId; - - bool m_areValidRegions; - bool m_computedAlmostOnce; - bool m_justLoaded; - bool m_minimizeEdges; - bool m_notIntersectingStrokes, m_computeRegions; - TGroupId m_insideGroup; - - std::vector m_strokes; - double m_autocloseTolerance; - IntersectionData *m_intersectionData; - std::vector m_regions; - TThread::Mutex *m_mutex; - Imp(TVectorImage *vi); - ~Imp(); - - void initRegionsData(); - void deleteRegionsData(); - - TRegion *getRegion(const TPointD &p); - - int fill(const TPointD &p, int styleId); - bool selectFill(const TRectD &selectArea, TStroke *s, int styleId, bool onlyUnfilled, bool fillAreas, bool fillLines); - - void addStrokeRegionRef(UINT strokeIndex, TRegion *region); - - int computeRegions(); - void reindexEdges(UINT strokeIndex); - void reindexEdges(const std::vector &indexes, bool areAdded); - - void checkRegionDbConsistency(); - void cloneRegions(TVectorImage::Imp &out, bool doComputeRegions = true); - - void eraseIntersection(int index); - UINT getFillData(std::unique_ptr& v); - void setFillData(std::unique_ptr const& v, UINT branchCount, bool doComputeRegions = true); - void notifyChangedStrokes(const std::vector &strokeIndexArray, const std::vector &oldVectorStrokeArray, bool areFlipped); - void insertStrokeAt(VIStroke *stroke, int strokeIndex, bool recomputeRegions = true); - void moveStroke(int fromIndex, int toIndex); - void autoFill(int styleId, bool oddLevel); - - TRegion *getRegion(TRegionId regId, int index) const; - TRegion *getRegionFromLoopStroke(int strokeIndex) const; - VIStroke *joinStroke(int index1, int index2, int cpIndex1, int cpIndex2); - VIStroke *joinStrokeSmoothly(int index1, int index2, int cpIndex1, int cpIndex2); - VIStroke *extendStroke(int index, const TThickPoint &p, int cpIndex); - VIStroke *extendStrokeSmoothly(int index, const TThickPoint &p, int cpIndex); - void removeStrokes(const std::vector &toBeRemoved, bool deleteThem, bool recomputeRegions); - TStroke *removeStroke(int index, bool doComputeRegions); - void splitStroke(int strokeIndex, const std::vector &sortedWRanges); - void moveStrokes(int fromIndex, int count, int moveBefore, bool regroup); - - TStroke *removeEndpoints(int strokeIndex); - void restoreEndpoints(int index, TStroke *oldStroke); - - int areDifferentGroup(UINT index1, bool isRegion1, UINT index2, bool isRegion2) const; - void rearrangeMultiGroup(); - void reindexGroups(Imp &img); - void addRegion(TRegion *region); - void regroupGhosts(std::vector &changedStrokes); - bool inCurrentGroup(int strokeIndex) const; - bool canMoveStrokes(int strokeIndex, int count, int moveBefore) const; + int m_maxGroupId; + int m_maxGhostGroupId; + + bool m_areValidRegions; + bool m_computedAlmostOnce; + bool m_justLoaded; + bool m_minimizeEdges; + bool m_notIntersectingStrokes, m_computeRegions; + TGroupId m_insideGroup; + + std::vector m_strokes; + double m_autocloseTolerance; + IntersectionData *m_intersectionData; + std::vector m_regions; + TThread::Mutex *m_mutex; + Imp(TVectorImage *vi); + ~Imp(); + + void initRegionsData(); + void deleteRegionsData(); + + TRegion *getRegion(const TPointD &p); + + int fill(const TPointD &p, int styleId); + bool selectFill(const TRectD &selectArea, TStroke *s, int styleId, + bool onlyUnfilled, bool fillAreas, bool fillLines); + + void addStrokeRegionRef(UINT strokeIndex, TRegion *region); + + int computeRegions(); + void reindexEdges(UINT strokeIndex); + void reindexEdges(const std::vector &indexes, bool areAdded); + + void checkRegionDbConsistency(); + void cloneRegions(TVectorImage::Imp &out, bool doComputeRegions = true); + + void eraseIntersection(int index); + UINT getFillData(std::unique_ptr &v); + void setFillData(std::unique_ptr const &v, + UINT branchCount, bool doComputeRegions = true); + void notifyChangedStrokes(const std::vector &strokeIndexArray, + const std::vector &oldVectorStrokeArray, + bool areFlipped); + void insertStrokeAt(VIStroke *stroke, int strokeIndex, + bool recomputeRegions = true); + void moveStroke(int fromIndex, int toIndex); + void autoFill(int styleId, bool oddLevel); + + TRegion *getRegion(TRegionId regId, int index) const; + TRegion *getRegionFromLoopStroke(int strokeIndex) const; + VIStroke *joinStroke(int index1, int index2, int cpIndex1, int cpIndex2); + VIStroke *joinStrokeSmoothly(int index1, int index2, int cpIndex1, + int cpIndex2); + VIStroke *extendStroke(int index, const TThickPoint &p, int cpIndex); + VIStroke *extendStrokeSmoothly(int index, const TThickPoint &p, int cpIndex); + void removeStrokes(const std::vector &toBeRemoved, bool deleteThem, + bool recomputeRegions); + TStroke *removeStroke(int index, bool doComputeRegions); + void splitStroke(int strokeIndex, + const std::vector &sortedWRanges); + void moveStrokes(int fromIndex, int count, int moveBefore, bool regroup); + + TStroke *removeEndpoints(int strokeIndex); + void restoreEndpoints(int index, TStroke *oldStroke); + + int areDifferentGroup(UINT index1, bool isRegion1, UINT index2, + bool isRegion2) const; + void rearrangeMultiGroup(); + void reindexGroups(Imp &img); + void addRegion(TRegion *region); + void regroupGhosts(std::vector &changedStrokes); + bool inCurrentGroup(int strokeIndex) const; + bool canMoveStrokes(int strokeIndex, int count, int moveBefore) const; #ifdef _DEBUG - void checkIntersections(); - void checkRegions(const std::vector ®ions); - void printStrokes(std::ofstream &os); - void checkGroups(); + void checkIntersections(); + void checkRegions(const std::vector ®ions); + void printStrokes(std::ofstream &os); + void checkGroups(); #endif #ifdef NEW_REGION_FILL - TRegionFinder *m_regionFinder; - void resetRegionFinder(); + TRegionFinder *m_regionFinder; + void resetRegionFinder(); #endif private: - void findRegions(const TRectD &rect); - int computeIntersections(); - void findIntersections(); - - int computeEndpointsIntersections(); - //Imp(const TVectorImage::Imp &); - //Imp & operator=(const TVectorImage::Imp &); - void eraseDeadIntersections(); - IntersectedStroke *eraseBranch(Intersection *in, IntersectedStroke *is); - void doEraseIntersection(int index, std::vector *toBeDeleted = 0); - void eraseEdgeFromStroke(IntersectedStroke *is); - bool areWholeGroups(const std::vector &indexes) const; - //accorpa tutti i gruppi ghost adiacenti in uno solo, e rinomina gruppi ghost separati con lo stesso id; si usa questa funzione dopo ula creazione di un gruppo o il move di strokes - - //--------------------NUOVO CALCOLO REGIONI------------------------------------------------ + void findRegions(const TRectD &rect); + int computeIntersections(); + void findIntersections(); + + int computeEndpointsIntersections(); + // Imp(const TVectorImage::Imp &); + // Imp & operator=(const TVectorImage::Imp &); + void eraseDeadIntersections(); + IntersectedStroke *eraseBranch(Intersection *in, IntersectedStroke *is); + void doEraseIntersection(int index, std::vector *toBeDeleted = 0); + void eraseEdgeFromStroke(IntersectedStroke *is); + bool areWholeGroups(const std::vector &indexes) const; + // accorpa tutti i gruppi ghost adiacenti in uno solo, e rinomina gruppi ghost + // separati con lo stesso id; si usa questa funzione dopo ula creazione di un + // gruppo o il move di strokes + + //--------------------NUOVO CALCOLO + //REGIONI------------------------------------------------ public: #ifdef LEVO - vector existingRegions; - TRegion *findRegionFromStroke(const IntersectStroke &stroke, const TPointD &p); - bool findNextStrokes(const TEdge &currEdge, std::multimap &nextEdges); - bool addNextEdge(TEdge &edge, TRegion ®ion, TRegion *&existingRegion, bool isStartingEdge = false); - bool addNextEdge(TAutocloseEdge &edge, TRegion ®ion, TRegion *&existingRegion); - bool storeRegion(TRegion *region, const TPointD &p); - - bool exploreAndAddNextEdge(TEdge &edge, TEdge &nextEdge, TRegion ®ion, TRegion *&existingRegion); - bool addNextAutocloseEdge(TEdge &edge, TAutocloseEdge &nextEdge, TRegion ®ion, TRegion *&existingRegion); - bool addNextAutocloseEdge(TAutocloseEdge &edge, TEdge &nextEdge, TRegion ®ion, TRegion *&existingRegion); - void computeAutocloseSegments(const TEdge &currEdge, int strokeIndex, std::multimap &segments); - void computeAutocloseSegmentsSameStroke(const TEdge &currEdge, std::multimap &segments); + vector existingRegions; + TRegion *findRegionFromStroke(const IntersectStroke &stroke, + const TPointD &p); + bool findNextStrokes(const TEdge &currEdge, + std::multimap &nextEdges); + bool addNextEdge(TEdge &edge, TRegion ®ion, TRegion *&existingRegion, + bool isStartingEdge = false); + bool addNextEdge(TAutocloseEdge &edge, TRegion ®ion, + TRegion *&existingRegion); + bool storeRegion(TRegion *region, const TPointD &p); + + bool exploreAndAddNextEdge(TEdge &edge, TEdge &nextEdge, TRegion ®ion, + TRegion *&existingRegion); + bool addNextAutocloseEdge(TEdge &edge, TAutocloseEdge &nextEdge, + TRegion ®ion, TRegion *&existingRegion); + bool addNextAutocloseEdge(TAutocloseEdge &edge, TEdge &nextEdge, + TRegion ®ion, TRegion *&existingRegion); + void computeAutocloseSegments( + const TEdge &currEdge, int strokeIndex, + std::multimap &segments); + void computeAutocloseSegmentsSameStroke( + const TEdge &currEdge, std::multimap &segments); #endif - //-------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------- private: - // not implemented - Imp(const Imp &); - Imp &operator=(const Imp &); + // not implemented + Imp(const Imp &); + Imp &operator=(const Imp &); }; void addRegion(std::vector ®ionArray, TRegion *region); diff --git a/toonz/sources/common/tvectorrenderer.cpp b/toonz/sources/common/tvectorrenderer.cpp index 295506f..8ad85d6 100644 --- a/toonz/sources/common/tvectorrenderer.cpp +++ b/toonz/sources/common/tvectorrenderer.cpp @@ -30,9 +30,12 @@ #ifdef USE_MESA -extern "C" int GLAPIENTRY wglChoosePixelFormat(HDC, const PIXELFORMATDESCRIPTOR *); -extern "C" int GLAPIENTRY wglDescribePixelFormat(HDC, int, unsigned int, LPPIXELFORMATDESCRIPTOR); -extern "C" int GLAPIENTRY wglSetPixelFormat(HDC, int, const PIXELFORMATDESCRIPTOR *); +extern "C" int GLAPIENTRY wglChoosePixelFormat(HDC, + const PIXELFORMATDESCRIPTOR *); +extern "C" int GLAPIENTRY wglDescribePixelFormat(HDC, int, unsigned int, + LPPIXELFORMATDESCRIPTOR); +extern "C" int GLAPIENTRY wglSetPixelFormat(HDC, int, + const PIXELFORMATDESCRIPTOR *); extern "C" int GLAPIENTRY wglSwapBuffers(HDC); #define ChoosePixelFormat wglChoosePixelFormat @@ -45,226 +48,231 @@ extern "C" int GLAPIENTRY wglSwapBuffers(HDC); #ifdef WIN32 // init a BITMAPINFO structure -void initBITMAPINFO(BITMAPINFO &info, const TRasterP img) -{ - memset(&info, 0, sizeof(BITMAPINFOHEADER)); - - info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - info.bmiHeader.biWidth = img->getLx(); - info.bmiHeader.biHeight = img->getLy(); - info.bmiHeader.biPlanes = 1; - info.bmiHeader.biBitCount = 32; - info.bmiHeader.biCompression = BI_RGB; - info.bmiHeader.biSizeImage = 0; - info.bmiHeader.biXPelsPerMeter = 1000; - info.bmiHeader.biYPelsPerMeter = 1000; - info.bmiHeader.biClrUsed = 0; - info.bmiHeader.biClrImportant = 0; +void initBITMAPINFO(BITMAPINFO &info, const TRasterP img) { + memset(&info, 0, sizeof(BITMAPINFOHEADER)); + + info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + info.bmiHeader.biWidth = img->getLx(); + info.bmiHeader.biHeight = img->getLy(); + info.bmiHeader.biPlanes = 1; + info.bmiHeader.biBitCount = 32; + info.bmiHeader.biCompression = BI_RGB; + info.bmiHeader.biSizeImage = 0; + info.bmiHeader.biXPelsPerMeter = 1000; + info.bmiHeader.biYPelsPerMeter = 1000; + info.bmiHeader.biClrUsed = 0; + info.bmiHeader.biClrImportant = 0; } //----------------------------------------------------------------------------- #ifdef BUBU -void hardRenderVectorImage_MESA(const TVectorRenderData &rd, TRaster32P &ras, const TVectorImageP &vimg) -{ - int rasterWidth = ras->getLx(); - int rasterHeight = ras->getLy(); +void hardRenderVectorImage_MESA(const TVectorRenderData &rd, TRaster32P &ras, + const TVectorImageP &vimg) { + int rasterWidth = ras->getLx(); + int rasterHeight = ras->getLy(); //--- begin mesa stuff /* Create an RGBA-mode context */ #if OSMESA_MAJOR_VERSION * 100 + OSMESA_MINOR_VERSION >= 305 - /* specify Z, stencil, accum sizes */ - OSMesaContext ctx = OSMesaCreateContextExt(OSMESA_RGBA, 16, 0, 0, NULL); + /* specify Z, stencil, accum sizes */ + OSMesaContext ctx = OSMesaCreateContextExt(OSMESA_RGBA, 16, 0, 0, NULL); #else - OSMesaContext ctx = OSMesaCreateContext(OSMESA_RGBA, NULL); + OSMesaContext ctx = OSMesaCreateContext(OSMESA_RGBA, NULL); #endif - if (!ctx) { - throw TException("OSMesaCreateContext failed!\n"); - } - ras->lock(); - /* Bind the buffer to the context and make it current */ - if (!OSMesaMakeCurrent(ctx, ras->getRawData(), GL_UNSIGNED_BYTE, ras->getLx(), ras->getLy())) { - { - ras->unlock(); - throw TException("OSMesaMakeCurrent failed!\n"); - } - } - - //---end mesa stuff - // cfr. help: OpenGL/Programming tip/OpenGL Correctness Tips - glViewport(0, 0, rasterWidth, rasterHeight); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluOrtho2D(0, rasterWidth, 0, rasterHeight); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glTranslatef(0.375, 0.375, 0.0); - /* - glClearColor(0.0f,0.0f,0.0f,0.0f); - glClear(GL_COLOR_BUFFER_BIT); + if (!ctx) { + throw TException("OSMesaCreateContext failed!\n"); + } + ras->lock(); + /* Bind the buffer to the context and make it current */ + if (!OSMesaMakeCurrent(ctx, ras->getRawData(), GL_UNSIGNED_BYTE, ras->getLx(), + ras->getLy())) { + { + ras->unlock(); + throw TException("OSMesaMakeCurrent failed!\n"); + } + } - // draw background - glRasterPos2d(0, 0); - glDrawPixels( ras->getLx(),ras->getLy(), GL_BGRA_EXT, GL_UNSIGNED_BYTE, ras->getRawData()); + //---end mesa stuff + // cfr. help: OpenGL/Programming tip/OpenGL Correctness Tips + glViewport(0, 0, rasterWidth, rasterHeight); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluOrtho2D(0, rasterWidth, 0, rasterHeight); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.375, 0.375, 0.0); + /* +glClearColor(0.0f,0.0f,0.0f,0.0f); +glClear(GL_COLOR_BUFFER_BIT); + +// draw background +glRasterPos2d(0, 0); +glDrawPixels( ras->getLx(),ras->getLy(), GL_BGRA_EXT, GL_UNSIGNED_BYTE, +ras->getRawData()); */ - // do OpenGL draw - assert(vimg); - tglDraw(rd, vimg.getPointer()); - - // force to finish - glFlush(); - glFinish(); - /* - // set info in out raster - TDimension size = ras->getSize(); - - if( ras->getWrap() == rasterWidth ) - memcpy( ras->getRawData(), offData, ras->getPixelSize()*size.lx*size.ly ); - else - { - TRaster32P temp( ras->getLx(), ras->getLy()); - memcpy( temp->getRawData(), offData, ras->getPixelSize()*size.lx*size.ly ); - ras->copy(temp); - } + // do OpenGL draw + assert(vimg); + tglDraw(rd, vimg.getPointer()); + + // force to finish + glFlush(); + glFinish(); + /* +// set info in out raster +TDimension size = ras->getSize(); + +if( ras->getWrap() == rasterWidth ) +memcpy( ras->getRawData(), offData, ras->getPixelSize()*size.lx*size.ly ); +else +{ +TRaster32P temp( ras->getLx(), ras->getLy()); +memcpy( temp->getRawData(), offData, ras->getPixelSize()*size.lx*size.ly ); +ras->copy(temp); +} */ - OSMesaDestroyContext(ctx); - ras->unlock(); + OSMesaDestroyContext(ctx); + ras->unlock(); } -#endif //BUBU -void hardRenderVectorImage(const TVectorRenderData &rd, TRaster32P &ras, const TVectorImageP &vimg) -{ - int rasterWidth = ras->getLx(); - int rasterHeight = ras->getLy(); - ras->lock(); +#endif // BUBU +void hardRenderVectorImage(const TVectorRenderData &rd, TRaster32P &ras, + const TVectorImageP &vimg) { + int rasterWidth = ras->getLx(); + int rasterHeight = ras->getLy(); + ras->lock(); #ifdef USE_MESA /* Create an RGBA-mode context */ #if OSMESA_MAJOR_VERSION * 100 + OSMESA_MINOR_VERSION >= 305 - /* specify Z, stencil, accum sizes */ - OSMesaContext ctx = OSMesaCreateContextExt(OSMESA_RGBA, 16, 0, 0, NULL); + /* specify Z, stencil, accum sizes */ + OSMesaContext ctx = OSMesaCreateContextExt(OSMESA_RGBA, 16, 0, 0, NULL); #else - OSMesaContext ctx = OSMesaCreateContext(OSMESA_RGBA, NULL); + OSMesaContext ctx = OSMesaCreateContext(OSMESA_RGBA, NULL); #endif - if (!ctx) { - ras->unlock(); - throw TException("OSMesaCreateContext failed!\n"); - } - - /* Bind the buffer to the context and make it current */ + if (!ctx) { + ras->unlock(); + throw TException("OSMesaCreateContext failed!\n"); + } - if (!OSMesaMakeCurrent(ctx, ras->getRawData(), GL_UNSIGNED_BYTE, ras->getLx(), ras->getLy())) { + /* Bind the buffer to the context and make it current */ - { - ras->unlock(); - throw TException("OSMesaMakeCurrent failed!\n"); - } - } + if (!OSMesaMakeCurrent(ctx, ras->getRawData(), GL_UNSIGNED_BYTE, ras->getLx(), + ras->getLy())) { + { + ras->unlock(); + throw TException("OSMesaMakeCurrent failed!\n"); + } + } #else - BITMAPINFO info; - - initBITMAPINFO(info, ras); - - void *offData = 0; // a pointer to buffer - - // open an offscreen device - HDC offDC = CreateCompatibleDC(NULL); - - HBITMAP offDIB = // and a bitmap image - CreateDIBSection(offDC, &info, DIB_RGB_COLORS, &offData, NULL, 0); - - assert(offDIB); - assert(offData); - - int dataSize = // number of byte of raster - rasterWidth * rasterHeight * 4; - - memset(offData, 0, dataSize); - - HGDIOBJ oldobj = // select BIB to write - SelectObject(offDC, offDIB); - - static PIXELFORMATDESCRIPTOR pfd = - { - sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd - 1, // version number - 0 | (false ? (PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER) : (PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI)) | PFD_SUPPORT_OPENGL, // support OpenGL - PFD_TYPE_RGBA, // RGBA type - 32, // 32-bit color depth - 0, 0, 0, 0, 0, 0, // color bits ignored - 0, // no alpha buffer - 0, // shift bit ignored - 0, // no accumulation buffer - 0, 0, 0, 0, // accum bits ignored - 32, // 32-bit z-buffer - 0, // no stencil buffer - 0, // no auxiliary buffer - PFD_MAIN_PLANE, // main layer - 0, // reserved - 0, 0, 0 // layer masks ignored - }; - - // get the best available match of pixel format for the device context - int iPixelFormat = ChoosePixelFormat(offDC, &pfd); - assert(iPixelFormat != 0); - - // make that the pixel format of the device context - int ret = SetPixelFormat(offDC, iPixelFormat, &pfd); - assert(ret == TRUE); - - // make a valid context for OpenGL rendering - HGLRC hglRC = wglCreateContext(offDC); - assert(hglRC); - ret = wglMakeCurrent(offDC, hglRC); - assert(ret == TRUE); + BITMAPINFO info; + + initBITMAPINFO(info, ras); + + void *offData = 0; // a pointer to buffer + + // open an offscreen device + HDC offDC = CreateCompatibleDC(NULL); + + HBITMAP offDIB = // and a bitmap image + CreateDIBSection(offDC, &info, DIB_RGB_COLORS, &offData, NULL, 0); + + assert(offDIB); + assert(offData); + + int dataSize = // number of byte of raster + rasterWidth * rasterHeight * 4; + + memset(offData, 0, dataSize); + + HGDIOBJ oldobj = // select BIB to write + SelectObject(offDC, offDIB); + + static PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd + 1, // version number + 0 | (false ? (PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER) + : (PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI)) | + PFD_SUPPORT_OPENGL, // support OpenGL + PFD_TYPE_RGBA, // RGBA type + 32, // 32-bit color depth + 0, + 0, 0, 0, 0, 0, // color bits ignored + 0, // no alpha buffer + 0, // shift bit ignored + 0, // no accumulation buffer + 0, 0, 0, 0, // accum bits ignored + 32, // 32-bit z-buffer + 0, // no stencil buffer + 0, // no auxiliary buffer + PFD_MAIN_PLANE, // main layer + 0, // reserved + 0, 0, 0 // layer masks ignored + }; + + // get the best available match of pixel format for the device context + int iPixelFormat = ChoosePixelFormat(offDC, &pfd); + assert(iPixelFormat != 0); + + // make that the pixel format of the device context + int ret = SetPixelFormat(offDC, iPixelFormat, &pfd); + assert(ret == TRUE); + + // make a valid context for OpenGL rendering + HGLRC hglRC = wglCreateContext(offDC); + assert(hglRC); + ret = wglMakeCurrent(offDC, hglRC); + assert(ret == TRUE); #endif - // cfr. help: OpenGL/Programming tip/OpenGL Correctness Tips - glViewport(0, 0, rasterWidth, rasterHeight); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluOrtho2D(0, rasterWidth, 0, rasterHeight); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glTranslatef(0.375, 0.375, 0.0); + // cfr. help: OpenGL/Programming tip/OpenGL Correctness Tips + glViewport(0, 0, rasterWidth, rasterHeight); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluOrtho2D(0, rasterWidth, 0, rasterHeight); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.375, 0.375, 0.0); #ifndef USE_MESA - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); - // draw background - glRasterPos2d(0, 0); - glDrawPixels(ras->getLx(), ras->getLy(), GL_BGRA_EXT, GL_UNSIGNED_BYTE, ras->getRawData()); + // draw background + glRasterPos2d(0, 0); + glDrawPixels(ras->getLx(), ras->getLy(), GL_BGRA_EXT, GL_UNSIGNED_BYTE, + ras->getRawData()); #endif - // do OpenGL draw - assert(vimg); + // do OpenGL draw + assert(vimg); - tglDraw(rd, vimg.getPointer()); + tglDraw(rd, vimg.getPointer()); - // force to finish - glFlush(); + // force to finish + glFlush(); #ifdef USE_MESA - OSMesaDestroyContext(ctx); + OSMesaDestroyContext(ctx); #else - // set info in out raster - TDimension size = ras->getSize(); - - if (ras->getWrap() == rasterWidth) - memcpy(ras->getRawData(), offData, ras->getPixelSize() * size.lx * size.ly); - else { - TRaster32P temp(ras->getLx(), ras->getLy()); - memcpy(temp->getRawData(), offData, ras->getPixelSize() * size.lx * size.ly); - ras->copy(temp); - } - - ret = wglMakeCurrent(offDC, NULL); - assert(ret == TRUE); - wglDeleteContext(hglRC); - - // release object - SelectObject(offDC, oldobj); - DeleteObject(offDIB); - DeleteObject(offDC); + // set info in out raster + TDimension size = ras->getSize(); + + if (ras->getWrap() == rasterWidth) + memcpy(ras->getRawData(), offData, ras->getPixelSize() * size.lx * size.ly); + else { + TRaster32P temp(ras->getLx(), ras->getLy()); + memcpy(temp->getRawData(), offData, + ras->getPixelSize() * size.lx * size.ly); + ras->copy(temp); + } + + ret = wglMakeCurrent(offDC, NULL); + assert(ret == TRUE); + wglDeleteContext(hglRC); + + // release object + SelectObject(offDC, oldobj); + DeleteObject(offDIB); + DeleteObject(offDC); #endif - ras->unlock(); + ras->unlock(); } // end of WIN32 @@ -272,86 +280,74 @@ void hardRenderVectorImage(const TVectorRenderData &rd, TRaster32P &ras, const T //============================================================================= -namespace -{ +namespace { GLXContext ctx; XVisualInfo *visinfo; GC gc; -Window make_rgb_window(Display *dpy, - unsigned int width, unsigned int height) -{ - const int sbAttrib[] = {GLX_RGBA, - GLX_RED_SIZE, 1, - GLX_GREEN_SIZE, 1, - GLX_BLUE_SIZE, 1, - None}; - const int dbAttrib[] = {GLX_RGBA, - GLX_RED_SIZE, 1, - GLX_GREEN_SIZE, 1, - GLX_BLUE_SIZE, 1, - GLX_DOUBLEBUFFER, - None}; - int scrnum; - XSetWindowAttributes attr; - TUINT32 mask; - Window root; - Window win; - - scrnum = DefaultScreen(dpy); - root = RootWindow(dpy, scrnum); - - visinfo = glXChooseVisual(dpy, scrnum, (int *)sbAttrib); - if (!visinfo) { - visinfo = glXChooseVisual(dpy, scrnum, (int *)dbAttrib); - if (!visinfo) { - printf("Error: couldn't get an RGB visual\n"); - exit(1); - } - } - - /* window attributes */ - attr.background_pixel = 0; - attr.border_pixel = 0; - /* TODO: share root colormap if possible */ - attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone); - attr.event_mask = StructureNotifyMask | ExposureMask; - mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; - - win = XCreateWindow(dpy, root, 0, 0, width, height, - 0, visinfo->depth, InputOutput, - visinfo->visual, mask, &attr); - - /* make an X GC so we can do XCopyArea later */ - gc = XCreateGC(dpy, win, 0, NULL); - - /* need indirect context */ - ctx = glXCreateContext(dpy, visinfo, NULL, False); - if (!ctx) { - printf("Error: glXCreateContext failed\n"); - exit(-1); - } - - printf("Direct rendering: %s\n", glXIsDirect(dpy, ctx) ? "Yes" : "No"); - - return win; +Window make_rgb_window(Display *dpy, unsigned int width, unsigned int height) { + const int sbAttrib[] = {GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, + 1, GLX_BLUE_SIZE, 1, None}; + const int dbAttrib[] = {GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, + 1, GLX_BLUE_SIZE, 1, GLX_DOUBLEBUFFER, + None}; + int scrnum; + XSetWindowAttributes attr; + TUINT32 mask; + Window root; + Window win; + + scrnum = DefaultScreen(dpy); + root = RootWindow(dpy, scrnum); + + visinfo = glXChooseVisual(dpy, scrnum, (int *)sbAttrib); + if (!visinfo) { + visinfo = glXChooseVisual(dpy, scrnum, (int *)dbAttrib); + if (!visinfo) { + printf("Error: couldn't get an RGB visual\n"); + exit(1); + } + } + + /* window attributes */ + attr.background_pixel = 0; + attr.border_pixel = 0; + /* TODO: share root colormap if possible */ + attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone); + attr.event_mask = StructureNotifyMask | ExposureMask; + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; + + win = XCreateWindow(dpy, root, 0, 0, width, height, 0, visinfo->depth, + InputOutput, visinfo->visual, mask, &attr); + + /* make an X GC so we can do XCopyArea later */ + gc = XCreateGC(dpy, win, 0, NULL); + + /* need indirect context */ + ctx = glXCreateContext(dpy, visinfo, NULL, False); + if (!ctx) { + printf("Error: glXCreateContext failed\n"); + exit(-1); + } + + printf("Direct rendering: %s\n", glXIsDirect(dpy, ctx) ? "Yes" : "No"); + + return win; } -GLXPixmap make_pixmap(Display *dpy, Window win, - unsigned int width, unsigned int height, - Pixmap *pixmap) -{ - Pixmap pm; - GLXPixmap glxpm; - XWindowAttributes attr; +GLXPixmap make_pixmap(Display *dpy, Window win, unsigned int width, + unsigned int height, Pixmap *pixmap) { + Pixmap pm; + GLXPixmap glxpm; + XWindowAttributes attr; - pm = XCreatePixmap(dpy, win, width, height, visinfo->depth); - if (!pm) { - printf("Error: XCreatePixmap failed\n"); - exit(-1); - } + pm = XCreatePixmap(dpy, win, width, height, visinfo->depth); + if (!pm) { + printf("Error: XCreatePixmap failed\n"); + exit(-1); + } - XGetWindowAttributes(dpy, win, &attr); + XGetWindowAttributes(dpy, win, &attr); /* * IMPORTANT: @@ -360,100 +356,95 @@ GLXPixmap make_pixmap(Display *dpy, Window win, * to render correctly. This is because Mesa allows RGB rendering * into any kind of visual, not just TrueColor or DirectColor. */ -#ifdef PROBLEMI_CON_IL_DRIVER_NVIDIA // GLX_MESA_pixmap_colormap // - if (strstr(glXQueryExtensionsString(dpy, 0), "GLX_MESA_pixmap_colormap")) { - /* stand-alone Mesa, specify the colormap */ - glxpm = glXCreateGLXPixmapMESA(dpy, visinfo, pm, attr.colormap); - } else { - glxpm = glXCreateGLXPixmap(dpy, visinfo, pm); - } +#ifdef PROBLEMI_CON_IL_DRIVER_NVIDIA // GLX_MESA_pixmap_colormap // + if (strstr(glXQueryExtensionsString(dpy, 0), "GLX_MESA_pixmap_colormap")) { + /* stand-alone Mesa, specify the colormap */ + glxpm = glXCreateGLXPixmapMESA(dpy, visinfo, pm, attr.colormap); + } else { + glxpm = glXCreateGLXPixmap(dpy, visinfo, pm); + } #else - /* This will work with Mesa too if the visual is TrueColor or DirectColor */ - glxpm = glXCreateGLXPixmap(dpy, visinfo, pm); + /* This will work with Mesa too if the visual is TrueColor or DirectColor */ + glxpm = glXCreateGLXPixmap(dpy, visinfo, pm); #endif - if (!glxpm) { - printf("Error: GLXCreateGLXPixmap failed\n"); - exit(-1); - } + if (!glxpm) { + printf("Error: GLXCreateGLXPixmap failed\n"); + exit(-1); + } - *pixmap = pm; + *pixmap = pm; - return glxpm; + return glxpm; } } -//void offscreenRender(TRaster32P& ras, const TVectorImageP& vimg, const TAffine& aff) -void hardRenderVectorImage(const TVectorRenderData &rd, TRaster32P &ras, const TVectorImageP &vimg) -{ - Display *dpy; - Window win; - Pixmap pm; - GLXPixmap glxpm; +// void offscreenRender(TRaster32P& ras, const TVectorImageP& vimg, const +// TAffine& aff) +void hardRenderVectorImage(const TVectorRenderData &rd, TRaster32P &ras, + const TVectorImageP &vimg) { + Display *dpy; + Window win; + Pixmap pm; + GLXPixmap glxpm; - ras->lock(); + ras->lock(); - dpy = XOpenDisplay(NULL); + dpy = XOpenDisplay(NULL); - win = make_rgb_window(dpy, ras->getLx(), ras->getLy()); - glxpm = make_pixmap(dpy, win, ras->getLx(), ras->getLy(), &pm); + win = make_rgb_window(dpy, ras->getLx(), ras->getLy()); + glxpm = make_pixmap(dpy, win, ras->getLx(), ras->getLy(), &pm); - GLXContext oldctx = glXGetCurrentContext(); - GLXDrawable olddrw = glXGetCurrentDrawable(); + GLXContext oldctx = glXGetCurrentContext(); + GLXDrawable olddrw = glXGetCurrentDrawable(); - glXMakeCurrent(dpy, glxpm, ctx); - //printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); + glXMakeCurrent(dpy, glxpm, ctx); + // printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); - // cfr. help: OpenGL/Programming tip/OpenGL Correctness Tips - glViewport(0, 0, ras->getLx(), ras->getLy()); + // cfr. help: OpenGL/Programming tip/OpenGL Correctness Tips + glViewport(0, 0, ras->getLx(), ras->getLy()); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluOrtho2D(0, ras->getLx(), 0, ras->getLy()); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glTranslatef(0.375, 0.375, 0.0); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluOrtho2D(0, ras->getLx(), 0, ras->getLy()); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.375, 0.375, 0.0); - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); - // draw background - glRasterPos2d(0, 0); - glDrawPixels(ras->getLx(), ras->getLy(), GL_RGBA, GL_UNSIGNED_BYTE, ras->getRawData()); + // draw background + glRasterPos2d(0, 0); + glDrawPixels(ras->getLx(), ras->getLy(), GL_RGBA, GL_UNSIGNED_BYTE, + ras->getRawData()); - // do OpenGL draw - assert(vimg); + // do OpenGL draw + assert(vimg); - tglDraw(rd, vimg.getPointer()); + tglDraw(rd, vimg.getPointer()); - glFlush(); + glFlush(); #if defined(__sgi) - glReadPixels(0, 0, - ras->getLx(), ras->getLy(), - GL_ABGR_EXT, - GL_UNSIGNED_BYTE, - ras->getRawData()); + glReadPixels(0, 0, ras->getLx(), ras->getLy(), GL_ABGR_EXT, GL_UNSIGNED_BYTE, + ras->getRawData()); #elif defined(LINUX) - glReadPixels(0, 0, - ras->getLx(), ras->getLy(), - GL_RGBA, - GL_UNSIGNED_BYTE, - ras->getRawData()); + glReadPixels(0, 0, ras->getLx(), ras->getLy(), GL_RGBA, GL_UNSIGNED_BYTE, + ras->getRawData()); #endif - Bool ret = glXMakeCurrent(dpy, olddrw, oldctx); + Bool ret = glXMakeCurrent(dpy, olddrw, oldctx); #ifdef DEBUG - if (!ret) { - std::cerr << __FUNCTION__ - << " error in glXMakeCurrent olddrw=" << olddrw - << " oldctx=" << oldctx << std::endl; - } + if (!ret) { + std::cerr << __FUNCTION__ << " error in glXMakeCurrent olddrw=" << olddrw + << " oldctx=" << oldctx << std::endl; + } #endif - ras->unlock(); + ras->unlock(); } #endif diff --git a/toonz/sources/common/tvrender/macofflinegl.cpp b/toonz/sources/common/tvrender/macofflinegl.cpp index 2a2f793..c545234 100644 --- a/toonz/sources/common/tvrender/macofflinegl.cpp +++ b/toonz/sources/common/tvrender/macofflinegl.cpp @@ -6,32 +6,30 @@ #include "tthread.h" -namespace -{ +namespace { #if defined(powerpc) -void rightRotateBits(UCHAR *buf, int bufferSize) -{ - UINT *buffer = (UINT *)buf; - register UINT app; - for (int i = 0; i < bufferSize; i++, buffer++) { - app = *buffer; - *buffer = app >> 8 | app << 24; - } +void rightRotateBits(UCHAR *buf, int bufferSize) { + UINT *buffer = (UINT *)buf; + register UINT app; + for (int i = 0; i < bufferSize; i++, buffer++) { + app = *buffer; + *buffer = app >> 8 | app << 24; + } } #else -void rightRotateBits(UCHAR *buf, int bufferSize) -{ - UINT *buffer = (UINT *)buf; - register UINT app; - for (int i = 0; i < bufferSize; i++, buffer++) { - app = *buffer; - *buffer = (app >> 16 & 0x000000ff) | (app << 16 & 0x00ff0000) | (app & 0xff00ff00); - } +void rightRotateBits(UCHAR *buf, int bufferSize) { + UINT *buffer = (UINT *)buf; + register UINT app; + for (int i = 0; i < bufferSize; i++, buffer++) { + app = *buffer; + *buffer = (app >> 16 & 0x000000ff) | (app << 16 & 0x00ff0000) | + (app & 0xff00ff00); + } } #endif -} // namespace +} // namespace GLubyte *memBuffer; @@ -40,159 +38,155 @@ GLubyte *memBuffer; //----------------------------------------------------------------------------- MacOfflineGL::MacOfflineGL(TDimension rasterSize, const TOfflineGL::Imp *shared) - : TOfflineGL::Imp(rasterSize.lx, rasterSize.ly), m_context(0), m_oldContext(0) -{ - createContext(rasterSize, shared); + : TOfflineGL::Imp(rasterSize.lx, rasterSize.ly) + , m_context(0) + , m_oldContext(0) { + createContext(rasterSize, shared); } //----------------------------------------------------------------------------- -MacOfflineGL::~MacOfflineGL() -{ - aglDestroyContext(m_context); -} +MacOfflineGL::~MacOfflineGL() { aglDestroyContext(m_context); } //----------------------------------------------------------------------------- -void MacOfflineGL::createContext(TDimension rasterSize, const TOfflineGL::Imp *shared) -{ - - GLint attribs[20], cnt = 0; - - //NOTE: AGL_OFFSCREEN *must* be selected - or it seems that gl surfaces are never destructed correctly! - //This may lead to a kernel panic! - - attribs[cnt++] = AGL_RGBA; - attribs[cnt++] = GL_TRUE; - attribs[cnt++] = AGL_PIXEL_SIZE; - attribs[cnt++] = 32; - attribs[cnt++] = AGL_BUFFER_SIZE; - attribs[cnt++] = 32; - attribs[cnt++] = AGL_STENCIL_SIZE; - attribs[cnt++] = 8; - attribs[cnt++] = AGL_DEPTH_SIZE; - attribs[cnt++] = 24; - attribs[cnt++] = AGL_OFFSCREEN; - attribs[cnt++] = AGL_ALPHA_SIZE; - attribs[cnt++] = 8; - attribs[cnt] = AGL_NONE; - - AGLPixelFormat fmt = aglChoosePixelFormat(0, 0, attribs); - - if (fmt == NULL) { - GLenum err = aglGetError(); - std::cout << "Unable to create a pixel format, AGLError = " << err << std::endl; - } - - m_context = aglCreateContext(fmt, NULL); - if (!m_context) { - GLenum err = aglGetError(); - /* - AGL_NO_ERROR 0 - AGL_BAD_ATTRIBUTE 10000 - AGL_BAD_PROPERTY 10001 - AGL_BAD_PIXELFMT 10002 - AGL_BAD_RENDINFO 10003 - AGL_BAD_CONTEXT 10004 - AGL_BAD_DRAWABLE 10005 - AGL_BAD_GDEV 10006 - AGL_BAD_STATE 10007 - AGL_BAD_VALUE 10008 - AGL_BAD_MATCH 10009 - AGL_BAD_ENUM 10010 - AGL_BAD_OFFSCREEN 10011 - AGL_BAD_FULLSCREEN 10012 - AGL_BAD_WINDOW 10013 - AGL_BAD_POINTER 10014 - AGL_BAD_MODULE 10015 - AGL_BAD_ALLOC 10016 - AGL_BAD_CONNECTION 10017 - */ - std::cout << "Unable to create an OpenGL Context, AGLError = " << err << std::endl; - } - - makeCurrent(); - - // Creo il pixel buffer - - GLboolean ret; - - AGLPbuffer pbuffer; - - ret = aglCreatePBuffer(rasterSize.lx, rasterSize.ly, GL_TEXTURE_RECTANGLE_EXT, GL_RGBA, 0, &pbuffer); - if (!ret) { - GLenum err = aglGetError(); - std::cout << "Unable to create a PBuffer, AGLError = " << err << std::endl; - } - - //memBuffer = new GLubyte[rasterSize.lx*rasterSize.ly*4]; - - ret = aglSetOffScreen(m_context, rasterSize.lx, rasterSize.ly, rasterSize.lx * 4, memBuffer); - - ret = aglSetPBuffer(m_context, pbuffer, 0, 0, 0); - if (!ret) { - GLenum err = aglGetError(); - std::cout << "Unable to set a PBuffer, AGLError = " << err << std::endl; - } - - // Non serve piu' - aglDestroyPixelFormat(fmt); +void MacOfflineGL::createContext(TDimension rasterSize, + const TOfflineGL::Imp *shared) { + GLint attribs[20], cnt = 0; + + // NOTE: AGL_OFFSCREEN *must* be selected - or it seems that gl surfaces are + // never destructed correctly! + // This may lead to a kernel panic! + + attribs[cnt++] = AGL_RGBA; + attribs[cnt++] = GL_TRUE; + attribs[cnt++] = AGL_PIXEL_SIZE; + attribs[cnt++] = 32; + attribs[cnt++] = AGL_BUFFER_SIZE; + attribs[cnt++] = 32; + attribs[cnt++] = AGL_STENCIL_SIZE; + attribs[cnt++] = 8; + attribs[cnt++] = AGL_DEPTH_SIZE; + attribs[cnt++] = 24; + attribs[cnt++] = AGL_OFFSCREEN; + attribs[cnt++] = AGL_ALPHA_SIZE; + attribs[cnt++] = 8; + attribs[cnt] = AGL_NONE; + + AGLPixelFormat fmt = aglChoosePixelFormat(0, 0, attribs); + + if (fmt == NULL) { + GLenum err = aglGetError(); + std::cout << "Unable to create a pixel format, AGLError = " << err + << std::endl; + } + + m_context = aglCreateContext(fmt, NULL); + if (!m_context) { + GLenum err = aglGetError(); + /* + AGL_NO_ERROR 0 + AGL_BAD_ATTRIBUTE 10000 + AGL_BAD_PROPERTY 10001 + AGL_BAD_PIXELFMT 10002 + AGL_BAD_RENDINFO 10003 + AGL_BAD_CONTEXT 10004 + AGL_BAD_DRAWABLE 10005 + AGL_BAD_GDEV 10006 + AGL_BAD_STATE 10007 + AGL_BAD_VALUE 10008 + AGL_BAD_MATCH 10009 + AGL_BAD_ENUM 10010 + AGL_BAD_OFFSCREEN 10011 + AGL_BAD_FULLSCREEN 10012 + AGL_BAD_WINDOW 10013 + AGL_BAD_POINTER 10014 + AGL_BAD_MODULE 10015 + AGL_BAD_ALLOC 10016 + AGL_BAD_CONNECTION 10017 +*/ + std::cout << "Unable to create an OpenGL Context, AGLError = " << err + << std::endl; + } + + makeCurrent(); + + // Creo il pixel buffer + + GLboolean ret; + + AGLPbuffer pbuffer; + + ret = aglCreatePBuffer(rasterSize.lx, rasterSize.ly, GL_TEXTURE_RECTANGLE_EXT, + GL_RGBA, 0, &pbuffer); + if (!ret) { + GLenum err = aglGetError(); + std::cout << "Unable to create a PBuffer, AGLError = " << err << std::endl; + } + + // memBuffer = new GLubyte[rasterSize.lx*rasterSize.ly*4]; + + ret = aglSetOffScreen(m_context, rasterSize.lx, rasterSize.ly, + rasterSize.lx * 4, memBuffer); + + ret = aglSetPBuffer(m_context, pbuffer, 0, 0, 0); + if (!ret) { + GLenum err = aglGetError(); + std::cout << "Unable to set a PBuffer, AGLError = " << err << std::endl; + } + + // Non serve piu' + aglDestroyPixelFormat(fmt); } //----------------------------------------------------------------------------- -void MacOfflineGL::makeCurrent() -{ - if (m_context) { - bool ret = aglSetCurrentContext(m_context); - if (ret == GL_FALSE) { - GLenum err = aglGetError(); - std::cout << "Unable to set current OpenGL Context, AGLError = " << err << std::endl; - } - } else - m_oldContext = 0; +void MacOfflineGL::makeCurrent() { + if (m_context) { + bool ret = aglSetCurrentContext(m_context); + if (ret == GL_FALSE) { + GLenum err = aglGetError(); + std::cout << "Unable to set current OpenGL Context, AGLError = " << err + << std::endl; + } + } else + m_oldContext = 0; } //----------------------------------------------------------------------------- -void MacOfflineGL::doneCurrent() -{ - if (aglGetCurrentContext() != m_context) - return; - aglSetCurrentContext(0); +void MacOfflineGL::doneCurrent() { + if (aglGetCurrentContext() != m_context) return; + aglSetCurrentContext(0); } //----------------------------------------------------------------------------- -void MacOfflineGL::saveCurrentContext() -{ - m_oldContext = aglGetCurrentContext(); +void MacOfflineGL::saveCurrentContext() { + m_oldContext = aglGetCurrentContext(); } //----------------------------------------------------------------------------- -void MacOfflineGL::restoreCurrentContext() -{ - if (m_oldContext) - aglSetCurrentContext(m_oldContext); - m_oldContext = 0; +void MacOfflineGL::restoreCurrentContext() { + if (m_oldContext) aglSetCurrentContext(m_oldContext); + m_oldContext = 0; } //----------------------------------------------------------------------------- -void MacOfflineGL::getRaster(TRaster32P raster) -{ - makeCurrent(); - glFinish(); +void MacOfflineGL::getRaster(TRaster32P raster) { + makeCurrent(); + glFinish(); - int lx = raster->getLx(); - int ly = raster->getLy(); + int lx = raster->getLx(); + int ly = raster->getLy(); - raster->lock(); + raster->lock(); - glReadPixels(0, 0, lx, ly, GL_RGBA, GL_UNSIGNED_BYTE, raster->getRawData()); + glReadPixels(0, 0, lx, ly, GL_RGBA, GL_UNSIGNED_BYTE, raster->getRawData()); - rightRotateBits(raster->getRawData(), lx * ly); + rightRotateBits(raster->getRawData(), lx * ly); - raster->unlock(); + raster->unlock(); } diff --git a/toonz/sources/common/tvrender/qtofflinegl.cpp b/toonz/sources/common/tvrender/qtofflinegl.cpp index e1484d9..6d46512 100644 --- a/toonz/sources/common/tvrender/qtofflinegl.cpp +++ b/toonz/sources/common/tvrender/qtofflinegl.cpp @@ -8,36 +8,38 @@ #ifdef _WIN32 -void swapRedBlueChannels(void *buffer, int bufferSize) // Flips The Red And Blue Bytes (WidthxHeight) +void swapRedBlueChannels( + void *buffer, + int bufferSize) // Flips The Red And Blue Bytes (WidthxHeight) { - void *b = buffer; // Pointer To The Buffer + void *b = buffer; // Pointer To The Buffer #ifdef x64 - int size = bufferSize; - UCHAR *pix = (UCHAR *)b; - while (size > 0) { - UCHAR r = *pix; - UCHAR b = *(pix + 2); - *pix = b; - *(pix + 2) = r; - pix += 4; - size--; - } + int size = bufferSize; + UCHAR *pix = (UCHAR *)b; + while (size > 0) { + UCHAR r = *pix; + UCHAR b = *(pix + 2); + *pix = b; + *(pix + 2) = r; + pix += 4; + size--; + } #else - __asm // Assembler Code To Follow - { - mov ecx, bufferSize // Counter Set To Dimensions Of Our Memory Block - mov ebx, b // Points ebx To Our Data (b) - label: // Label Used For Looping - mov al,[ebx+0] // Loads Value At ebx Into al - mov ah,[ebx+2] // Loads Value At ebx+2 Into ah - mov [ebx+2],al // Stores Value In al At ebx+2 - mov [ebx+0],ah // Stores Value In ah At ebx - - add ebx,4 // Moves Through The Data By 4 Bytes - dec ecx // Decreases Our Loop Counter - jnz label // If Not Zero Jump Back To Label - } + __asm // Assembler Code To Follow + { + mov ecx, bufferSize // Counter Set To Dimensions Of Our Memory Block + mov ebx, b // Points ebx To Our Data (b) + label: // Label Used For Looping + mov al,[ebx+0] // Loads Value At ebx Into al + mov ah,[ebx+2] // Loads Value At ebx+2 Into ah + mov [ebx+2],al // Stores Value In al At ebx+2 + mov [ebx+0],ah // Stores Value In ah At ebx + + add ebx,4 // Moves Through The Data By 4 Bytes + dec ecx // Decreases Our Loop Counter + jnz label // If Not Zero Jump Back To Label + } #endif } @@ -48,24 +50,23 @@ void swapRedBlueChannels(void *buffer, int bufferSize) // Flips The Red And Blue #if defined(MACOSX) #if defined(powerpc) -void rightRotateBits(UCHAR *buf, int bufferSize) -{ - UINT *buffer = (UINT *)buf; - UINT app; - for (int i = 0; i < bufferSize; i++, buffer++) { - app = *buffer; - *buffer = app >> 8 | app << 24; - } +void rightRotateBits(UCHAR *buf, int bufferSize) { + UINT *buffer = (UINT *)buf; + UINT app; + for (int i = 0; i < bufferSize; i++, buffer++) { + app = *buffer; + *buffer = app >> 8 | app << 24; + } } #else -void rightRotateBits(UCHAR *buf, int bufferSize) -{ - UINT *buffer = (UINT *)buf; - UINT app; - for (int i = 0; i < bufferSize; i++, buffer++) { - app = *buffer; - *buffer = (app >> 16 & 0x000000ff) | (app << 16 & 0x00ff0000) | (app & 0xff00ff00); - } +void rightRotateBits(UCHAR *buf, int bufferSize) { + UINT *buffer = (UINT *)buf; + UINT app; + for (int i = 0; i < bufferSize; i++, buffer++) { + app = *buffer; + *buffer = (app >> 16 & 0x000000ff) | (app << 16 & 0x00ff0000) | + (app & 0xff00ff00); + } } #endif #endif @@ -78,69 +79,68 @@ void rightRotateBits(UCHAR *buf, int bufferSize) //----------------------------------------------------------------------------- -QtOfflineGL::QtOfflineGL(TDimension rasterSize, std::shared_ptr shared) - : TOfflineGL::Imp(rasterSize.lx, rasterSize.ly) - , m_context(0) - , m_oldContext(0) -{ - createContext(rasterSize, std::move(shared)); - /* - makeCurrent(); +QtOfflineGL::QtOfflineGL(TDimension rasterSize, + std::shared_ptr shared) + : TOfflineGL::Imp(rasterSize.lx, rasterSize.ly) + , m_context(0) + , m_oldContext(0) { + createContext(rasterSize, std::move(shared)); + /* +makeCurrent(); - glClearColor(0.0f,0.0f,0.0f,0.0f); - glClear(GL_COLOR_BUFFER_BIT); +glClearColor(0.0f,0.0f,0.0f,0.0f); +glClear(GL_COLOR_BUFFER_BIT); - doneCurrent(); +doneCurrent(); */ } //----------------------------------------------------------------------------- -QtOfflineGL::~QtOfflineGL() -{ -} +QtOfflineGL::~QtOfflineGL() {} //----------------------------------------------------------------------------- -void QtOfflineGL::createContext(TDimension rasterSize, std::shared_ptr shared) -{ - // Imposto il formato dei Pixel (pixelFormat) - /* - 32, // 32-bit color depth - 0, 0, 0, 0, 0, 0, // color bits ignored - 8, // no alpha buffer - 0, // shift bit ignored - 0, // no accumulation buffer - 0, 0, 0, 0, // accum bits ignored - 32, // 32-bit z-buffer - 32, // max stencil buffer - 0, // no auxiliary buffer - PFD_MAIN_PLANE, // main layer - 0, // reserved - 0, 0, 0 // layer masks ignored - - ATTENZIONE !! SU MAC IL FORMATO E' DIVERSO (casomai possiamo mettere un ifdef) +void QtOfflineGL::createContext(TDimension rasterSize, + std::shared_ptr shared) { + // Imposto il formato dei Pixel (pixelFormat) + /* + 32, // 32-bit color depth + 0, 0, 0, 0, 0, 0, // color bits ignored + 8, // no alpha buffer + 0, // shift bit ignored + 0, // no accumulation buffer + 0, 0, 0, 0, // accum bits ignored + 32, // 32-bit z-buffer + 32, // max stencil buffer + 0, // no auxiliary buffer + PFD_MAIN_PLANE, // main layer + 0, // reserved + 0, 0, 0 // layer masks ignored + + ATTENZIONE !! SU MAC IL FORMATO E' DIVERSO (casomai possiamo mettere un + ifdef) + + SPECIFICHE MAC = depth_size 24, stencil_size 8, alpha_size 1 - SPECIFICHE MAC = depth_size 24, stencil_size 8, alpha_size 1 - - */ +*/ - QGLFormat fmt; + QGLFormat fmt; #ifdef _WIN32 - fmt.setAlphaBufferSize(8); - fmt.setAlpha(true); - fmt.setRgba(true); - fmt.setDepthBufferSize(32); - fmt.setDepth(true); - fmt.setStencilBufferSize(32); - fmt.setStencil(true); - fmt.setAccum(false); - fmt.setPlane(0); + fmt.setAlphaBufferSize(8); + fmt.setAlpha(true); + fmt.setRgba(true); + fmt.setDepthBufferSize(32); + fmt.setDepth(true); + fmt.setStencilBufferSize(32); + fmt.setStencil(true); + fmt.setAccum(false); + fmt.setPlane(0); #elif MACOSX - fmt = QGLFormat::defaultFormat(); - //printf("GL Version: %s\n",glGetString(GL_VERSION)); - fmt.setVersion(2, 1); /* OSX10.8 では 3.2 だめかも */ + fmt = QGLFormat::defaultFormat(); + // printf("GL Version: %s\n",glGetString(GL_VERSION)); + fmt.setVersion(2, 1); /* OSX10.8 では 3.2 だめかも */ #if 0 fmt.setAlphaBufferSize(8); fmt.setAlpha(true); @@ -155,216 +155,206 @@ void QtOfflineGL::createContext(TDimension rasterSize, std::shared_ptr(); - m_surface->setFormat(format); - m_surface->create(); + m_surface = std::make_shared(); + m_surface->setFormat(format); + m_surface->create(); - m_context = std::make_shared(); - m_context->setFormat(format); - m_context->create(); - m_context->makeCurrent(m_surface.get()); + m_context = std::make_shared(); + m_context->setFormat(format); + m_context->create(); + m_context->makeCurrent(m_surface.get()); - QOpenGLFramebufferObjectFormat fbo_format; - m_fbo = std::make_shared(rasterSize.lx, rasterSize.ly, fbo_format); - m_fbo->bind(); + QOpenGLFramebufferObjectFormat fbo_format; + m_fbo = std::make_shared(rasterSize.lx, + rasterSize.ly, fbo_format); + m_fbo->bind(); - printf("create context:%p [thread:0x%x]\n", m_context.get(), QThread::currentThreadId()); - - // Creo il contesto OpenGL - assicurandomi che sia effettivamente creato - // NOTA: Se il contesto non viene creato, di solito basta ritentare qualche volta. + printf("create context:%p [thread:0x%x]\n", m_context.get(), + QThread::currentThreadId()); + // Creo il contesto OpenGL - assicurandomi che sia effettivamente creato + // NOTA: Se il contesto non viene creato, di solito basta ritentare qualche + // volta. } //----------------------------------------------------------------------------- -void QtOfflineGL::makeCurrent() -{ - if (m_context) { - m_context->moveToThread(QThread::currentThread()); - m_context->makeCurrent(m_surface.get()); - } - // else - // m_oldContext = 0; +void QtOfflineGL::makeCurrent() { + if (m_context) { + m_context->moveToThread(QThread::currentThread()); + m_context->makeCurrent(m_surface.get()); + } + // else + // m_oldContext = 0; } //----------------------------------------------------------------------------- -void QtOfflineGL::doneCurrent() -{ - if (m_context) { - m_context->doneCurrent(); - } +void QtOfflineGL::doneCurrent() { + if (m_context) { + m_context->doneCurrent(); + } } //----------------------------------------------------------------------------- -void QtOfflineGL::saveCurrentContext() -{ - // m_oldContext = const_cast(QGLContext::currentContext()); +void QtOfflineGL::saveCurrentContext() { + // m_oldContext = const_cast(QGLContext::currentContext()); } //----------------------------------------------------------------------------- -void QtOfflineGL::restoreCurrentContext() -{ - // if(m_oldContext) m_oldContext->makeCurrent(); - // m_oldContext = 0; +void QtOfflineGL::restoreCurrentContext() { + // if(m_oldContext) m_oldContext->makeCurrent(); + // m_oldContext = 0; } //----------------------------------------------------------------------------- -void QtOfflineGL::getRaster(TRaster32P raster) -{ - makeCurrent(); - glFlush(); +void QtOfflineGL::getRaster(TRaster32P raster) { + makeCurrent(); + glFlush(); - int lx = raster->getLx(); - int ly = raster->getLy(); + int lx = raster->getLx(); + int ly = raster->getLy(); - raster->lock(); - raster->copy( TRaster32P(lx, ly, m_fbo->width(), (TPixelRGBM32 *)m_fbo->toImage(false).bits(), false) ); - raster->unlock(); + raster->lock(); + raster->copy(TRaster32P(lx, ly, m_fbo->width(), + (TPixelRGBM32 *)m_fbo->toImage(false).bits(), false)); + raster->unlock(); } -//QGLPixelBuffer::hasOpenGLPbuffers() (statica) -> true se la scheda supporta i PBuffer +// QGLPixelBuffer::hasOpenGLPbuffers() (statica) -> true se la scheda supporta i +// PBuffer //============================================================================= // QtOfflineGLPBuffer : implem. offlineGL usando QT e PBuffer //----------------------------------------------------------------------------- QtOfflineGLPBuffer::QtOfflineGLPBuffer(TDimension rasterSize) - : TOfflineGL::Imp(rasterSize.lx, rasterSize.ly), m_context(0) -{ - createContext(rasterSize); + : TOfflineGL::Imp(rasterSize.lx, rasterSize.ly), m_context(0) { + createContext(rasterSize); - makeCurrent(); + makeCurrent(); - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); - doneCurrent(); + doneCurrent(); } //----------------------------------------------------------------------------- -QtOfflineGLPBuffer::~QtOfflineGLPBuffer() -{ -} +QtOfflineGLPBuffer::~QtOfflineGLPBuffer() {} //----------------------------------------------------------------------------- -void QtOfflineGLPBuffer::createContext(TDimension rasterSize) -{ - // Imposto il formato dei Pixel (pixelFormat) - /* - 32, // 32-bit color depth - 0, 0, 0, 0, 0, 0, // color bits ignored - 8, // no alpha buffer - 0, // shift bit ignored - 0, // no accumulation buffer - 0, 0, 0, 0, // accum bits ignored - 32, // 32-bit z-buffer - 32, // max stencil buffer - 0, // no auxiliary buffer - PFD_MAIN_PLANE, // main layer - 0, // reserved - 0, 0, 0 // layer masks ignored - - ATTENZIONE !! SU MAC IL FORMATO E' DIVERSO (casomai possiamo mettere un ifdef) +void QtOfflineGLPBuffer::createContext(TDimension rasterSize) { + // Imposto il formato dei Pixel (pixelFormat) + /* +32, // 32-bit color depth +0, 0, 0, 0, 0, 0, // color bits ignored +8, // no alpha buffer +0, // shift bit ignored +0, // no accumulation buffer +0, 0, 0, 0, // accum bits ignored +32, // 32-bit z-buffer +32, // max stencil buffer +0, // no auxiliary buffer +PFD_MAIN_PLANE, // main layer +0, // reserved +0, 0, 0 // layer masks ignored + +ATTENZIONE !! SU MAC IL FORMATO E' DIVERSO (casomai possiamo mettere un ifdef) + +SPECIFICHE MAC = depth_size 24, stencil_size 8, alpha_size 1 - SPECIFICHE MAC = depth_size 24, stencil_size 8, alpha_size 1 - - */ +*/ - QGLFormat fmt; + QGLFormat fmt; #ifdef _WIN32 - fmt.setAlphaBufferSize(8); - fmt.setAlpha(false); - fmt.setRgba(true); - fmt.setDepthBufferSize(32); - fmt.setDepth(true); - fmt.setStencilBufferSize(32); - fmt.setStencil(true); - fmt.setAccum(false); - fmt.setPlane(0); + fmt.setAlphaBufferSize(8); + fmt.setAlpha(false); + fmt.setRgba(true); + fmt.setDepthBufferSize(32); + fmt.setDepth(true); + fmt.setStencilBufferSize(32); + fmt.setStencil(true); + fmt.setAccum(false); + fmt.setPlane(0); #elif MACOSX - fmt.setAlphaBufferSize(1); - fmt.setAlpha(false); - fmt.setRgba(true); - fmt.setDepthBufferSize(24); - fmt.setDepth(true); - fmt.setStencilBufferSize(8); - fmt.setStencil(true); - fmt.setAccum(false); - fmt.setPlane(0); + fmt.setAlphaBufferSize(1); + fmt.setAlpha(false); + fmt.setRgba(true); + fmt.setDepthBufferSize(24); + fmt.setDepth(true); + fmt.setStencilBufferSize(8); + fmt.setStencil(true); + fmt.setAccum(false); + fmt.setPlane(0); #endif - // Il PixelBuffer deve essere con width ed height potenze di 2 + // Il PixelBuffer deve essere con width ed height potenze di 2 - int sizeMax = std::max(rasterSize.lx, rasterSize.ly); + int sizeMax = std::max(rasterSize.lx, rasterSize.ly); - // trovo la potenza di 2 che "contiene" sizeMax e la utilizzo per il PBuffer - int pBufferSize = 2; - while (pBufferSize < sizeMax) - pBufferSize *= 2; + // trovo la potenza di 2 che "contiene" sizeMax e la utilizzo per il PBuffer + int pBufferSize = 2; + while (pBufferSize < sizeMax) pBufferSize *= 2; - m_context = std::make_shared(QSize(pBufferSize, pBufferSize), fmt); + m_context = + std::make_shared(QSize(pBufferSize, pBufferSize), fmt); } //----------------------------------------------------------------------------- -void QtOfflineGLPBuffer::makeCurrent() -{ - if (m_context){ - m_context->makeCurrent(); - } +void QtOfflineGLPBuffer::makeCurrent() { + if (m_context) { + m_context->makeCurrent(); + } } //----------------------------------------------------------------------------- -void QtOfflineGLPBuffer::doneCurrent() -{ - if (m_context) - m_context->doneCurrent(); +void QtOfflineGLPBuffer::doneCurrent() { + if (m_context) m_context->doneCurrent(); } //----------------------------------------------------------------------------- -void QtOfflineGLPBuffer::getRaster(TRaster32P raster) -{ - makeCurrent(); - glFlush(); - - //The image is stored using a 32-bit ARGB format (0xAARRGGBB). - QImage image = m_context->toImage(); - - int lx = raster->getLx(), ly = raster->getLy(); - - static const TRaster32P emptyRaster; - if (image.height() == 0 || image.width() == 0) - return; - - // devo iniziare a leggere la Y da un certo offset - // dato dalla differenza tra la y della image e la y del raster - int yOffset = image.height() - ly; - raster->lock(); - - for (int y = 0; y < ly; y++) { - QRgb *inpPix = (QRgb *)image.scanLine(yOffset + y); - - TPixel32 *pix = raster->pixels(ly - 1 - y); - TPixel32 *endPix = pix + lx; - - for (; pix < endPix; ++pix) { - pix->m = 255; - pix->r = qRed(*inpPix); - pix->g = qGreen(*inpPix); - pix->b = qBlue(*inpPix); - inpPix++; - } - } - raster->unlock(); +void QtOfflineGLPBuffer::getRaster(TRaster32P raster) { + makeCurrent(); + glFlush(); + + // The image is stored using a 32-bit ARGB format (0xAARRGGBB). + QImage image = m_context->toImage(); + + int lx = raster->getLx(), ly = raster->getLy(); + + static const TRaster32P emptyRaster; + if (image.height() == 0 || image.width() == 0) return; + + // devo iniziare a leggere la Y da un certo offset + // dato dalla differenza tra la y della image e la y del raster + int yOffset = image.height() - ly; + raster->lock(); + + for (int y = 0; y < ly; y++) { + QRgb *inpPix = (QRgb *)image.scanLine(yOffset + y); + + TPixel32 *pix = raster->pixels(ly - 1 - y); + TPixel32 *endPix = pix + lx; + + for (; pix < endPix; ++pix) { + pix->m = 255; + pix->r = qRed(*inpPix); + pix->g = qGreen(*inpPix); + pix->b = qBlue(*inpPix); + inpPix++; + } + } + raster->unlock(); } diff --git a/toonz/sources/common/tvrender/tcolorstyles.cpp b/toonz/sources/common/tvrender/tcolorstyles.cpp index 2dcfe89..6c1813f 100644 --- a/toonz/sources/common/tvrender/tcolorstyles.cpp +++ b/toonz/sources/common/tvrender/tcolorstyles.cpp @@ -17,17 +17,17 @@ //***************************************************************************** #ifndef checkErrorsByGL -#define checkErrorsByGL \ - { \ - GLenum err = glGetError(); \ - assert(err != GL_INVALID_ENUM); \ - assert(err != GL_INVALID_VALUE); \ - assert(err != GL_INVALID_OPERATION); \ - assert(err != GL_STACK_OVERFLOW); \ - assert(err != GL_STACK_UNDERFLOW); \ - assert(err != GL_OUT_OF_MEMORY); \ - assert(err == GL_NO_ERROR); \ - } +#define checkErrorsByGL \ + { \ + GLenum err = glGetError(); \ + assert(err != GL_INVALID_ENUM); \ + assert(err != GL_INVALID_VALUE); \ + assert(err != GL_INVALID_OPERATION); \ + assert(err != GL_STACK_OVERFLOW); \ + assert(err != GL_STACK_UNDERFLOW); \ + assert(err != GL_OUT_OF_MEMORY); \ + assert(err == GL_NO_ERROR); \ + } #endif #undef checkErrorsByGL @@ -42,327 +42,321 @@ int TColorStyle::m_currentFrame = 0; //------------------------------------------------------------------- TColorStyle::TColorStyle() - : m_name(L"color"), m_globalName(L""), m_originalName(L""), m_versionNumber(0), m_flags(0), m_enabled(true), m_icon(0), m_validIcon(false), m_isEditedFromOriginal(false) -{ -} + : m_name(L"color") + , m_globalName(L"") + , m_originalName(L"") + , m_versionNumber(0) + , m_flags(0) + , m_enabled(true) + , m_icon(0) + , m_validIcon(false) + , m_isEditedFromOriginal(false) {} //------------------------------------------------------------------- -TColorStyle::~TColorStyle() -{ -} +TColorStyle::~TColorStyle() {} //------------------------------------------------------------------- TColorStyle::TColorStyle(const TColorStyle &other) - : m_name(other.m_name), m_globalName(other.m_globalName), m_originalName(other.m_originalName), m_versionNumber(other.m_versionNumber), m_flags(other.m_flags), m_enabled(other.m_enabled), m_validIcon(false), m_isEditedFromOriginal(other.m_isEditedFromOriginal) -{ -} + : m_name(other.m_name) + , m_globalName(other.m_globalName) + , m_originalName(other.m_originalName) + , m_versionNumber(other.m_versionNumber) + , m_flags(other.m_flags) + , m_enabled(other.m_enabled) + , m_validIcon(false) + , m_isEditedFromOriginal(other.m_isEditedFromOriginal) {} //------------------------------------------------------------------- -TColorStyle &TColorStyle::operator=(const TColorStyle &other) -{ - m_name = other.m_name; - m_globalName = other.m_globalName; - m_originalName = other.m_originalName; - m_versionNumber = other.m_versionNumber; - m_flags = other.m_flags; - m_enabled = other.m_enabled; - m_validIcon = false; - m_isEditedFromOriginal = other.m_isEditedFromOriginal; - - return *this; +TColorStyle &TColorStyle::operator=(const TColorStyle &other) { + m_name = other.m_name; + m_globalName = other.m_globalName; + m_originalName = other.m_originalName; + m_versionNumber = other.m_versionNumber; + m_flags = other.m_flags; + m_enabled = other.m_enabled; + m_validIcon = false; + m_isEditedFromOriginal = other.m_isEditedFromOriginal; + + return *this; } //------------------------------------------------------------------- -bool TColorStyle::operator==(const TColorStyle &cs) const -{ - if (getTagId() != cs.getTagId()) - return false; - - if (getMainColor() != cs.getMainColor()) - return false; - - int paramCount = getParamCount(); - if (paramCount != cs.getParamCount()) - return false; - - int colorParamCount = getColorParamCount(); - if (colorParamCount != cs.getColorParamCount()) - return false; - - if (m_name != cs.getName()) - return false; - if (m_originalName != cs.getOriginalName()) - return false; - if (m_globalName != cs.getGlobalName()) - return false; - if (m_isEditedFromOriginal != cs.getIsEditedFlag()) - return false; - - for (int p = 0; p < colorParamCount; ++p) - if (getColorParamValue(p) != cs.getColorParamValue(p)) - return false; - - for (int p = 0; p < paramCount; ++p) { - switch (getParamType(p)) { - case BOOL: - if (getParamValue(bool_tag(), p) != cs.getParamValue(bool_tag(), p)) - return false; - break; - case INT: - case ENUM: - if (getParamValue(int_tag(), p) != cs.getParamValue(int_tag(), p)) - return false; - break; - case DOUBLE: - if (getParamValue(double_tag(), p) != cs.getParamValue(double_tag(), p)) - return false; - break; - case FILEPATH: - if (getParamValue(TFilePath_tag(), p) != cs.getParamValue(TFilePath_tag(), p)) - return false; - break; - default: - assert(false); - } - } - - return true; +bool TColorStyle::operator==(const TColorStyle &cs) const { + if (getTagId() != cs.getTagId()) return false; + + if (getMainColor() != cs.getMainColor()) return false; + + int paramCount = getParamCount(); + if (paramCount != cs.getParamCount()) return false; + + int colorParamCount = getColorParamCount(); + if (colorParamCount != cs.getColorParamCount()) return false; + + if (m_name != cs.getName()) return false; + if (m_originalName != cs.getOriginalName()) return false; + if (m_globalName != cs.getGlobalName()) return false; + if (m_isEditedFromOriginal != cs.getIsEditedFlag()) return false; + + for (int p = 0; p < colorParamCount; ++p) + if (getColorParamValue(p) != cs.getColorParamValue(p)) return false; + + for (int p = 0; p < paramCount; ++p) { + switch (getParamType(p)) { + case BOOL: + if (getParamValue(bool_tag(), p) != cs.getParamValue(bool_tag(), p)) + return false; + break; + case INT: + case ENUM: + if (getParamValue(int_tag(), p) != cs.getParamValue(int_tag(), p)) + return false; + break; + case DOUBLE: + if (getParamValue(double_tag(), p) != cs.getParamValue(double_tag(), p)) + return false; + break; + case FILEPATH: + if (getParamValue(TFilePath_tag(), p) != + cs.getParamValue(TFilePath_tag(), p)) + return false; + break; + default: + assert(false); + } + } + + return true; } //------------------------------------------------------------------- -QString TColorStyle::getParamNames(int index) const -{ - assert(false); - return QString(""); +QString TColorStyle::getParamNames(int index) const { + assert(false); + return QString(""); } //------------------------------------------------------------------- -void TColorStyle::updateVersionNumber() -{ - ++m_versionNumber; -} +void TColorStyle::updateVersionNumber() { ++m_versionNumber; } //------------------------------------------------------------------- -const TRaster32P &TColorStyle::getIcon(const TDimension &d) -{ - checkErrorsByGL; - if (!m_validIcon || !m_icon || m_icon->getSize() != d) { - checkErrorsByGL; - makeIcon(d); - checkErrorsByGL; - m_validIcon = true; - } - checkErrorsByGL; - - if (!m_icon) { - checkErrorsByGL; - TRaster32P icon(d); - checkErrorsByGL; - icon->fill(TPixel32::Black); - checkErrorsByGL; - int lx = icon->getLx(); - checkErrorsByGL; - int ly = icon->getLy(); - checkErrorsByGL; - for (int y = 0; y < ly; y++) { - checkErrorsByGL; - int x = ((lx - 1 - 10) * y / ly); - checkErrorsByGL; - icon->extractT(x, y, x + 5, y)->fill(TPixel32::Red); - checkErrorsByGL; - } - checkErrorsByGL; - m_icon = icon; - checkErrorsByGL; - } - return m_icon; +const TRaster32P &TColorStyle::getIcon(const TDimension &d) { + checkErrorsByGL; + if (!m_validIcon || !m_icon || m_icon->getSize() != d) { + checkErrorsByGL; + makeIcon(d); + checkErrorsByGL; + m_validIcon = true; + } + checkErrorsByGL; + + if (!m_icon) { + checkErrorsByGL; + TRaster32P icon(d); + checkErrorsByGL; + icon->fill(TPixel32::Black); + checkErrorsByGL; + int lx = icon->getLx(); + checkErrorsByGL; + int ly = icon->getLy(); + checkErrorsByGL; + for (int y = 0; y < ly; y++) { + checkErrorsByGL; + int x = ((lx - 1 - 10) * y / ly); + checkErrorsByGL; + icon->extractT(x, y, x + 5, y)->fill(TPixel32::Red); + checkErrorsByGL; + } + checkErrorsByGL; + m_icon = icon; + checkErrorsByGL; + } + return m_icon; } //------------------------------------------------------------------- -void TColorStyle::makeIcon(const TDimension &d) -{ - checkErrorsByGL; - TColorStyle *style = this->clone(); - checkErrorsByGL; - - TPaletteP tmpPalette = new TPalette(); - checkErrorsByGL; - int id = tmpPalette->addStyle(style); - checkErrorsByGL; - - int contextLx = pow(2.0, tceil(log((double)d.lx) / log(2.0))); - int contextLy = pow(2.0, tceil(log((double)d.ly) / log(2.0))); - TDimension dim(contextLx, contextLy); - - TOfflineGL *glContext = TOfflineGL::getStock(dim); - - checkErrorsByGL; - glContext->clear(TPixel32::White); - checkErrorsByGL; - - TVectorImageP img = new TVectorImage; - checkErrorsByGL; - img->setPalette(tmpPalette.getPointer()); - checkErrorsByGL; - - std::vector points(3); - - if (isRegionStyle() && !isStrokeStyle()) { - points[0] = TThickPoint(-55, -50, 1); - points[1] = TThickPoint(0, -60, 1); - points[2] = TThickPoint(55, -50, 1); - TStroke *stroke1 = new TStroke(points); - - img->addStroke(stroke1); - - points[0] = TThickPoint(50, -55, 1); - points[1] = TThickPoint(60, 0, 1); - points[2] = TThickPoint(50, 55, 1); - TStroke *stroke2 = new TStroke(points); - img->addStroke(stroke2); - - points[0] = TThickPoint(55, 50, 1); - points[1] = TThickPoint(0, 60, 1); - points[2] = TThickPoint(-55, 50, 1); - TStroke *stroke3 = new TStroke(points); - img->addStroke(stroke3); - - points[0] = TThickPoint(-50, 55, 1); - points[1] = TThickPoint(-60, 0, 1); - points[2] = TThickPoint(-50, -55, 1); - TStroke *stroke4 = new TStroke(points); - img->addStroke(stroke4); - - img->fill(TPointD(0, 0), id); - } else if (isStrokeStyle() && !isRegionStyle()) { - - double rasX05 = d.lx * 0.5; - double rasY05 = d.ly * 0.5; - - points[0] = TThickPoint(-rasX05, -rasY05, 7); - points[1] = TThickPoint(0, -rasY05, 9); - points[2] = TThickPoint(rasX05, rasY05, 12); - TStroke *stroke1 = new TStroke(points); - - stroke1->setStyle(id); - - img->addStroke(stroke1); - points.clear(); - } else if (!isRasterStyle()) { - assert(isStrokeStyle() && isRegionStyle()); - - points[0] = TThickPoint(-60, -30, 0.5); - points[1] = TThickPoint(0, -30, 0.5); - points[2] = TThickPoint(60, -30, 0.5); - TStroke *stroke1 = new TStroke(points); - stroke1->setStyle(id); - img->addStroke(stroke1); - - points[0] = TThickPoint(60, -30, 0.5); - points[1] = TThickPoint(60, 0, 0.5); - points[2] = TThickPoint(60, 30, 0.5); - TStroke *stroke2 = new TStroke(points); - stroke2->setStyle(id); - img->addStroke(stroke2); - - points[0] = TThickPoint(60, 30, 0.5); - points[1] = TThickPoint(0, 30, 0.5); - points[2] = TThickPoint(-60, 30, 0.5); - TStroke *stroke3 = new TStroke(points); - stroke3->setStyle(id); - img->addStroke(stroke3); - - points[0] = TThickPoint(-60, 30, 0.5); - points[1] = TThickPoint(-60, 0, 0.5); - points[2] = TThickPoint(-60, -30, 0.5); - TStroke *stroke4 = new TStroke(points); - stroke4->setStyle(id); - img->addStroke(stroke4); - - img->fill(TPointD(0, 0), id); - } - - TRectD bbox = img->getBBox(); - checkErrorsByGL; - - bbox = bbox.enlarge(TDimensionD(-10, -10)); - checkErrorsByGL; - - double scx = 0.9 * d.lx / bbox.getLx(); - double scy = 0.9 * d.ly / bbox.getLy(); - double sc = std::min(scx, scy); - double dx = (d.lx - bbox.getLx() * sc) * 0.5; - double dy = (d.ly - bbox.getLy() * sc) * 0.5; - TAffine aff = TScale(scx, scy) * TTranslation(-bbox.getP00() + TPointD(dx, dy)); - - checkErrorsByGL; - if (isRegionStyle() && !isStrokeStyle()) - aff = aff * TTranslation(-10, -10); - - checkErrorsByGL; - const TVectorRenderData rd(aff, TRect(), tmpPalette.getPointer(), 0, true); - checkErrorsByGL; - glContext->draw(img, rd); - checkErrorsByGL; - - TRect rect(d); - if (!m_icon || m_icon->getSize() != d) { - checkErrorsByGL; - m_icon = glContext->getRaster()->extract(rect)->clone(); - } else { - checkErrorsByGL; - m_icon->copy(glContext->getRaster()->extract(rect)); - } +void TColorStyle::makeIcon(const TDimension &d) { + checkErrorsByGL; + TColorStyle *style = this->clone(); + checkErrorsByGL; + + TPaletteP tmpPalette = new TPalette(); + checkErrorsByGL; + int id = tmpPalette->addStyle(style); + checkErrorsByGL; + + int contextLx = pow(2.0, tceil(log((double)d.lx) / log(2.0))); + int contextLy = pow(2.0, tceil(log((double)d.ly) / log(2.0))); + TDimension dim(contextLx, contextLy); + + TOfflineGL *glContext = TOfflineGL::getStock(dim); + + checkErrorsByGL; + glContext->clear(TPixel32::White); + checkErrorsByGL; + + TVectorImageP img = new TVectorImage; + checkErrorsByGL; + img->setPalette(tmpPalette.getPointer()); + checkErrorsByGL; + + std::vector points(3); + + if (isRegionStyle() && !isStrokeStyle()) { + points[0] = TThickPoint(-55, -50, 1); + points[1] = TThickPoint(0, -60, 1); + points[2] = TThickPoint(55, -50, 1); + TStroke *stroke1 = new TStroke(points); + + img->addStroke(stroke1); + + points[0] = TThickPoint(50, -55, 1); + points[1] = TThickPoint(60, 0, 1); + points[2] = TThickPoint(50, 55, 1); + TStroke *stroke2 = new TStroke(points); + img->addStroke(stroke2); + + points[0] = TThickPoint(55, 50, 1); + points[1] = TThickPoint(0, 60, 1); + points[2] = TThickPoint(-55, 50, 1); + TStroke *stroke3 = new TStroke(points); + img->addStroke(stroke3); + + points[0] = TThickPoint(-50, 55, 1); + points[1] = TThickPoint(-60, 0, 1); + points[2] = TThickPoint(-50, -55, 1); + TStroke *stroke4 = new TStroke(points); + img->addStroke(stroke4); + + img->fill(TPointD(0, 0), id); + } else if (isStrokeStyle() && !isRegionStyle()) { + double rasX05 = d.lx * 0.5; + double rasY05 = d.ly * 0.5; + + points[0] = TThickPoint(-rasX05, -rasY05, 7); + points[1] = TThickPoint(0, -rasY05, 9); + points[2] = TThickPoint(rasX05, rasY05, 12); + TStroke *stroke1 = new TStroke(points); + + stroke1->setStyle(id); + + img->addStroke(stroke1); + points.clear(); + } else if (!isRasterStyle()) { + assert(isStrokeStyle() && isRegionStyle()); + + points[0] = TThickPoint(-60, -30, 0.5); + points[1] = TThickPoint(0, -30, 0.5); + points[2] = TThickPoint(60, -30, 0.5); + TStroke *stroke1 = new TStroke(points); + stroke1->setStyle(id); + img->addStroke(stroke1); + + points[0] = TThickPoint(60, -30, 0.5); + points[1] = TThickPoint(60, 0, 0.5); + points[2] = TThickPoint(60, 30, 0.5); + TStroke *stroke2 = new TStroke(points); + stroke2->setStyle(id); + img->addStroke(stroke2); + + points[0] = TThickPoint(60, 30, 0.5); + points[1] = TThickPoint(0, 30, 0.5); + points[2] = TThickPoint(-60, 30, 0.5); + TStroke *stroke3 = new TStroke(points); + stroke3->setStyle(id); + img->addStroke(stroke3); + + points[0] = TThickPoint(-60, 30, 0.5); + points[1] = TThickPoint(-60, 0, 0.5); + points[2] = TThickPoint(-60, -30, 0.5); + TStroke *stroke4 = new TStroke(points); + stroke4->setStyle(id); + img->addStroke(stroke4); + + img->fill(TPointD(0, 0), id); + } + + TRectD bbox = img->getBBox(); + checkErrorsByGL; + + bbox = bbox.enlarge(TDimensionD(-10, -10)); + checkErrorsByGL; + + double scx = 0.9 * d.lx / bbox.getLx(); + double scy = 0.9 * d.ly / bbox.getLy(); + double sc = std::min(scx, scy); + double dx = (d.lx - bbox.getLx() * sc) * 0.5; + double dy = (d.ly - bbox.getLy() * sc) * 0.5; + TAffine aff = + TScale(scx, scy) * TTranslation(-bbox.getP00() + TPointD(dx, dy)); + + checkErrorsByGL; + if (isRegionStyle() && !isStrokeStyle()) aff = aff * TTranslation(-10, -10); + + checkErrorsByGL; + const TVectorRenderData rd(aff, TRect(), tmpPalette.getPointer(), 0, true); + checkErrorsByGL; + glContext->draw(img, rd); + checkErrorsByGL; + + TRect rect(d); + if (!m_icon || m_icon->getSize() != d) { + checkErrorsByGL; + m_icon = glContext->getRaster()->extract(rect)->clone(); + } else { + checkErrorsByGL; + m_icon->copy(glContext->getRaster()->extract(rect)); + } } //------------------------------------------------------------------- -void TColorStyle::assignNames(const TColorStyle *src) -{ - m_name = src->getName(); - m_globalName = src->getGlobalName(); - m_originalName = src->getOriginalName(); - m_isEditedFromOriginal = src->getIsEditedFlag(); +void TColorStyle::assignNames(const TColorStyle *src) { + m_name = src->getName(); + m_globalName = src->getGlobalName(); + m_originalName = src->getOriginalName(); + m_isEditedFromOriginal = src->getIsEditedFlag(); } //------------------------------------------------------------------- -void TColorStyle::assignBlend(const TColorStyle &a, const TColorStyle &b, double t) -{ - // Blend colors - { - int col, colCount = getColorParamCount(); - assert(a.getColorParamCount() == colCount && b.getColorParamCount() == colCount); - - for (col = 0; col != colCount; ++col) - setColorParamValue(col, blend(a.getColorParamValue(col), b.getColorParamValue(col), t)); - } - - // Blend parameters - { - int par, parCount = getParamCount(); - assert(a.getParamCount() == parCount && b.getParamCount() == parCount); - - for (par = 0; par != parCount; ++par) { - switch (getParamType(par)) { - case DOUBLE: - setParamValue(par, (1 - t) * a.getParamValue(double_tag(), par) + t * b.getParamValue(double_tag(), par)); - break; - default: - break; - } - } - } - - invalidateIcon(); +void TColorStyle::assignBlend(const TColorStyle &a, const TColorStyle &b, + double t) { + // Blend colors + { + int col, colCount = getColorParamCount(); + assert(a.getColorParamCount() == colCount && + b.getColorParamCount() == colCount); + + for (col = 0; col != colCount; ++col) + setColorParamValue( + col, blend(a.getColorParamValue(col), b.getColorParamValue(col), t)); + } + + // Blend parameters + { + int par, parCount = getParamCount(); + assert(a.getParamCount() == parCount && b.getParamCount() == parCount); + + for (par = 0; par != parCount; ++par) { + switch (getParamType(par)) { + case DOUBLE: + setParamValue(par, (1 - t) * a.getParamValue(double_tag(), par) + + t * b.getParamValue(double_tag(), par)); + break; + default: + break; + } + } + } + + invalidateIcon(); } //=================================================================== @@ -371,161 +365,147 @@ void TColorStyle::assignBlend(const TColorStyle &a, const TColorStyle &b, double // //=================================================================== -namespace -{ +namespace { -class ColorStyleList -{ // singleton - ColorStyleList() {} +class ColorStyleList { // singleton + ColorStyleList() {} - struct Item { - TColorStyle *m_style; - bool m_isObsolete; - // Item() : m_style(0), m_isObsolete(false) { assert(0); } - Item(TColorStyle *style, bool obsolete = false) - : m_style(style), m_isObsolete(obsolete) {} - }; + struct Item { + TColorStyle *m_style; + bool m_isObsolete; + // Item() : m_style(0), m_isObsolete(false) { assert(0); } + Item(TColorStyle *style, bool obsolete = false) + : m_style(style), m_isObsolete(obsolete) {} + }; - typedef std::map Table; - Table m_table; + typedef std::map Table; + Table m_table; public: - static ColorStyleList *instance() - { - static ColorStyleList *_instance = 0; - if (!_instance) - _instance = new ColorStyleList(); - return _instance; - } - - int getStyleCount() - { - return int(m_table.size()); - } - - void declare(TColorStyle *style) - { - int id = style->getTagId(); - if (m_table.find(id) != m_table.end()) { - throw TException("Duplicate color style declaration. id = " + std::to_string(id)); - } - m_table.insert(std::make_pair(id, Item(style))); - std::vector ids; - style->getObsoleteTagIds(ids); - for (std::vector::iterator it = ids.begin(); it != ids.end(); ++it) { - if (m_table.find(*it) != m_table.end()) { - throw TException("Duplicate color style declaration for obsolete style. id = " + std::to_string(*it)); - } - m_table.insert(std::make_pair(*it, Item(style->clone(), true))); - } - } - - TColorStyle *create(int id, bool &isObsolete) - { - Table::iterator it = m_table.find(id); - if (it == m_table.end()) - throw TException("Unknown color style id; id = " + std::to_string(id)); - - isObsolete = it->second.m_isObsolete; - - return it->second.m_style->clone(); - } - - void getAllTags(std::vector &tags) - { - tags.clear(); - tags.reserve(m_table.size()); - for (Table::iterator it = m_table.begin(); - it != m_table.end(); ++it) - if (!it->second.m_isObsolete) - tags.push_back(it->first); - } - - ~ColorStyleList() - { - Table::iterator it = m_table.begin(); - for (; it != m_table.end(); ++it) { - delete it->second.m_style; - } - } + static ColorStyleList *instance() { + static ColorStyleList *_instance = 0; + if (!_instance) _instance = new ColorStyleList(); + return _instance; + } + + int getStyleCount() { return int(m_table.size()); } + + void declare(TColorStyle *style) { + int id = style->getTagId(); + if (m_table.find(id) != m_table.end()) { + throw TException("Duplicate color style declaration. id = " + + std::to_string(id)); + } + m_table.insert(std::make_pair(id, Item(style))); + std::vector ids; + style->getObsoleteTagIds(ids); + for (std::vector::iterator it = ids.begin(); it != ids.end(); ++it) { + if (m_table.find(*it) != m_table.end()) { + throw TException( + "Duplicate color style declaration for obsolete style. id = " + + std::to_string(*it)); + } + m_table.insert(std::make_pair(*it, Item(style->clone(), true))); + } + } + + TColorStyle *create(int id, bool &isObsolete) { + Table::iterator it = m_table.find(id); + if (it == m_table.end()) + throw TException("Unknown color style id; id = " + std::to_string(id)); + + isObsolete = it->second.m_isObsolete; + + return it->second.m_style->clone(); + } + + void getAllTags(std::vector &tags) { + tags.clear(); + tags.reserve(m_table.size()); + for (Table::iterator it = m_table.begin(); it != m_table.end(); ++it) + if (!it->second.m_isObsolete) tags.push_back(it->first); + } + + ~ColorStyleList() { + Table::iterator it = m_table.begin(); + for (; it != m_table.end(); ++it) { + delete it->second.m_style; + } + } private: - // not implemented - ColorStyleList(const ColorStyleList &); - ColorStyleList &operator=(const ColorStyleList &); + // not implemented + ColorStyleList(const ColorStyleList &); + ColorStyleList &operator=(const ColorStyleList &); }; //----------------------------------------------------------------------------- -} // namespace +} // namespace //=================================================================== -void TColorStyle::declare(TColorStyle *style) -{ - ColorStyleList::instance()->declare(style); +void TColorStyle::declare(TColorStyle *style) { + ColorStyleList::instance()->declare(style); } //=================================================================== -double computeAverageThickness(const TStroke *s, double &minThickness, double &maxThickness) -{ - int count = s->getControlPointCount(); +double computeAverageThickness(const TStroke *s, double &minThickness, + double &maxThickness) { + int count = s->getControlPointCount(); - minThickness = 1000; - maxThickness = -1; - double resThick = 0; + minThickness = 1000; + maxThickness = -1; + double resThick = 0; - for (int i = 0; i < s->getControlPointCount(); i++) { - double thick = s->getControlPoint(i).thick; - if (i >= 2 && i < s->getControlPointCount() - 2) - resThick += thick; + for (int i = 0; i < s->getControlPointCount(); i++) { + double thick = s->getControlPoint(i).thick; + if (i >= 2 && i < s->getControlPointCount() - 2) resThick += thick; - if (thick < minThickness) - minThickness = thick; - if (thick > maxThickness) - maxThickness = thick; - } + if (thick < minThickness) minThickness = thick; + if (thick > maxThickness) maxThickness = thick; + } - if (count < 6) - return s->getControlPoint(count / 2 + 1).thick; - return resThick / (s->getControlPointCount() - 4); + if (count < 6) return s->getControlPoint(count / 2 + 1).thick; + return resThick / (s->getControlPointCount() - 4); } -void TColorStyle::drawStroke(TFlash &flash, const TStroke *s) const -{ - bool isCenterline = false; - double minThickness, maxThickness = 0; - std::wstring quality = flash.getLineQuality(); - double thickness = computeAverageThickness(s, minThickness, maxThickness); - if (minThickness == maxThickness && minThickness == 0) - return; - if (quality == TFlash::ConstantLines) - isCenterline = true; - else if (quality == TFlash::MixedLines && (maxThickness == 0 || minThickness / maxThickness > 0.5)) - isCenterline = true; - else if (quality == TFlash::VariableLines && maxThickness - minThickness < 0.16) // Quando si salva il pli, si approssima al thick. - // L'errore di approx e' sempre 0.1568... - isCenterline = true; - //else assert(false); - - flash.setFillColor(getAverageColor()); - //flash.setFillColor(TPixel::Red); - - TStroke *saux = const_cast(s); - if (isCenterline) { - saux->setAverageThickness(thickness); - flash.setThickness(s->getAverageThickness()); - flash.setLineColor(getAverageColor()); - flash.drawCenterline(s, false); - } else { - saux->setAverageThickness(0); - if (!flash.drawOutline(saux)) { - flash.setThickness(thickness); - flash.setLineColor(getAverageColor()); - flash.drawCenterline(s, false); - } - } +void TColorStyle::drawStroke(TFlash &flash, const TStroke *s) const { + bool isCenterline = false; + double minThickness, maxThickness = 0; + std::wstring quality = flash.getLineQuality(); + double thickness = computeAverageThickness(s, minThickness, maxThickness); + if (minThickness == maxThickness && minThickness == 0) return; + if (quality == TFlash::ConstantLines) + isCenterline = true; + else if (quality == TFlash::MixedLines && + (maxThickness == 0 || minThickness / maxThickness > 0.5)) + isCenterline = true; + else if (quality == TFlash::VariableLines && + maxThickness - minThickness < + 0.16) // Quando si salva il pli, si approssima al thick. + // L'errore di approx e' sempre 0.1568... + isCenterline = true; + // else assert(false); + + flash.setFillColor(getAverageColor()); + // flash.setFillColor(TPixel::Red); + + TStroke *saux = const_cast(s); + if (isCenterline) { + saux->setAverageThickness(thickness); + flash.setThickness(s->getAverageThickness()); + flash.setLineColor(getAverageColor()); + flash.drawCenterline(s, false); + } else { + saux->setAverageThickness(0); + if (!flash.drawOutline(saux)) { + flash.setThickness(thickness); + flash.setLineColor(getAverageColor()); + flash.drawCenterline(s, false); + } + } } //----------------------------------------------------------------------------- @@ -537,99 +517,95 @@ void TColorStyle::drawStroke(TFlash &flash, const TStroke *s) const // note: If name starts with a digit or by '_', another '_' // is added. // (*): In such case, the flag is mandatory. -void TColorStyle::save(TOutputStreamInterface &os) const -{ - std::wstring name = getName(); - bool numberedName = !name.empty() && ('0' <= name[0] && name[0] <= '9' || name[0] == '_'); - - if (m_flags > 0 || (name.length() == 1 && numberedName)) - os << ("_" + QString::number(m_flags)).toStdString(); - std::wstring gname = getGlobalName(); - std::wstring origName = getOriginalName(); - - if (gname != L"") { - os << ::to_string(L"|" + gname); - - //save the original name from studio palette - if (origName != L"") { - //write two "@"s if the edited flag is ON - os << ::to_string(((m_isEditedFromOriginal) ? L"@@" : L"@") + origName); - } - } - - if (numberedName) - name.insert(0, L"_"); - - os << ::to_string(name) << getTagId(); - saveData(os); +void TColorStyle::save(TOutputStreamInterface &os) const { + std::wstring name = getName(); + bool numberedName = + !name.empty() && ('0' <= name[0] && name[0] <= '9' || name[0] == '_'); + + if (m_flags > 0 || (name.length() == 1 && numberedName)) + os << ("_" + QString::number(m_flags)).toStdString(); + std::wstring gname = getGlobalName(); + std::wstring origName = getOriginalName(); + + if (gname != L"") { + os << ::to_string(L"|" + gname); + + // save the original name from studio palette + if (origName != L"") { + // write two "@"s if the edited flag is ON + os << ::to_string(((m_isEditedFromOriginal) ? L"@@" : L"@") + origName); + } + } + + if (numberedName) name.insert(0, L"_"); + + os << ::to_string(name) << getTagId(); + saveData(os); } //------------------------------------------------------------------- -TColorStyle *TColorStyle::load(TInputStreamInterface &is) -{ - std::string name; - std::wstring gname; - std::wstring origName; - bool isEdited = false; - - is >> name; - unsigned int flags = 0; - if (name.length() == 2 && name[0] == '_' && '0' <= name[1] && name[1] <= '9') { - flags = QString::fromStdString(name.substr(1)).toUInt(); - is >> name; - } - if (name.length() > 0 && name[0] == '|') { - gname = ::to_wstring(name.substr(1)); - is >> name; - - //If the style is copied from studio palette, original name is here - if (name.length() > 0 && name[0] == '@') { - //if there are two "@"s, then activate the edited flag - if (name[1] == '@') { - isEdited = true; - origName = ::to_wstring(name.substr(2)); - } else { - origName = ::to_wstring(name.substr(1)); - } - is >> name; - } - } - int id = 0; - if (!name.empty() && '0' <= name[0] && name[0] <= '9') { - id = std::stoi(name); - name = "color"; - } else { - if (!name.empty() && name[0] == '_') - name.erase(name.begin()); - is >> id; - } - bool isObsolete = false; - TColorStyle *style = ColorStyleList::instance()->create(id, isObsolete); - assert(style); - style->setFlags(flags); - if (isObsolete) - style->loadData(id, is); - else - style->loadData(is); - style->setName(::to_wstring(name)); - style->setGlobalName(gname); - style->setOriginalName(origName); - style->setIsEditedFlag(isEdited); - return style; +TColorStyle *TColorStyle::load(TInputStreamInterface &is) { + std::string name; + std::wstring gname; + std::wstring origName; + bool isEdited = false; + + is >> name; + unsigned int flags = 0; + if (name.length() == 2 && name[0] == '_' && '0' <= name[1] && + name[1] <= '9') { + flags = QString::fromStdString(name.substr(1)).toUInt(); + is >> name; + } + if (name.length() > 0 && name[0] == '|') { + gname = ::to_wstring(name.substr(1)); + is >> name; + + // If the style is copied from studio palette, original name is here + if (name.length() > 0 && name[0] == '@') { + // if there are two "@"s, then activate the edited flag + if (name[1] == '@') { + isEdited = true; + origName = ::to_wstring(name.substr(2)); + } else { + origName = ::to_wstring(name.substr(1)); + } + is >> name; + } + } + int id = 0; + if (!name.empty() && '0' <= name[0] && name[0] <= '9') { + id = std::stoi(name); + name = "color"; + } else { + if (!name.empty() && name[0] == '_') name.erase(name.begin()); + is >> id; + } + bool isObsolete = false; + TColorStyle *style = ColorStyleList::instance()->create(id, isObsolete); + assert(style); + style->setFlags(flags); + if (isObsolete) + style->loadData(id, is); + else + style->loadData(is); + style->setName(::to_wstring(name)); + style->setGlobalName(gname); + style->setOriginalName(origName); + style->setIsEditedFlag(isEdited); + return style; } //------------------------------------------------------------------- -TColorStyle *TColorStyle::create(int tagId) -{ - bool isObsolete = false; - return ColorStyleList::instance()->create(tagId, isObsolete); +TColorStyle *TColorStyle::create(int tagId) { + bool isObsolete = false; + return ColorStyleList::instance()->create(tagId, isObsolete); } //------------------------------------------------------------------- -void TColorStyle::getAllTags(std::vector &tags) -{ - ColorStyleList::instance()->getAllTags(tags); +void TColorStyle::getAllTags(std::vector &tags) { + ColorStyleList::instance()->getAllTags(tags); } diff --git a/toonz/sources/common/tvrender/tellipticbrush.cpp b/toonz/sources/common/tvrender/tellipticbrush.cpp index 7b6f7df..7d107bc 100644 --- a/toonz/sources/common/tvrender/tellipticbrush.cpp +++ b/toonz/sources/common/tvrender/tellipticbrush.cpp @@ -1,6 +1,6 @@ -//Toonz components includes +// Toonz components includes #include "tcurveutil.h" #include "tinterval.h" @@ -16,7 +16,8 @@ using namespace tellipticbrush; /*! \file tellipticbrush.cpp This code deals with the "outlinization" process of a TStroke instance. -The process of extracing the outline of a thick stroke can be resumed in 2 main steps: +The process of extracing the outline of a thick stroke can be resumed in 2 main +steps: 1. Discretize the stroke centerline in the most appropriate centerline points, extracting infos about position and left/right derivatives at each. @@ -27,14 +28,19 @@ The process of extracing the outline of a thick stroke can be resumed in 2 main The first major step has some sub-routines worth noting: 1.1 Isolate regions of the stroke where the thickness speed is greater - than the gemoetrical speed of the centerline. These points are 'self-covered' - by their immediate neighbourhood, and thus cannot be seen - or build outline directions. - 1.2 Some procedural style need to sample the centerline at a given length step. + than the gemoetrical speed of the centerline. These points are +'self-covered' + by their immediate neighbourhood, and thus cannot be seen - or build +outline directions. + 1.2 Some procedural style need to sample the centerline at a given length +step. 1.3 The centerline should be sampled so that the resulting polygonal outline - approximation is tightly close to the theoretical outline, up to an error bound. + approximation is tightly close to the theoretical outline, up to an error +bound. The recursive approach is the simplest to deal with this issue. -The second step implements different outline styles to extrude the centerline points. +The second step implements different outline styles to extrude the centerline +points. */ //******************************************************************************** @@ -42,26 +48,23 @@ The second step implements different outline styles to extrude the centerline po //******************************************************************************** //! Returns the distance between two points -double tellipticbrush::dist(const TPointD &P1, const TPointD &P2) -{ - return norm(P2 - P1); +double tellipticbrush::dist(const TPointD &P1, const TPointD &P2) { + return norm(P2 - P1); } //------------------------------------------------------------ //! Returns the distance between two points -double tellipticbrush::dist(const TThickPoint &P1, const TThickPoint &P2) -{ - return norm(P2 - P1); +double tellipticbrush::dist(const TThickPoint &P1, const TThickPoint &P2) { + return norm(P2 - P1); } //------------------------------------------------------------ -//!Returns the angle between (unnormalized) vectors v1 and v2 -double tellipticbrush::angle(const TPointD &v1, const TPointD &v2) -{ - TPointD d1(v1 * (1.0 / norm(v1))), d2(v2 * (1.0 / norm(v2))); - return atan2(cross(v1, v2), v1 * v2); +//! Returns the angle between (unnormalized) vectors v1 and v2 +double tellipticbrush::angle(const TPointD &v1, const TPointD &v2) { + TPointD d1(v1 * (1.0 / norm(v1))), d2(v2 * (1.0 / norm(v2))); + return atan2(cross(v1, v2), v1 * v2); } //------------------------------------------------------------ @@ -70,81 +73,81 @@ double tellipticbrush::angle(const TPointD &v1, const TPointD &v2) Returns the intersection between two lines in the form of \b coordinates from a pair of the lines' starting points. Passed directions must have norm 1. - If the system's determinant modulus is under the specified tolerance parameter, + If the system's determinant modulus is under the specified tolerance + parameter, TConsts::napd is returned. */ -TPointD tellipticbrush::intersectionCoords( - const TPointD &P0, const TPointD &d0, const TPointD &P1, const TPointD &d1, - double detTol) -{ - //Solve P0 + x * d0 == P1 + y * d1 - - double det = d0.y * d1.x - d0.x * d1.y; - if (fabs(det) < detTol) - return TConsts::napd; - - TPointD P1_P0(P1 - P0); - return TPointD( - (d1.x * P1_P0.y - d1.y * P1_P0.x) / det, - (d0.x * P1_P0.y - d0.y * P1_P0.x) / det); +TPointD tellipticbrush::intersectionCoords(const TPointD &P0, const TPointD &d0, + const TPointD &P1, const TPointD &d1, + double detTol) { + // Solve P0 + x * d0 == P1 + y * d1 + + double det = d0.y * d1.x - d0.x * d1.y; + if (fabs(det) < detTol) return TConsts::napd; + + TPointD P1_P0(P1 - P0); + return TPointD((d1.x * P1_P0.y - d1.y * P1_P0.x) / det, + (d0.x * P1_P0.y - d0.y * P1_P0.x) / det); } //------------------------------------------------------------ /*! - Returns the left or right envelope direction of centerline point p against thick direction d. + Returns the left or right envelope direction of centerline point p against + thick direction d. */ -void tellipticbrush::buildEnvelopeDirection( - const TThickPoint &p, const TThickPoint &d, bool left, TPointD &res) -{ - double dNorm2 = sq(d.x) + sq(d.y); +void tellipticbrush::buildEnvelopeDirection(const TThickPoint &p, + const TThickPoint &d, bool left, + TPointD &res) { + double dNorm2 = sq(d.x) + sq(d.y); - double a = -d.thick / dNorm2; - double b = sqrt(dNorm2 - sq(d.thick)) / dNorm2; + double a = -d.thick / dNorm2; + double b = sqrt(dNorm2 - sq(d.thick)) / dNorm2; - TPointD n(left ? TPointD(-d.y, d.x) : TPointD(d.y, -d.x)); - res = a * TPointD(d.x, d.y) + b * n; + TPointD n(left ? TPointD(-d.y, d.x) : TPointD(d.y, -d.x)); + res = a * TPointD(d.x, d.y) + b * n; } //------------------------------------------------------------ -void tellipticbrush::buildEnvelopeDirections( - const TThickPoint &p, const TThickPoint &d, TPointD &resL, TPointD &resR) -{ - double dNorm2 = sq(d.x) + sq(d.y); +void tellipticbrush::buildEnvelopeDirections(const TThickPoint &p, + const TThickPoint &d, + TPointD &resL, TPointD &resR) { + double dNorm2 = sq(d.x) + sq(d.y); - double a = -d.thick / dNorm2; - double b = sqrt(dNorm2 - sq(d.thick)) / dNorm2; + double a = -d.thick / dNorm2; + double b = sqrt(dNorm2 - sq(d.thick)) / dNorm2; - TPointD n(-d.y, d.x); - resL = a * TPointD(d.x, d.y) + b * n; - resR = a * TPointD(d.x, d.y) - b * n; + TPointD n(-d.y, d.x); + resL = a * TPointD(d.x, d.y) + b * n; + resR = a * TPointD(d.x, d.y) - b * n; } //------------------------------------------------------------ /*! - Extrudes centerline point p against thick direction d, returning its left or right + Extrudes centerline point p against thick direction d, returning its left or + right envelope displacement vector. */ -void tellipticbrush::buildEnvelopeVector( - const TThickPoint &p, const TThickPoint &d, bool left, TPointD &res) -{ - buildEnvelopeDirection(p, d, left, res); - res.x = p.thick * res.x; - res.y = p.thick * res.y; +void tellipticbrush::buildEnvelopeVector(const TThickPoint &p, + const TThickPoint &d, bool left, + TPointD &res) { + buildEnvelopeDirection(p, d, left, res); + res.x = p.thick * res.x; + res.y = p.thick * res.y; } //------------------------------------------------------------ -void tellipticbrush::buildEnvelopeVectors( - const TThickPoint &p, const TThickPoint &d, TPointD &resL, TPointD &resR) -{ - buildEnvelopeDirections(p, d, resL, resR); - resL.x = p.thick * resL.x; - resL.y = p.thick * resL.y; - resR.x = p.thick * resR.x; - resR.y = p.thick * resR.y; +void tellipticbrush::buildEnvelopeVectors(const TThickPoint &p, + const TThickPoint &d, TPointD &resL, + TPointD &resR) { + buildEnvelopeDirections(p, d, resL, resR); + resL.x = p.thick * resL.x; + resL.y = p.thick * resL.y; + resR.x = p.thick * resR.x; + resR.y = p.thick * resR.y; } //------------------------------------------------------------ @@ -153,419 +156,420 @@ void tellipticbrush::buildEnvelopeVectors( Builds the angle that supports a *quality* discretization of the circle with maximal error < m_pixSize. */ -void tellipticbrush::buildAngularSubdivision( - double radius, double angle, double err, int &nAngles) -{ - /* - See "Graphic Gems", page 600. +void tellipticbrush::buildAngularSubdivision(double radius, double angle, + double err, int &nAngles) { + /* +See "Graphic Gems", page 600. - NOTE: maxAngle is not multiplied by 2.0 as the naive pythagorical - argument would pretend. The 2.0 holds if we want to find the angle - at which the distance of the circle from its approximation is always < error. +NOTE: maxAngle is not multiplied by 2.0 as the naive pythagorical +argument would pretend. The 2.0 holds if we want to find the angle +at which the distance of the circle from its approximation is always < error. - But we want MORE. We want that to happen against the distance from EVERY - TANGENT LINE of the arc - not the arc itself. - This is coherent with the assumption that pixels orientation is not known. +But we want MORE. We want that to happen against the distance from EVERY +TANGENT LINE of the arc - not the arc itself. +This is coherent with the assumption that pixels orientation is not known. - It's easy to see that maxAngle just has to be not multiplied by 2. - */ +It's easy to see that maxAngle just has to be not multiplied by 2. +*/ - double maxAngle = acos(1.0 - err / radius); //* 2.0; - nAngles = tceil(fabs(angle) / maxAngle); + double maxAngle = acos(1.0 - err / radius); //* 2.0; + nAngles = tceil(fabs(angle) / maxAngle); } //------------------------------------------------------------ -TRectD tellipticbrush::computeBBox(const TStroke &stroke) -{ - TRectD bbox; +TRectD tellipticbrush::computeBBox(const TStroke &stroke) { + TRectD bbox; - int i, n = stroke.getChunkCount(); - for (i = 0; i < n; i++) - bbox += stroke.getChunk(i)->getBBox(); + int i, n = stroke.getChunkCount(); + for (i = 0; i < n; i++) bbox += stroke.getChunk(i)->getBBox(); - return bbox; + return bbox; } //******************************************************************************** // CenterlinePoint implementation //******************************************************************************** -void tellipticbrush::CenterlinePoint::buildPos(const TStroke &stroke) -{ - if (m_posBuilt) - return; +void tellipticbrush::CenterlinePoint::buildPos(const TStroke &stroke) { + if (m_posBuilt) return; - m_p = stroke.getChunk(m_chunkIdx)->getThickPoint(m_t); - m_posBuilt = true; + m_p = stroke.getChunk(m_chunkIdx)->getThickPoint(m_t); + m_posBuilt = true; } //------------------------------------------------------------ -void tellipticbrush::CenterlinePoint::buildDirs(const TStroke &stroke) -{ - if (m_dirsBuilt) - return; - - int chunkPrev, chunkNext; - double tPrev, tNext; - bool coveredPrev, coveredNext; - - //Discriminate the boundary cases - bool quadBoundary; - if (m_t == 0.0) { - quadBoundary = true; - chunkPrev = m_chunkIdx - 1, chunkNext = m_chunkIdx; - tPrev = 1.0, tNext = 0.0; - } else if (m_t == 1.0) { - quadBoundary = true; - chunkPrev = m_chunkIdx, chunkNext = m_chunkIdx + 1; - tPrev = 1.0, tNext = 0.0; - } else { - quadBoundary = false; - chunkPrev = chunkNext = m_chunkIdx; - tPrev = tNext = m_t; - } - - //Build the backward direction - if (chunkPrev >= 0) { - const TThickQuadratic *ttqPrev = stroke.getChunk(chunkPrev); - - const TThickPoint &P0 = ttqPrev->getThickP0(); - const TThickPoint &P1 = ttqPrev->getThickP1(); - const TThickPoint &P2 = ttqPrev->getThickP2(); - - if (quadBoundary && (P1 == P2)) - m_prevD = P2 - P0; //Toonz 'Linear' CPs. Eliminating a perilous singularity this way. - else { - m_prevD.x = 2.0 * ((P1.x - P0.x) + tPrev * (P0.x - 2.0 * P1.x + P2.x)); - m_prevD.y = 2.0 * ((P1.y - P0.y) + tPrev * (P0.y - 2.0 * P1.y + P2.y)); - m_prevD.thick = 2.0 * ((P1.thick - P0.thick) + tPrev * (P0.thick - 2.0 * P1.thick + P2.thick)); - } - - //Points whose thickness derivative does exceeds the point speed - //cannot project envelope directions for that direction. This needs to be known. - coveredPrev = (sq(m_prevD.x) + sq(m_prevD.y) < sq(m_prevD.thick) + tolPar); - - //Accept only uncovered derivatives - m_hasPrevD = !coveredPrev; - } else { - m_hasPrevD = false; - coveredPrev = true; //ie prev coverage must not affect next coverage - m_prevD = TConsts::natp; - } - - //Build the forward direction - if (chunkPrev == chunkNext) { - //If the quadratic is the same, no need to derive it twice - m_hasNextD = m_hasPrevD; - m_nextD = m_prevD; - coveredNext = coveredPrev; - } else if (chunkNext < stroke.getChunkCount()) { - const TThickQuadratic *ttqNext = stroke.getChunk(chunkNext); - - const TThickPoint &P0 = ttqNext->getThickP0(); - const TThickPoint &P1 = ttqNext->getThickP1(); - const TThickPoint &P2 = ttqNext->getThickP2(); - - if (quadBoundary && (P0 == P1)) - m_nextD = P2 - P0; - else { - m_nextD.x = 2.0 * ((P1.x - P0.x) + tNext * (P0.x - 2.0 * P1.x + P2.x)); - m_nextD.y = 2.0 * ((P1.y - P0.y) + tNext * (P0.y - 2.0 * P1.y + P2.y)); - m_nextD.thick = 2.0 * ((P1.thick - P0.thick) + tNext * (P0.thick - 2.0 * P1.thick + P2.thick)); - } - - coveredNext = (sq(m_nextD.x) + sq(m_nextD.y) < sq(m_nextD.thick) + tolPar); - m_hasNextD = !coveredNext; - } else { - m_hasNextD = false; - coveredNext = true; //ie prev coverage must not affect next coverage - m_nextD = TConsts::natp; - } - - m_covered = (coveredPrev && coveredNext); - - m_dirsBuilt = true; +void tellipticbrush::CenterlinePoint::buildDirs(const TStroke &stroke) { + if (m_dirsBuilt) return; + + int chunkPrev, chunkNext; + double tPrev, tNext; + bool coveredPrev, coveredNext; + + // Discriminate the boundary cases + bool quadBoundary; + if (m_t == 0.0) { + quadBoundary = true; + chunkPrev = m_chunkIdx - 1, chunkNext = m_chunkIdx; + tPrev = 1.0, tNext = 0.0; + } else if (m_t == 1.0) { + quadBoundary = true; + chunkPrev = m_chunkIdx, chunkNext = m_chunkIdx + 1; + tPrev = 1.0, tNext = 0.0; + } else { + quadBoundary = false; + chunkPrev = chunkNext = m_chunkIdx; + tPrev = tNext = m_t; + } + + // Build the backward direction + if (chunkPrev >= 0) { + const TThickQuadratic *ttqPrev = stroke.getChunk(chunkPrev); + + const TThickPoint &P0 = ttqPrev->getThickP0(); + const TThickPoint &P1 = ttqPrev->getThickP1(); + const TThickPoint &P2 = ttqPrev->getThickP2(); + + if (quadBoundary && (P1 == P2)) + m_prevD = P2 - P0; // Toonz 'Linear' CPs. Eliminating a perilous + // singularity this way. + else { + m_prevD.x = 2.0 * ((P1.x - P0.x) + tPrev * (P0.x - 2.0 * P1.x + P2.x)); + m_prevD.y = 2.0 * ((P1.y - P0.y) + tPrev * (P0.y - 2.0 * P1.y + P2.y)); + m_prevD.thick = 2.0 * ((P1.thick - P0.thick) + + tPrev * (P0.thick - 2.0 * P1.thick + P2.thick)); + } + + // Points whose thickness derivative does exceeds the point speed + // cannot project envelope directions for that direction. This needs to be + // known. + coveredPrev = (sq(m_prevD.x) + sq(m_prevD.y) < sq(m_prevD.thick) + tolPar); + + // Accept only uncovered derivatives + m_hasPrevD = !coveredPrev; + } else { + m_hasPrevD = false; + coveredPrev = true; // ie prev coverage must not affect next coverage + m_prevD = TConsts::natp; + } + + // Build the forward direction + if (chunkPrev == chunkNext) { + // If the quadratic is the same, no need to derive it twice + m_hasNextD = m_hasPrevD; + m_nextD = m_prevD; + coveredNext = coveredPrev; + } else if (chunkNext < stroke.getChunkCount()) { + const TThickQuadratic *ttqNext = stroke.getChunk(chunkNext); + + const TThickPoint &P0 = ttqNext->getThickP0(); + const TThickPoint &P1 = ttqNext->getThickP1(); + const TThickPoint &P2 = ttqNext->getThickP2(); + + if (quadBoundary && (P0 == P1)) + m_nextD = P2 - P0; + else { + m_nextD.x = 2.0 * ((P1.x - P0.x) + tNext * (P0.x - 2.0 * P1.x + P2.x)); + m_nextD.y = 2.0 * ((P1.y - P0.y) + tNext * (P0.y - 2.0 * P1.y + P2.y)); + m_nextD.thick = 2.0 * ((P1.thick - P0.thick) + + tNext * (P0.thick - 2.0 * P1.thick + P2.thick)); + } + + coveredNext = (sq(m_nextD.x) + sq(m_nextD.y) < sq(m_nextD.thick) + tolPar); + m_hasNextD = !coveredNext; + } else { + m_hasNextD = false; + coveredNext = true; // ie prev coverage must not affect next coverage + m_nextD = TConsts::natp; + } + + m_covered = (coveredPrev && coveredNext); + + m_dirsBuilt = true; } //******************************************************************************** // Specialized Linearizator for common stroke drawing //******************************************************************************** -namespace -{ +namespace { -class LengthLinearizator : public tellipticbrush::StrokeLinearizator -{ - double m_lengthStep; - int m_countIdx; +class LengthLinearizator : public tellipticbrush::StrokeLinearizator { + double m_lengthStep; + int m_countIdx; public: - LengthLinearizator(const TStroke *stroke, double lengthStep) - : StrokeLinearizator(stroke), m_lengthStep(lengthStep), m_countIdx(0) {} + LengthLinearizator(const TStroke *stroke, double lengthStep) + : StrokeLinearizator(stroke), m_lengthStep(lengthStep), m_countIdx(0) {} - void linearize(std::vector &cPoints, int chunk); + void linearize(std::vector &cPoints, int chunk); }; //-------------------------------------------------------------------------------------------- -void LengthLinearizator::linearize(std::vector &cPoints, int chunk) -{ - if (m_lengthStep == 0.0) - return; - - //Retrieve the stroke length at stroke start - double startW = this->m_stroke->getW(chunk, 0.0); - double startLength = this->m_stroke->getLength(startW); - - //Retrieve the quadratic's end length - const TThickQuadratic *ttq = this->m_stroke->getChunk(chunk); - double endLength = startLength + ttq->getLength(); - - //Build the step-length inside the chunk - int n = tceil(startLength / m_lengthStep); - double length; - double t, w; - int chk; - - for (length = n * m_lengthStep; length < endLength; length += m_lengthStep) { - //Retrieve the new params at length. Need to use the sloppy TStroke interface, - //unfortunately... - w = this->m_stroke->getParameterAtLength(length); - - //WARNING: TStroke's interface is COMPLETELY WRONG about what gets returned - //by the following function. This is just *CRAZY* - however, let's take it all right... - bool ok = !this->m_stroke->getChunkAndT(w, chk, t); - - //In case something goes wrong, skip - if (!ok || chk != chunk) - continue; - - //Store the param, that NEEDS TO BE INCREMENTALLY COUNTED - as length linearization - //is typically used for special procedural vector styles that need this info. - CenterlinePoint cPoint(chk, t); - cPoint.m_countIdx = m_countIdx += 2; //++m_countIdx; - cPoints.push_back(cPoint); - } +void LengthLinearizator::linearize(std::vector &cPoints, + int chunk) { + if (m_lengthStep == 0.0) return; + + // Retrieve the stroke length at stroke start + double startW = this->m_stroke->getW(chunk, 0.0); + double startLength = this->m_stroke->getLength(startW); + + // Retrieve the quadratic's end length + const TThickQuadratic *ttq = this->m_stroke->getChunk(chunk); + double endLength = startLength + ttq->getLength(); + + // Build the step-length inside the chunk + int n = tceil(startLength / m_lengthStep); + double length; + double t, w; + int chk; + + for (length = n * m_lengthStep; length < endLength; length += m_lengthStep) { + // Retrieve the new params at length. Need to use the sloppy TStroke + // interface, + // unfortunately... + w = this->m_stroke->getParameterAtLength(length); + + // WARNING: TStroke's interface is COMPLETELY WRONG about what gets returned + // by the following function. This is just *CRAZY* - however, let's take it + // all right... + bool ok = !this->m_stroke->getChunkAndT(w, chk, t); + + // In case something goes wrong, skip + if (!ok || chk != chunk) continue; + + // Store the param, that NEEDS TO BE INCREMENTALLY COUNTED - as length + // linearization + // is typically used for special procedural vector styles that need this + // info. + CenterlinePoint cPoint(chk, t); + cPoint.m_countIdx = m_countIdx += 2; //++m_countIdx; + cPoints.push_back(cPoint); + } } //============================================================================================ -class RecursiveLinearizator : public tellipticbrush::StrokeLinearizator -{ - double m_pixSize; +class RecursiveLinearizator : public tellipticbrush::StrokeLinearizator { + double m_pixSize; public: - RecursiveLinearizator(const TStroke *stroke, double pixSize) - : StrokeLinearizator(stroke), m_pixSize(pixSize) {} + RecursiveLinearizator(const TStroke *stroke, double pixSize) + : StrokeLinearizator(stroke), m_pixSize(pixSize) {} - void linearize(std::vector &cPoints, int chunk); - void subdivide(std::vector &cPoints, - CenterlinePoint &cp0, CenterlinePoint &cp1); + void linearize(std::vector &cPoints, int chunk); + void subdivide(std::vector &cPoints, CenterlinePoint &cp0, + CenterlinePoint &cp1); }; //-------------------------------------------------------------------------------------------- -void RecursiveLinearizator::linearize(std::vector &cPoints, int chunk) -{ - /* - Recursively linearizes the centerline, in the following way: +void RecursiveLinearizator::linearize(std::vector &cPoints, + int chunk) { + /* +Recursively linearizes the centerline, in the following way: - Take one point, together with the next. Add a point in the middle interval, until - the next thick point is included (up to pixSize) in the 'forward-cast' envelope of - current one. If the midpoint was added, repeat on the 2 sub-intervals. - */ +Take one point, together with the next. Add a point in the middle interval, +until +the next thick point is included (up to pixSize) in the 'forward-cast' envelope +of +current one. If the midpoint was added, repeat on the 2 sub-intervals. +*/ - const TStroke &stroke = *this->m_stroke; - const TThickQuadratic &ttq = *stroke.getChunk(chunk); + const TStroke &stroke = *this->m_stroke; + const TThickQuadratic &ttq = *stroke.getChunk(chunk); - //Sort the interval (SHOULD BE DONE OUTSIDE?) - std::sort(cPoints.begin(), cPoints.end()); + // Sort the interval (SHOULD BE DONE OUTSIDE?) + std::sort(cPoints.begin(), cPoints.end()); - std::vector addedPoints; + std::vector addedPoints; - unsigned int i, size_1 = cPoints.size() - 1; - for (i = 0; i < size_1; ++i) { - cPoints[i].buildPos(stroke); - cPoints[i].buildDirs(stroke); + unsigned int i, size_1 = cPoints.size() - 1; + for (i = 0; i < size_1; ++i) { + cPoints[i].buildPos(stroke); + cPoints[i].buildDirs(stroke); - cPoints[i + 1].buildPos(stroke); - cPoints[i + 1].buildDirs(stroke); + cPoints[i + 1].buildPos(stroke); + cPoints[i + 1].buildDirs(stroke); - subdivide(addedPoints, cPoints[i], cPoints[i + 1]); - } + subdivide(addedPoints, cPoints[i], cPoints[i + 1]); + } - cPoints[size_1].buildPos(stroke); - cPoints[size_1].buildDirs(stroke); + cPoints[size_1].buildPos(stroke); + cPoints[size_1].buildDirs(stroke); - CenterlinePoint cpEnd(chunk, 1.0); - { - const TThickPoint &P1(ttq.getThickP1()); - cpEnd.m_p = ttq.getThickP2(); - cpEnd.m_prevD = TThickPoint( - 2.0 * (cpEnd.m_p.x - P1.x), - 2.0 * (cpEnd.m_p.y - P1.y), - 2.0 * (cpEnd.m_p.thick - P1.thick)); - cpEnd.m_hasPrevD = true; //The effective false case should already be dealt by sqrt... - } + CenterlinePoint cpEnd(chunk, 1.0); + { + const TThickPoint &P1(ttq.getThickP1()); + cpEnd.m_p = ttq.getThickP2(); + cpEnd.m_prevD = + TThickPoint(2.0 * (cpEnd.m_p.x - P1.x), 2.0 * (cpEnd.m_p.y - P1.y), + 2.0 * (cpEnd.m_p.thick - P1.thick)); + cpEnd.m_hasPrevD = + true; // The effective false case should already be dealt by sqrt... + } - subdivide(addedPoints, cPoints[size_1], cpEnd); + subdivide(addedPoints, cPoints[size_1], cpEnd); - cPoints.insert(cPoints.end(), addedPoints.begin(), addedPoints.end()); + cPoints.insert(cPoints.end(), addedPoints.begin(), addedPoints.end()); } //-------------------------------------------------------------------------------------------- void RecursiveLinearizator::subdivide(std::vector &cPoints, - CenterlinePoint &cp0, CenterlinePoint &cp1) -{ - if (!(cp0.m_hasNextD && cp1.m_hasPrevD)) - return; + CenterlinePoint &cp0, + CenterlinePoint &cp1) { + if (!(cp0.m_hasNextD && cp1.m_hasPrevD)) return; - //Build the distance of next from the outline of cp's 'envelope extension' + // Build the distance of next from the outline of cp's 'envelope extension' - TPointD envDirL0, envDirR0, envDirL1, envDirR1; - buildEnvelopeDirections(cp0.m_p, cp0.m_nextD, envDirL0, envDirR0); - buildEnvelopeDirections(cp1.m_p, cp1.m_prevD, envDirL1, envDirR1); + TPointD envDirL0, envDirR0, envDirL1, envDirR1; + buildEnvelopeDirections(cp0.m_p, cp0.m_nextD, envDirL0, envDirR0); + buildEnvelopeDirections(cp1.m_p, cp1.m_prevD, envDirL1, envDirR1); - TPointD diff(convert(cp1.m_p) - convert(cp0.m_p)); - double d = std::max( - fabs(envDirL0 * (diff + cp1.m_p.thick * envDirL1 - cp0.m_p.thick * envDirL0)), - fabs(envDirR0 * (diff + cp1.m_p.thick * envDirR1 - cp0.m_p.thick * envDirR0))); + TPointD diff(convert(cp1.m_p) - convert(cp0.m_p)); + double d = std::max(fabs(envDirL0 * (diff + cp1.m_p.thick * envDirL1 - + cp0.m_p.thick * envDirL0)), + fabs(envDirR0 * (diff + cp1.m_p.thick * envDirR1 - + cp0.m_p.thick * envDirR0))); - if (d > m_pixSize && - cp1.m_t - cp0.m_t > 1e-4) { - double midT = 0.5 * (cp0.m_t + cp1.m_t); - CenterlinePoint midPoint(cp0.m_chunkIdx, midT); + if (d > m_pixSize && cp1.m_t - cp0.m_t > 1e-4) { + double midT = 0.5 * (cp0.m_t + cp1.m_t); + CenterlinePoint midPoint(cp0.m_chunkIdx, midT); - midPoint.buildPos(*this->m_stroke); - midPoint.buildDirs(*this->m_stroke); + midPoint.buildPos(*this->m_stroke); + midPoint.buildDirs(*this->m_stroke); - subdivide(cPoints, cp0, midPoint); - subdivide(cPoints, midPoint, cp1); + subdivide(cPoints, cp0, midPoint); + subdivide(cPoints, midPoint, cp1); - cPoints.push_back(midPoint); - } + cPoints.push_back(midPoint); + } } //============================================================================================ -class CoverageLinearizator : public tellipticbrush::StrokeLinearizator -{ +class CoverageLinearizator : public tellipticbrush::StrokeLinearizator { public: - CoverageLinearizator(const TStroke *stroke) - : StrokeLinearizator(stroke) {} + CoverageLinearizator(const TStroke *stroke) : StrokeLinearizator(stroke) {} - void linearize(std::vector &cPoints, int chunk); + void linearize(std::vector &cPoints, int chunk); }; //-------------------------------------------------------------------------------------------- -void CoverageLinearizator::linearize(std::vector &cPoints, int chunk) -{ - //Retrieve the at max 2 parameters for which: - // sq(d.x) + sq(d.y) == sq(d.thick) + tolPar(*) (ie, "self-coverage" critical points) +void CoverageLinearizator::linearize(std::vector &cPoints, + int chunk) { + // Retrieve the at max 2 parameters for which: + // sq(d.x) + sq(d.y) == sq(d.thick) + tolPar(*) (ie, "self-coverage" + // critical points) - //It can be rewritten in the canonical form: at^2 + bt + c == 0 + // It can be rewritten in the canonical form: at^2 + bt + c == 0 - const TThickQuadratic &ttq(*this->m_stroke->getChunk(chunk)); + const TThickQuadratic &ttq(*this->m_stroke->getChunk(chunk)); - TThickPoint P0(ttq.getThickP0()), P1(ttq.getThickP1()), P2(ttq.getThickP2()); - if ((P0 == P1) || (P1 == P2)) - return; //Linear speed out/in case. Straighted up in the buildDirs() + TThickPoint P0(ttq.getThickP0()), P1(ttq.getThickP1()), P2(ttq.getThickP2()); + if ((P0 == P1) || (P1 == P2)) + return; // Linear speed out/in case. Straighted up in the buildDirs() - //Remember that d = 2 [P1 - P0 + t (P0 + P2 - 2 P1)] + // Remember that d = 2 [P1 - P0 + t (P0 + P2 - 2 P1)] - T3DPointD u(P1.x - P0.x, P1.y - P0.y, P1.thick - P0.thick); - T3DPointD v(P0.x + P2.x - 2.0 * P1.x, P0.y + P2.y - 2.0 * P1.y, P0.thick + P2.thick - 2.0 * P1.thick); + T3DPointD u(P1.x - P0.x, P1.y - P0.y, P1.thick - P0.thick); + T3DPointD v(P0.x + P2.x - 2.0 * P1.x, P0.y + P2.y - 2.0 * P1.y, + P0.thick + P2.thick - 2.0 * P1.thick); - double a = sq(v.x) + sq(v.y) - sq(v.z); - if (fabs(a) < 1e-4) - return; //Little (acceleration) quadratics case + double a = sq(v.x) + sq(v.y) - sq(v.z); + if (fabs(a) < 1e-4) return; // Little (acceleration) quadratics case - //(*) Build tolerance - 2.0 since tolPar is already used to discriminate 'good' dirs. Ours must be. - const double twiceTolPar = 2.0 * tolPar; + //(*) Build tolerance - 2.0 since tolPar is already used to discriminate + //'good' dirs. Ours must be. + const double twiceTolPar = 2.0 * tolPar; - double b = 2.0 * (u.x * v.x + u.y * v.y - u.z * v.z); - double c = sq(u.x) + sq(u.y) - sq(u.z) - twiceTolPar; + double b = 2.0 * (u.x * v.x + u.y * v.y - u.z * v.z); + double c = sq(u.x) + sq(u.y) - sq(u.z) - twiceTolPar; - double delta = sq(b) - 4.0 * a * c; - if (delta < 0) - return; + double delta = sq(b) - 4.0 * a * c; + if (delta < 0) return; - double sqrtDelta = sqrt(delta); - double t0 = (-b - sqrtDelta) / (2.0 * a); - double t1 = (-b + sqrtDelta) / (2.0 * a); + double sqrtDelta = sqrt(delta); + double t0 = (-b - sqrtDelta) / (2.0 * a); + double t1 = (-b + sqrtDelta) / (2.0 * a); - if (t0 > 0 && t0 < 1) { - CenterlinePoint cp(chunk, t0); - cp.buildPos(*this->m_stroke); - cp.buildDirs(*this->m_stroke); - cp.m_hasNextD = false; - cPoints.push_back(cp); - } + if (t0 > 0 && t0 < 1) { + CenterlinePoint cp(chunk, t0); + cp.buildPos(*this->m_stroke); + cp.buildDirs(*this->m_stroke); + cp.m_hasNextD = false; + cPoints.push_back(cp); + } - if (t1 > 0 && t1 < 1) { - CenterlinePoint cp(chunk, t1); - cp.buildPos(*this->m_stroke); - cp.buildDirs(*this->m_stroke); - cp.m_hasPrevD = false; - cPoints.push_back(cp); - } + if (t1 > 0 && t1 < 1) { + CenterlinePoint cp(chunk, t1); + cp.buildPos(*this->m_stroke); + cp.buildDirs(*this->m_stroke); + cp.m_hasPrevD = false; + cPoints.push_back(cp); + } } -} //namespace +} // namespace //******************************************************************************** // Outline Builder implementation //******************************************************************************** -tellipticbrush::OutlineBuilder::OutlineBuilder(const OutlinizationData &data, const TStroke &stroke) - : m_pixSize(data.m_pixSize), m_oOptions(stroke.outlineOptions()), m_lastChunk(stroke.getChunkCount() - 1) -{ - typedef TStroke::OutlineOptions OutlineOptions; - - switch (m_oOptions.m_capStyle) { - case OutlineOptions::PROJECTING_CAP: { - m_addBeginCap = &OutlineBuilder::addProjectingBeginCap>; - m_addEndCap = &OutlineBuilder::addProjectingEndCap>; - m_addBeginCap_ext = &OutlineBuilder::addProjectingBeginCap; - m_addEndCap_ext = &OutlineBuilder::addProjectingEndCap; - break; - } - case OutlineOptions::BUTT_CAP: { - m_addBeginCap = &OutlineBuilder::addButtBeginCap; - m_addEndCap = &OutlineBuilder::addButtEndCap; - m_addBeginCap_ext = 0; - m_addEndCap_ext = 0; - break; - } - case OutlineOptions::ROUND_CAP: - default: - m_addBeginCap = &OutlineBuilder::addRoundBeginCap; - m_addEndCap = &OutlineBuilder::addRoundEndCap; - m_addBeginCap_ext = 0; - m_addEndCap_ext = 0; - }; - - switch (m_oOptions.m_joinStyle) { - case OutlineOptions::MITER_JOIN: { - m_addSideCaps = &OutlineBuilder::addMiterSideCaps>; - m_addSideCaps_ext = &OutlineBuilder::addMiterSideCaps; - break; - } - - case OutlineOptions::BEVEL_JOIN: { - m_addSideCaps = &OutlineBuilder::addBevelSideCaps; - m_addSideCaps_ext = 0; - break; - } - case OutlineOptions::ROUND_JOIN: - default: - m_addSideCaps = &OutlineBuilder::addRoundSideCaps; - m_addSideCaps_ext = 0; - }; +tellipticbrush::OutlineBuilder::OutlineBuilder(const OutlinizationData &data, + const TStroke &stroke) + : m_pixSize(data.m_pixSize) + , m_oOptions(stroke.outlineOptions()) + , m_lastChunk(stroke.getChunkCount() - 1) { + typedef TStroke::OutlineOptions OutlineOptions; + + switch (m_oOptions.m_capStyle) { + case OutlineOptions::PROJECTING_CAP: { + m_addBeginCap = + &OutlineBuilder::addProjectingBeginCap>; + m_addEndCap = + &OutlineBuilder::addProjectingEndCap>; + m_addBeginCap_ext = &OutlineBuilder::addProjectingBeginCap; + m_addEndCap_ext = &OutlineBuilder::addProjectingEndCap; + break; + } + case OutlineOptions::BUTT_CAP: { + m_addBeginCap = &OutlineBuilder::addButtBeginCap; + m_addEndCap = &OutlineBuilder::addButtEndCap; + m_addBeginCap_ext = 0; + m_addEndCap_ext = 0; + break; + } + case OutlineOptions::ROUND_CAP: + default: + m_addBeginCap = &OutlineBuilder::addRoundBeginCap; + m_addEndCap = &OutlineBuilder::addRoundEndCap; + m_addBeginCap_ext = 0; + m_addEndCap_ext = 0; + }; + + switch (m_oOptions.m_joinStyle) { + case OutlineOptions::MITER_JOIN: { + m_addSideCaps = + &OutlineBuilder::addMiterSideCaps>; + m_addSideCaps_ext = &OutlineBuilder::addMiterSideCaps; + break; + } + + case OutlineOptions::BEVEL_JOIN: { + m_addSideCaps = &OutlineBuilder::addBevelSideCaps; + m_addSideCaps_ext = 0; + break; + } + case OutlineOptions::ROUND_JOIN: + default: + m_addSideCaps = &OutlineBuilder::addRoundSideCaps; + m_addSideCaps_ext = 0; + }; } //------------------------------------------------------------ @@ -575,39 +579,40 @@ tellipticbrush::OutlineBuilder::OutlineBuilder(const OutlinizationData &data, co adds them to the supplied vector container. */ void tellipticbrush::OutlineBuilder::buildOutlinePoints( - std::vector &oPoints, const CenterlinePoint &cPoint) -{ - //If the centerline directions exist and match, just add their envelope - //displacement directly - if (cPoint.m_hasPrevD && cPoint.m_hasNextD && - cPoint.m_prevD == cPoint.m_nextD) { - TPointD leftD, rightD; - buildEnvelopeVector(cPoint.m_p, cPoint.m_prevD, true, leftD); - buildEnvelopeVector(cPoint.m_p, cPoint.m_prevD, false, rightD); - - oPoints.push_back(TOutlinePoint(convert(cPoint.m_p) + rightD, cPoint.m_countIdx)); - oPoints.push_back(TOutlinePoint(convert(cPoint.m_p) + leftD, cPoint.m_countIdx)); - } else { - //We have to add caps/joins together with the envelope displacements - //Caps which are not at stroke ends are always imposed to be round. - - if (cPoint.m_hasPrevD) { - if (cPoint.m_hasNextD) - (this->*m_addSideCaps)(oPoints, cPoint); - else if (cPoint.m_chunkIdx == m_lastChunk && cPoint.m_t == 1.0) - (this->*m_addEndCap)(oPoints, cPoint); - else - addRoundEndCap(oPoints, cPoint); - } else { - if (cPoint.m_hasNextD) - if (cPoint.m_chunkIdx == 0 && cPoint.m_t == 0.0) - (this->*m_addBeginCap)(oPoints, cPoint); - else - addRoundBeginCap(oPoints, cPoint); - else - addCircle(oPoints, cPoint); - } - } + std::vector &oPoints, const CenterlinePoint &cPoint) { + // If the centerline directions exist and match, just add their envelope + // displacement directly + if (cPoint.m_hasPrevD && cPoint.m_hasNextD && + cPoint.m_prevD == cPoint.m_nextD) { + TPointD leftD, rightD; + buildEnvelopeVector(cPoint.m_p, cPoint.m_prevD, true, leftD); + buildEnvelopeVector(cPoint.m_p, cPoint.m_prevD, false, rightD); + + oPoints.push_back( + TOutlinePoint(convert(cPoint.m_p) + rightD, cPoint.m_countIdx)); + oPoints.push_back( + TOutlinePoint(convert(cPoint.m_p) + leftD, cPoint.m_countIdx)); + } else { + // We have to add caps/joins together with the envelope displacements + // Caps which are not at stroke ends are always imposed to be round. + + if (cPoint.m_hasPrevD) { + if (cPoint.m_hasNextD) + (this->*m_addSideCaps)(oPoints, cPoint); + else if (cPoint.m_chunkIdx == m_lastChunk && cPoint.m_t == 1.0) + (this->*m_addEndCap)(oPoints, cPoint); + else + addRoundEndCap(oPoints, cPoint); + } else { + if (cPoint.m_hasNextD) + if (cPoint.m_chunkIdx == 0 && cPoint.m_t == 0.0) + (this->*m_addBeginCap)(oPoints, cPoint); + else + addRoundBeginCap(oPoints, cPoint); + else + addCircle(oPoints, cPoint); + } + } } //------------------------------------------------------------ @@ -617,515 +622,513 @@ void tellipticbrush::OutlineBuilder::buildOutlinePoints( and adds them to the supplied (bbox) rect. */ void tellipticbrush::OutlineBuilder::buildOutlineExtensions( - TRectD &bbox, const CenterlinePoint &cPoint) -{ - if (!(cPoint.m_hasPrevD && cPoint.m_hasNextD && - cPoint.m_prevD == cPoint.m_nextD)) { - //Only non-envelope points are interesting to the bbox builder procedure - - if (cPoint.m_hasPrevD) { - if (cPoint.m_hasNextD && - m_addSideCaps_ext) - (this->*m_addSideCaps_ext)(bbox, cPoint); - else if (cPoint.m_chunkIdx == m_lastChunk && cPoint.m_t == 1.0 && - m_addEndCap_ext) - (this->*m_addEndCap_ext)(bbox, cPoint); - } else { - if (cPoint.m_hasNextD) - if (cPoint.m_chunkIdx == 0 && cPoint.m_t == 0.0 && - m_addBeginCap_ext) - (this->*m_addBeginCap_ext)(bbox, cPoint); - } - } + TRectD &bbox, const CenterlinePoint &cPoint) { + if (!(cPoint.m_hasPrevD && cPoint.m_hasNextD && + cPoint.m_prevD == cPoint.m_nextD)) { + // Only non-envelope points are interesting to the bbox builder procedure + + if (cPoint.m_hasPrevD) { + if (cPoint.m_hasNextD && m_addSideCaps_ext) + (this->*m_addSideCaps_ext)(bbox, cPoint); + else if (cPoint.m_chunkIdx == m_lastChunk && cPoint.m_t == 1.0 && + m_addEndCap_ext) + (this->*m_addEndCap_ext)(bbox, cPoint); + } else { + if (cPoint.m_hasNextD) + if (cPoint.m_chunkIdx == 0 && cPoint.m_t == 0.0 && m_addBeginCap_ext) + (this->*m_addBeginCap_ext)(bbox, cPoint); + } + } } //------------------------------------------------------------ void tellipticbrush::OutlineBuilder::addCircularArcPoints( - int idx, std::vector &outPoints, - const TPointD ¢er, const TPointD &ray, double angle, int nAngles, - int countIdx) -{ - TPointD rotRay(ray); - - //Push the initial point without rotation - outPoints[idx] = TOutlinePoint(center + ray, countIdx); - idx += 2; - - //Build the rotation - double sin_a = sin(angle); //NOTE: The 'angle' input parameter CANNOT be substituted with just cos, - double cos_a = cos(angle); //while sin = sqrt(1.0 - sq(cos)), BECAUSE this way sin is ALWAYS > 0 - - int i; - for (i = 1; i <= nAngles; ++i, idx += 2) { - rotRay = TPointD( - rotRay.x * cos_a - rotRay.y * sin_a, - rotRay.x * sin_a + rotRay.y * cos_a); - outPoints[idx] = center + rotRay; - } + int idx, std::vector &outPoints, const TPointD ¢er, + const TPointD &ray, double angle, int nAngles, int countIdx) { + TPointD rotRay(ray); + + // Push the initial point without rotation + outPoints[idx] = TOutlinePoint(center + ray, countIdx); + idx += 2; + + // Build the rotation + double sin_a = sin(angle); // NOTE: The 'angle' input parameter CANNOT be + // substituted with just cos, + double cos_a = cos(angle); // while sin = sqrt(1.0 - sq(cos)), BECAUSE this + // way sin is ALWAYS > 0 + + int i; + for (i = 1; i <= nAngles; ++i, idx += 2) { + rotRay = TPointD(rotRay.x * cos_a - rotRay.y * sin_a, + rotRay.x * sin_a + rotRay.y * cos_a); + outPoints[idx] = center + rotRay; + } } //------------------------------------------------------------ void tellipticbrush::OutlineBuilder::addCircle( - std::vector &oPoints, const CenterlinePoint &cPoint) -{ - //Build the angle step for (0, pi) - int nAngles; - double stepAngle, totAngle = angle(TPointD(1.0, 0.0), TPointD(-1.0, 0.0)); - - buildAngularSubdivision(cPoint.m_p.thick, totAngle, m_pixSize, nAngles); - stepAngle = totAngle / (double)nAngles; - - //Resize the vector to store the required points - int idx = oPoints.size(); - oPoints.resize(oPoints.size() + 2 * (nAngles + 1), TOutlinePoint(TPointD())); - - //Add the circle points from each semi-circle - addCircularArcPoints(idx, oPoints, - convert(cPoint.m_p), TPointD(cPoint.m_p.thick, 0.0), - -stepAngle, nAngles, cPoint.m_countIdx); - addCircularArcPoints(idx + 1, oPoints, - convert(cPoint.m_p), TPointD(cPoint.m_p.thick, 0.0), - stepAngle, nAngles, cPoint.m_countIdx); + std::vector &oPoints, const CenterlinePoint &cPoint) { + // Build the angle step for (0, pi) + int nAngles; + double stepAngle, totAngle = angle(TPointD(1.0, 0.0), TPointD(-1.0, 0.0)); + + buildAngularSubdivision(cPoint.m_p.thick, totAngle, m_pixSize, nAngles); + stepAngle = totAngle / (double)nAngles; + + // Resize the vector to store the required points + int idx = oPoints.size(); + oPoints.resize(oPoints.size() + 2 * (nAngles + 1), TOutlinePoint(TPointD())); + + // Add the circle points from each semi-circle + addCircularArcPoints(idx, oPoints, convert(cPoint.m_p), + TPointD(cPoint.m_p.thick, 0.0), -stepAngle, nAngles, + cPoint.m_countIdx); + addCircularArcPoints(idx + 1, oPoints, convert(cPoint.m_p), + TPointD(cPoint.m_p.thick, 0.0), stepAngle, nAngles, + cPoint.m_countIdx); } //------------------------------------------------------------ void tellipticbrush::OutlineBuilder::addRoundBeginCap( - std::vector &oPoints, const CenterlinePoint &cPoint) -{ - TPointD rightD; - buildEnvelopeVector(cPoint.m_p, cPoint.m_nextD, false, rightD); + std::vector &oPoints, const CenterlinePoint &cPoint) { + TPointD rightD; + buildEnvelopeVector(cPoint.m_p, cPoint.m_nextD, false, rightD); - TPointD beginD(-convert(cPoint.m_nextD)); - beginD = (cPoint.m_p.thick / norm(beginD)) * beginD; + TPointD beginD(-convert(cPoint.m_nextD)); + beginD = (cPoint.m_p.thick / norm(beginD)) * beginD; - int nAngles; - double stepAngle, totAngle = angle(beginD, rightD); + int nAngles; + double stepAngle, totAngle = angle(beginD, rightD); - buildAngularSubdivision(cPoint.m_p.thick, totAngle, m_pixSize, nAngles); - stepAngle = totAngle / (double)nAngles; + buildAngularSubdivision(cPoint.m_p.thick, totAngle, m_pixSize, nAngles); + stepAngle = totAngle / (double)nAngles; - int idx = oPoints.size(); - oPoints.resize(oPoints.size() + 2 * (nAngles + 1), TOutlinePoint(TPointD())); + int idx = oPoints.size(); + oPoints.resize(oPoints.size() + 2 * (nAngles + 1), TOutlinePoint(TPointD())); - addCircularArcPoints(idx, oPoints, - convert(cPoint.m_p), beginD, - stepAngle, nAngles, cPoint.m_countIdx); - addCircularArcPoints(idx + 1, oPoints, - convert(cPoint.m_p), beginD, - -stepAngle, nAngles, cPoint.m_countIdx); //we just need to take the opposite angle to deal with left side + addCircularArcPoints(idx, oPoints, convert(cPoint.m_p), beginD, stepAngle, + nAngles, cPoint.m_countIdx); + addCircularArcPoints(idx + 1, oPoints, convert(cPoint.m_p), beginD, + -stepAngle, nAngles, + cPoint.m_countIdx); // we just need to take the opposite + // angle to deal with left side } //------------------------------------------------------------ void tellipticbrush::OutlineBuilder::addRoundEndCap( - std::vector &oPoints, const CenterlinePoint &cPoint) -{ - //Build the backward envelope directions - //Note that the situation is specular on the left and right side... - TPointD leftD, rightD; - buildEnvelopeVector(cPoint.m_p, cPoint.m_prevD, true, leftD); - buildEnvelopeVector(cPoint.m_p, cPoint.m_prevD, false, rightD); - - int nAngles; - double stepAngle, totAngle = angle(rightD, convert(cPoint.m_prevD)); - - buildAngularSubdivision(cPoint.m_p.thick, totAngle, m_pixSize, nAngles); - stepAngle = totAngle / (double)nAngles; - - int idx = oPoints.size(); - oPoints.resize(oPoints.size() + 2 * (nAngles + 1), TOutlinePoint(TPointD())); - - addCircularArcPoints(idx, oPoints, - convert(cPoint.m_p), rightD, - stepAngle, nAngles, cPoint.m_countIdx); - addCircularArcPoints(idx + 1, oPoints, - convert(cPoint.m_p), leftD, - -stepAngle, nAngles, cPoint.m_countIdx); //we just need to take the opposite angle to deal with left side + std::vector &oPoints, const CenterlinePoint &cPoint) { + // Build the backward envelope directions + // Note that the situation is specular on the left and right side... + TPointD leftD, rightD; + buildEnvelopeVector(cPoint.m_p, cPoint.m_prevD, true, leftD); + buildEnvelopeVector(cPoint.m_p, cPoint.m_prevD, false, rightD); + + int nAngles; + double stepAngle, totAngle = angle(rightD, convert(cPoint.m_prevD)); + + buildAngularSubdivision(cPoint.m_p.thick, totAngle, m_pixSize, nAngles); + stepAngle = totAngle / (double)nAngles; + + int idx = oPoints.size(); + oPoints.resize(oPoints.size() + 2 * (nAngles + 1), TOutlinePoint(TPointD())); + + addCircularArcPoints(idx, oPoints, convert(cPoint.m_p), rightD, stepAngle, + nAngles, cPoint.m_countIdx); + addCircularArcPoints(idx + 1, oPoints, convert(cPoint.m_p), leftD, -stepAngle, + nAngles, cPoint.m_countIdx); // we just need to take the + // opposite angle to deal + // with left side } //------------------------------------------------------------ void tellipticbrush::OutlineBuilder::addButtBeginCap( - std::vector &oPoints, const CenterlinePoint &cPoint) -{ - //Just add the 2 basic envelope points - TPointD leftDNext, rightDNext; - buildEnvelopeVectors(cPoint.m_p, cPoint.m_nextD, leftDNext, rightDNext); - - //PLUS, add their midpoint, since it generates this part of stroke antialias... - TPointD leftP(convert(cPoint.m_p) + leftDNext), rightP(convert(cPoint.m_p) + rightDNext); - TPointD midP(0.5 * (leftP + rightP)); - - oPoints.push_back(midP); - oPoints.push_back(midP); - - oPoints.push_back(TOutlinePoint(rightP, cPoint.m_countIdx)); - oPoints.push_back(TOutlinePoint(leftP, cPoint.m_countIdx)); + std::vector &oPoints, const CenterlinePoint &cPoint) { + // Just add the 2 basic envelope points + TPointD leftDNext, rightDNext; + buildEnvelopeVectors(cPoint.m_p, cPoint.m_nextD, leftDNext, rightDNext); + + // PLUS, add their midpoint, since it generates this part of stroke + // antialias... + TPointD leftP(convert(cPoint.m_p) + leftDNext), + rightP(convert(cPoint.m_p) + rightDNext); + TPointD midP(0.5 * (leftP + rightP)); + + oPoints.push_back(midP); + oPoints.push_back(midP); + + oPoints.push_back(TOutlinePoint(rightP, cPoint.m_countIdx)); + oPoints.push_back(TOutlinePoint(leftP, cPoint.m_countIdx)); } //------------------------------------------------------------ void tellipticbrush::OutlineBuilder::addButtEndCap( - std::vector &oPoints, const CenterlinePoint &cPoint) -{ - TPointD leftDPrev, rightDPrev; - buildEnvelopeVectors(cPoint.m_p, cPoint.m_prevD, leftDPrev, rightDPrev); + std::vector &oPoints, const CenterlinePoint &cPoint) { + TPointD leftDPrev, rightDPrev; + buildEnvelopeVectors(cPoint.m_p, cPoint.m_prevD, leftDPrev, rightDPrev); - TPointD leftP(convert(cPoint.m_p) + leftDPrev), rightP(convert(cPoint.m_p) + rightDPrev); - TPointD midP(0.5 * (leftP + rightP)); + TPointD leftP(convert(cPoint.m_p) + leftDPrev), + rightP(convert(cPoint.m_p) + rightDPrev); + TPointD midP(0.5 * (leftP + rightP)); - oPoints.push_back(TOutlinePoint(convert(cPoint.m_p) + rightDPrev, cPoint.m_countIdx)); - oPoints.push_back(TOutlinePoint(convert(cPoint.m_p) + leftDPrev, cPoint.m_countIdx)); + oPoints.push_back( + TOutlinePoint(convert(cPoint.m_p) + rightDPrev, cPoint.m_countIdx)); + oPoints.push_back( + TOutlinePoint(convert(cPoint.m_p) + leftDPrev, cPoint.m_countIdx)); - oPoints.push_back(midP); - oPoints.push_back(midP); + oPoints.push_back(midP); + oPoints.push_back(midP); } //------------------------------------------------------------ template void tellipticbrush::OutlineBuilder::addProjectingBeginCap( - T &oPoints, const CenterlinePoint &cPoint) -{ - double thick = cPoint.m_p.thick; + T &oPoints, const CenterlinePoint &cPoint) { + double thick = cPoint.m_p.thick; - //Find the base points - TPointD leftDNext, rightDNext; - buildEnvelopeDirections(cPoint.m_p, cPoint.m_nextD, leftDNext, rightDNext); + // Find the base points + TPointD leftDNext, rightDNext; + buildEnvelopeDirections(cPoint.m_p, cPoint.m_nextD, leftDNext, rightDNext); - TPointD leftP(convert(cPoint.m_p) + thick * leftDNext); - TPointD rightP(convert(cPoint.m_p) + thick * rightDNext); + TPointD leftP(convert(cPoint.m_p) + thick * leftDNext); + TPointD rightP(convert(cPoint.m_p) + thick * rightDNext); - //Add the intersections between the envelope directions' orthogonals and the - //direction orthogonals - TPointD dir(normalize(-cPoint.m_nextD)); - TPointD dirP(convert(cPoint.m_p) + thick * dir); + // Add the intersections between the envelope directions' orthogonals and the + // direction orthogonals + TPointD dir(normalize(-cPoint.m_nextD)); + TPointD dirP(convert(cPoint.m_p) + thick * dir); - TPointD cornerLCoords = intersectionCoords( - dirP, TPointD(dir.y, -dir.x), leftP, TPointD(-leftDNext.y, leftDNext.x)); + TPointD cornerLCoords = intersectionCoords( + dirP, TPointD(dir.y, -dir.x), leftP, TPointD(-leftDNext.y, leftDNext.x)); - TPointD cornerRCoords = intersectionCoords( - dirP, TPointD(-dir.y, dir.x), rightP, TPointD(rightDNext.y, -rightDNext.x)); + TPointD cornerRCoords = + intersectionCoords(dirP, TPointD(-dir.y, dir.x), rightP, + TPointD(rightDNext.y, -rightDNext.x)); - if (cornerLCoords.x < 0 || cornerRCoords.y < 0) - return; + if (cornerLCoords.x < 0 || cornerRCoords.y < 0) return; - //As before, midPoints must be added due to antialias - TPointD cornerL(dirP + cornerLCoords.x * TPointD(dir.y, -dir.x)); - TPointD cornerR(dirP + cornerRCoords.x * TPointD(-dir.y, dir.x)); - TPointD midP(0.5 * (cornerL + cornerR)); + // As before, midPoints must be added due to antialias + TPointD cornerL(dirP + cornerLCoords.x * TPointD(dir.y, -dir.x)); + TPointD cornerR(dirP + cornerRCoords.x * TPointD(-dir.y, dir.x)); + TPointD midP(0.5 * (cornerL + cornerR)); - addEnvelopePoint(oPoints, midP); - addEnvelopePoint(oPoints, midP); + addEnvelopePoint(oPoints, midP); + addEnvelopePoint(oPoints, midP); - addExtensionPoint(oPoints, cornerR); - addExtensionPoint(oPoints, cornerL); + addExtensionPoint(oPoints, cornerR); + addExtensionPoint(oPoints, cornerL); - //Initial points must be added later, in the begin case - addEnvelopePoint(oPoints, rightP, cPoint.m_countIdx); - addEnvelopePoint(oPoints, leftP, cPoint.m_countIdx); + // Initial points must be added later, in the begin case + addEnvelopePoint(oPoints, rightP, cPoint.m_countIdx); + addEnvelopePoint(oPoints, leftP, cPoint.m_countIdx); } //------------------------------------------------------------ template void tellipticbrush::OutlineBuilder::addProjectingEndCap( - T &oPoints, const CenterlinePoint &cPoint) -{ - double thick = cPoint.m_p.thick; + T &oPoints, const CenterlinePoint &cPoint) { + double thick = cPoint.m_p.thick; - //Add the base points - TPointD leftDPrev, rightDPrev; - buildEnvelopeDirections(cPoint.m_p, cPoint.m_prevD, leftDPrev, rightDPrev); + // Add the base points + TPointD leftDPrev, rightDPrev; + buildEnvelopeDirections(cPoint.m_p, cPoint.m_prevD, leftDPrev, rightDPrev); - TPointD leftP(convert(cPoint.m_p) + thick * leftDPrev); - TPointD rightP(convert(cPoint.m_p) + thick * rightDPrev); + TPointD leftP(convert(cPoint.m_p) + thick * leftDPrev); + TPointD rightP(convert(cPoint.m_p) + thick * rightDPrev); - addEnvelopePoint(oPoints, rightP, cPoint.m_countIdx); - addEnvelopePoint(oPoints, leftP, cPoint.m_countIdx); + addEnvelopePoint(oPoints, rightP, cPoint.m_countIdx); + addEnvelopePoint(oPoints, leftP, cPoint.m_countIdx); - //Add the intersections between the envelope directions' orthogonals and the - //direction orthogonals - TPointD dir(normalize(cPoint.m_prevD)); - TPointD dirP(convert(cPoint.m_p) + thick * dir); + // Add the intersections between the envelope directions' orthogonals and the + // direction orthogonals + TPointD dir(normalize(cPoint.m_prevD)); + TPointD dirP(convert(cPoint.m_p) + thick * dir); - TPointD cornerLCoords = intersectionCoords( - dirP, TPointD(-dir.y, dir.x), leftP, TPointD(leftDPrev.y, -leftDPrev.x)); + TPointD cornerLCoords = intersectionCoords( + dirP, TPointD(-dir.y, dir.x), leftP, TPointD(leftDPrev.y, -leftDPrev.x)); - TPointD cornerRCoords = intersectionCoords( - dirP, TPointD(dir.y, -dir.x), rightP, TPointD(-rightDPrev.y, rightDPrev.x)); + TPointD cornerRCoords = + intersectionCoords(dirP, TPointD(dir.y, -dir.x), rightP, + TPointD(-rightDPrev.y, rightDPrev.x)); - if (cornerLCoords.x < 0 || cornerRCoords.y < 0) - return; + if (cornerLCoords.x < 0 || cornerRCoords.y < 0) return; - TPointD cornerL(dirP + cornerLCoords.x * TPointD(-dir.y, dir.x)); - TPointD cornerR(dirP + cornerRCoords.x * TPointD(dir.y, -dir.x)); - TPointD midP(0.5 * (cornerL + cornerR)); + TPointD cornerL(dirP + cornerLCoords.x * TPointD(-dir.y, dir.x)); + TPointD cornerR(dirP + cornerRCoords.x * TPointD(dir.y, -dir.x)); + TPointD midP(0.5 * (cornerL + cornerR)); - addExtensionPoint(oPoints, cornerR); - addExtensionPoint(oPoints, cornerL); + addExtensionPoint(oPoints, cornerR); + addExtensionPoint(oPoints, cornerL); - addEnvelopePoint(oPoints, midP); - addEnvelopePoint(oPoints, midP); + addEnvelopePoint(oPoints, midP); + addEnvelopePoint(oPoints, midP); } //------------------------------------------------------------ void tellipticbrush::OutlineBuilder::addRoundSideCaps( - std::vector &oPoints, const CenterlinePoint &cPoint) -{ - //Side caps - this has only sense when the backward and forward direction-derivatives - //are different. This means that thay build different envelope directions. So, we add - //side caps to cover the 'elbow fractures' - - TPointD leftDPrev, leftDNext, rightDPrev, rightDNext; - buildEnvelopeVector(cPoint.m_p, cPoint.m_prevD, true, leftDPrev); - buildEnvelopeVector(cPoint.m_p, cPoint.m_nextD, true, leftDNext); - buildEnvelopeVector(cPoint.m_p, cPoint.m_prevD, false, rightDPrev); - buildEnvelopeVector(cPoint.m_p, cPoint.m_nextD, false, rightDNext); - - //This time, angle step is NOT specular - int nAnglesL, nAnglesR; - double totAngleL = angle(leftDPrev, leftDNext); - double totAngleR = angle(rightDPrev, rightDNext); - - //The common case is that these angles have the same sign - thus building - //opposites arcs of a circle - if (tsign(totAngleL) != tsign(totAngleR)) { - //However, there may be exceptions. We must still impose - //the constraint about 'covering opposite arcs of a circle' - - //it is necessary to make the outline look consistently filled. - - TPointD prevD(convert(cPoint.m_prevD)), nextD(convert(cPoint.m_nextD)); - - //The only dangerous case is when the directions are near-opposed - if (prevD * nextD < 0) { - const double twice_pi = 2 * TConsts::pi; - - //Here, we must make one angle its (sign-opposite) 2*pi complement. - //Keep the angle with the least fabs (smallest 'butterfly intersection') - if (fabs(totAngleL) < fabs(totAngleR)) - totAngleR = (totAngleR > 0) ? totAngleR - twice_pi : totAngleR + twice_pi; - else - totAngleL = (totAngleL > 0) ? totAngleL - twice_pi : totAngleL + twice_pi; - } - } - - buildAngularSubdivision(cPoint.m_p.thick, totAngleL, m_pixSize, nAnglesL); - buildAngularSubdivision(cPoint.m_p.thick, totAngleR, m_pixSize, nAnglesR); - - int nAngles = std::max(nAnglesL, nAnglesR); - double stepAngleL = totAngleL / (double)nAngles; - double stepAngleR = totAngleR / (double)nAngles; - - if (nAnglesL == 1 && nAnglesR == 1 && - fabs(totAngleL) < 0.525 && fabs(totAngleR) < 0.525) //angle < 30 degrees - { - //Simple case - oPoints.push_back(TOutlinePoint(convert(cPoint.m_p) + rightDPrev, cPoint.m_countIdx)); - oPoints.push_back(TOutlinePoint(convert(cPoint.m_p) + leftDPrev, cPoint.m_countIdx)); - } else { - int idx = oPoints.size(); - oPoints.resize(oPoints.size() + 2 * (nAngles + 1), TOutlinePoint(TPointD())); - - addCircularArcPoints(idx, oPoints, - convert(cPoint.m_p), rightDPrev, - stepAngleR, nAngles, cPoint.m_countIdx); - addCircularArcPoints(idx + 1, oPoints, - convert(cPoint.m_p), leftDPrev, - stepAngleL, nAngles, cPoint.m_countIdx); //same angle here, as this is just a stroke direction rotation - } + std::vector &oPoints, const CenterlinePoint &cPoint) { + // Side caps - this has only sense when the backward and forward + // direction-derivatives + // are different. This means that thay build different envelope directions. + // So, we add + // side caps to cover the 'elbow fractures' + + TPointD leftDPrev, leftDNext, rightDPrev, rightDNext; + buildEnvelopeVector(cPoint.m_p, cPoint.m_prevD, true, leftDPrev); + buildEnvelopeVector(cPoint.m_p, cPoint.m_nextD, true, leftDNext); + buildEnvelopeVector(cPoint.m_p, cPoint.m_prevD, false, rightDPrev); + buildEnvelopeVector(cPoint.m_p, cPoint.m_nextD, false, rightDNext); + + // This time, angle step is NOT specular + int nAnglesL, nAnglesR; + double totAngleL = angle(leftDPrev, leftDNext); + double totAngleR = angle(rightDPrev, rightDNext); + + // The common case is that these angles have the same sign - thus building + // opposites arcs of a circle + if (tsign(totAngleL) != tsign(totAngleR)) { + // However, there may be exceptions. We must still impose + // the constraint about 'covering opposite arcs of a circle' - + // it is necessary to make the outline look consistently filled. + + TPointD prevD(convert(cPoint.m_prevD)), nextD(convert(cPoint.m_nextD)); + + // The only dangerous case is when the directions are near-opposed + if (prevD * nextD < 0) { + // Here, we must make one angle its (sign-opposite) 2*pi complement. + // Keep the angle with the least fabs (smallest 'butterfly intersection') + if (fabs(totAngleL) < fabs(totAngleR)) + totAngleR = (totAngleR > 0) ? totAngleR - M_2PI : totAngleR + M_2PI; + else + totAngleL = (totAngleL > 0) ? totAngleL - M_2PI : totAngleL + M_2PI; + } + } + + buildAngularSubdivision(cPoint.m_p.thick, totAngleL, m_pixSize, nAnglesL); + buildAngularSubdivision(cPoint.m_p.thick, totAngleR, m_pixSize, nAnglesR); + + int nAngles = std::max(nAnglesL, nAnglesR); + double stepAngleL = totAngleL / (double)nAngles; + double stepAngleR = totAngleR / (double)nAngles; + + if (nAnglesL == 1 && nAnglesR == 1 && fabs(totAngleL) < 0.525 && + fabs(totAngleR) < 0.525) // angle < 30 degrees + { + // Simple case + oPoints.push_back( + TOutlinePoint(convert(cPoint.m_p) + rightDPrev, cPoint.m_countIdx)); + oPoints.push_back( + TOutlinePoint(convert(cPoint.m_p) + leftDPrev, cPoint.m_countIdx)); + } else { + int idx = oPoints.size(); + oPoints.resize(oPoints.size() + 2 * (nAngles + 1), + TOutlinePoint(TPointD())); + + addCircularArcPoints(idx, oPoints, convert(cPoint.m_p), rightDPrev, + stepAngleR, nAngles, cPoint.m_countIdx); + addCircularArcPoints( + idx + 1, oPoints, convert(cPoint.m_p), leftDPrev, stepAngleL, nAngles, + cPoint.m_countIdx); // same angle here, as this is just a stroke + // direction rotation + } } //------------------------------------------------------------ void tellipticbrush::OutlineBuilder::addBevelSideCaps( - std::vector &oPoints, const CenterlinePoint &cPoint) -{ - //Build the envelope directions - TPointD leftDPrev, leftDNext, rightDPrev, rightDNext; - buildEnvelopeDirections(cPoint.m_p, cPoint.m_prevD, leftDPrev, rightDPrev); - buildEnvelopeDirections(cPoint.m_p, cPoint.m_nextD, leftDNext, rightDNext); - - //Add at least 2 outline points (the prevs) - oPoints.push_back(TOutlinePoint(convert(cPoint.m_p) + cPoint.m_p.thick * rightDPrev, cPoint.m_countIdx)); - oPoints.push_back(TOutlinePoint(convert(cPoint.m_p) + cPoint.m_p.thick * leftDPrev, cPoint.m_countIdx)); - - //Only add the additional points when at least one of the envelope differences - //passing from prev to next is above the pixel size - if (2.0 * cPoint.m_p.thick < m_pixSize) - return; - - double threshold = sq(m_pixSize / cPoint.m_p.thick); - - double bevelSizeL = norm2(leftDNext - leftDPrev); - double bevelSizeR = norm2(rightDNext - rightDPrev); - - if (bevelSizeL > threshold || bevelSizeR > threshold) { - oPoints.push_back(convert(cPoint.m_p) + cPoint.m_p.thick * rightDNext); - oPoints.push_back(convert(cPoint.m_p) + cPoint.m_p.thick * leftDNext); - } + std::vector &oPoints, const CenterlinePoint &cPoint) { + // Build the envelope directions + TPointD leftDPrev, leftDNext, rightDPrev, rightDNext; + buildEnvelopeDirections(cPoint.m_p, cPoint.m_prevD, leftDPrev, rightDPrev); + buildEnvelopeDirections(cPoint.m_p, cPoint.m_nextD, leftDNext, rightDNext); + + // Add at least 2 outline points (the prevs) + oPoints.push_back(TOutlinePoint( + convert(cPoint.m_p) + cPoint.m_p.thick * rightDPrev, cPoint.m_countIdx)); + oPoints.push_back(TOutlinePoint( + convert(cPoint.m_p) + cPoint.m_p.thick * leftDPrev, cPoint.m_countIdx)); + + // Only add the additional points when at least one of the envelope + // differences + // passing from prev to next is above the pixel size + if (2.0 * cPoint.m_p.thick < m_pixSize) return; + + double threshold = sq(m_pixSize / cPoint.m_p.thick); + + double bevelSizeL = norm2(leftDNext - leftDPrev); + double bevelSizeR = norm2(rightDNext - rightDPrev); + + if (bevelSizeL > threshold || bevelSizeR > threshold) { + oPoints.push_back(convert(cPoint.m_p) + cPoint.m_p.thick * rightDNext); + oPoints.push_back(convert(cPoint.m_p) + cPoint.m_p.thick * leftDNext); + } } //------------------------------------------------------------ template void tellipticbrush::OutlineBuilder::addMiterSideCaps( - T &oPoints, const CenterlinePoint &cPoint) -{ - //Build the elbow side - - TPointD prevD(cPoint.m_prevD); - prevD = (1.0 / norm(prevD)) * prevD; - TPointD nextD(cPoint.m_nextD); - nextD = (1.0 / norm(nextD)) * nextD; - - double cross = prevD.x * nextD.y - prevD.y * nextD.x; - bool leftSide = (cross < 0); //ie elbow on the left side when turning right - - //Add the intersection point of the outline's tangential extensions - //'Tangential extensions' are just the orthogonals to envelope directions - - //Build envelope directions - TPointD envPrevSide, envNextSide; - buildEnvelopeDirection(cPoint.m_p, cPoint.m_prevD, leftSide, envPrevSide); - buildEnvelopeDirection(cPoint.m_p, cPoint.m_nextD, leftSide, envNextSide); - - //Build tangential directions - TPointD prevTangentialD, nextTangentialD; - if (leftSide) { - prevTangentialD = TPointD(envPrevSide.y, -envPrevSide.x); - nextTangentialD = TPointD(-envNextSide.y, envNextSide.x); - } else { - prevTangentialD = TPointD(-envPrevSide.y, envPrevSide.x); - nextTangentialD = TPointD(envNextSide.y, -envNextSide.x); - } - - //Build the outline points in the envelope directions - envPrevSide = cPoint.m_p.thick * envPrevSide; - envNextSide = cPoint.m_p.thick * envNextSide; - - TPointD p0(convert(cPoint.m_p) + envPrevSide); - TPointD p1(convert(cPoint.m_p) + envNextSide); - - //Set coordinates bounds - double lowerBound = std::max(cPoint.m_p.thick * m_oOptions.m_miterLower, m_pixSize); - double upperBound = cPoint.m_p.thick * m_oOptions.m_miterUpper; - - //Build the intersection between the 2 lines - TPointD cornerCoords(intersectionCoords(p0, prevTangentialD, p1, nextTangentialD)); - if (cornerCoords == TConsts::napd || - cornerCoords.x < lowerBound || cornerCoords.y > upperBound || - cornerCoords.y < lowerBound || cornerCoords.y > upperBound) { - //Bevel caps - addOutlineBuilderFunc(&OutlineBuilder::addBevelSideCaps, oPoints, cPoint); - return; - } - - TPointD corner(p0 + cornerCoords.x * prevTangentialD); - - TPointD envPrevNotSide, envNextNotSide; - buildEnvelopeVector(cPoint.m_p, cPoint.m_prevD, !leftSide, envPrevNotSide); - buildEnvelopeVector(cPoint.m_p, cPoint.m_nextD, !leftSide, envNextNotSide); - - TPointD notSidePrev(convert(cPoint.m_p) + envPrevNotSide); - TPointD notSideNext(convert(cPoint.m_p) + envNextNotSide); - if (leftSide) { - addEnvelopePoint(oPoints, notSidePrev, cPoint.m_countIdx); - addEnvelopePoint(oPoints, convert(cPoint.m_p) + envPrevSide, cPoint.m_countIdx); - - addExtensionPoint(oPoints, 0.5 * (notSidePrev + notSideNext)); - addExtensionPoint(oPoints, corner); - - addEnvelopePoint(oPoints, notSideNext); - addEnvelopePoint(oPoints, convert(cPoint.m_p) + envNextSide); - } else { - addEnvelopePoint(oPoints, convert(cPoint.m_p) + envPrevSide, cPoint.m_countIdx); - addEnvelopePoint(oPoints, notSidePrev, cPoint.m_countIdx); - - addExtensionPoint(oPoints, corner); - addExtensionPoint(oPoints, 0.5 * (notSidePrev + notSideNext)); - - addEnvelopePoint(oPoints, convert(cPoint.m_p) + envNextSide); - addEnvelopePoint(oPoints, notSideNext); - } + T &oPoints, const CenterlinePoint &cPoint) { + // Build the elbow side + + TPointD prevD(cPoint.m_prevD); + prevD = (1.0 / norm(prevD)) * prevD; + TPointD nextD(cPoint.m_nextD); + nextD = (1.0 / norm(nextD)) * nextD; + + double cross = prevD.x * nextD.y - prevD.y * nextD.x; + bool leftSide = (cross < 0); // ie elbow on the left side when turning right + + // Add the intersection point of the outline's tangential extensions + //'Tangential extensions' are just the orthogonals to envelope directions + + // Build envelope directions + TPointD envPrevSide, envNextSide; + buildEnvelopeDirection(cPoint.m_p, cPoint.m_prevD, leftSide, envPrevSide); + buildEnvelopeDirection(cPoint.m_p, cPoint.m_nextD, leftSide, envNextSide); + + // Build tangential directions + TPointD prevTangentialD, nextTangentialD; + if (leftSide) { + prevTangentialD = TPointD(envPrevSide.y, -envPrevSide.x); + nextTangentialD = TPointD(-envNextSide.y, envNextSide.x); + } else { + prevTangentialD = TPointD(-envPrevSide.y, envPrevSide.x); + nextTangentialD = TPointD(envNextSide.y, -envNextSide.x); + } + + // Build the outline points in the envelope directions + envPrevSide = cPoint.m_p.thick * envPrevSide; + envNextSide = cPoint.m_p.thick * envNextSide; + + TPointD p0(convert(cPoint.m_p) + envPrevSide); + TPointD p1(convert(cPoint.m_p) + envNextSide); + + // Set coordinates bounds + double lowerBound = + std::max(cPoint.m_p.thick * m_oOptions.m_miterLower, m_pixSize); + double upperBound = cPoint.m_p.thick * m_oOptions.m_miterUpper; + + // Build the intersection between the 2 lines + TPointD cornerCoords( + intersectionCoords(p0, prevTangentialD, p1, nextTangentialD)); + if (cornerCoords == TConsts::napd || cornerCoords.x < lowerBound || + cornerCoords.y > upperBound || cornerCoords.y < lowerBound || + cornerCoords.y > upperBound) { + // Bevel caps + addOutlineBuilderFunc(&OutlineBuilder::addBevelSideCaps, oPoints, cPoint); + return; + } + + TPointD corner(p0 + cornerCoords.x * prevTangentialD); + + TPointD envPrevNotSide, envNextNotSide; + buildEnvelopeVector(cPoint.m_p, cPoint.m_prevD, !leftSide, envPrevNotSide); + buildEnvelopeVector(cPoint.m_p, cPoint.m_nextD, !leftSide, envNextNotSide); + + TPointD notSidePrev(convert(cPoint.m_p) + envPrevNotSide); + TPointD notSideNext(convert(cPoint.m_p) + envNextNotSide); + if (leftSide) { + addEnvelopePoint(oPoints, notSidePrev, cPoint.m_countIdx); + addEnvelopePoint(oPoints, convert(cPoint.m_p) + envPrevSide, + cPoint.m_countIdx); + + addExtensionPoint(oPoints, 0.5 * (notSidePrev + notSideNext)); + addExtensionPoint(oPoints, corner); + + addEnvelopePoint(oPoints, notSideNext); + addEnvelopePoint(oPoints, convert(cPoint.m_p) + envNextSide); + } else { + addEnvelopePoint(oPoints, convert(cPoint.m_p) + envPrevSide, + cPoint.m_countIdx); + addEnvelopePoint(oPoints, notSidePrev, cPoint.m_countIdx); + + addExtensionPoint(oPoints, corner); + addExtensionPoint(oPoints, 0.5 * (notSidePrev + notSideNext)); + + addEnvelopePoint(oPoints, convert(cPoint.m_p) + envNextSide); + addEnvelopePoint(oPoints, notSideNext); + } } //******************************************************************************** // Outline Builder Function //******************************************************************************** -namespace -{ - -int buildCPointsData(const TStroke &stroke, std::vector &cPoints) -{ - //Build point positions - unsigned int i, pointsCount = cPoints.size(); - int validPointsCount = 0; - for (i = 0; i < pointsCount; ++i) { - CenterlinePoint &cPoint = cPoints[i]; - - cPoint.buildPos(stroke); - cPoint.buildDirs(stroke); - - if (!cPoint.m_covered) - //Covered points simply cannot build envelope directions (forward nor backward). - //So, don't consider them - ++validPointsCount; - } - - if (!validPointsCount) { - //Only single points may end up here. We just solve the problem - //uncovering the first point. - cPoints[0].m_covered = false; - validPointsCount = 1; - } - - return validPointsCount; +namespace { + +int buildCPointsData(const TStroke &stroke, + std::vector &cPoints) { + // Build point positions + unsigned int i, pointsCount = cPoints.size(); + int validPointsCount = 0; + for (i = 0; i < pointsCount; ++i) { + CenterlinePoint &cPoint = cPoints[i]; + + cPoint.buildPos(stroke); + cPoint.buildDirs(stroke); + + if (!cPoint.m_covered) + // Covered points simply cannot build envelope directions (forward nor + // backward). + // So, don't consider them + ++validPointsCount; + } + + if (!validPointsCount) { + // Only single points may end up here. We just solve the problem + // uncovering the first point. + cPoints[0].m_covered = false; + validPointsCount = 1; + } + + return validPointsCount; } -} //namespace +} // namespace //------------------------------------------------------------ -void tellipticbrush::buildOutline( - const TStroke &stroke, std::vector &cPoints, - TStrokeOutline &outline, const OutlinizationData &data) -{ - //Build the centerline points associated with passed stroke parameters - int outlineSize = buildCPointsData(stroke, cPoints); +void tellipticbrush::buildOutline(const TStroke &stroke, + std::vector &cPoints, + TStrokeOutline &outline, + const OutlinizationData &data) { + // Build the centerline points associated with passed stroke parameters + int outlineSize = buildCPointsData(stroke, cPoints); - //Reserve the lower bound known to the outline points - std::vector &oPoints = outline.getArray(); - oPoints.reserve(2 * outlineSize); + // Reserve the lower bound known to the outline points + std::vector &oPoints = outline.getArray(); + oPoints.reserve(2 * outlineSize); - OutlineBuilder outBuilder(data, stroke); + OutlineBuilder outBuilder(data, stroke); - //Now, build the outline - unsigned int i, cPointsCount = cPoints.size(); - for (i = 0;; ++i) { - //Search the next uncovered point - for (; i < cPointsCount && cPoints[i].m_covered; ++i) - ; + // Now, build the outline + unsigned int i, cPointsCount = cPoints.size(); + for (i = 0;; ++i) { + // Search the next uncovered point + for (; i < cPointsCount && cPoints[i].m_covered; ++i) + ; - if (i >= cPointsCount) - break; + if (i >= cPointsCount) break; - //Build the associated outline points - outBuilder.buildOutlinePoints(oPoints, cPoints[i]); - } + // Build the associated outline points + outBuilder.buildOutlinePoints(oPoints, cPoints[i]); + } } //******************************************************************************** // Make Outline Implementation //******************************************************************************** -namespace -{ +namespace { /* Quick container to store all the linearization features to be supported. @@ -1134,152 +1137,151 @@ namespace linearized points) */ struct LinearizatorsSet { - static const int nLinearizators = 3; + static const int nLinearizators = 3; - LengthLinearizator m_lengthLinearizator; - CoverageLinearizator m_coverageLinearizator; - RecursiveLinearizator m_recursiveLinearizator; + LengthLinearizator m_lengthLinearizator; + CoverageLinearizator m_coverageLinearizator; + RecursiveLinearizator m_recursiveLinearizator; - StrokeLinearizator *m_linearizatorPtrs[nLinearizators]; + StrokeLinearizator *m_linearizatorPtrs[nLinearizators]; public: - LinearizatorsSet(const TStroke &stroke, const OutlinizationData &data) - : m_lengthLinearizator(&stroke, data.m_options.m_lengthStep), m_coverageLinearizator(&stroke), m_recursiveLinearizator(&stroke, data.m_pixSize) - { - m_linearizatorPtrs[0] = &m_lengthLinearizator; - m_linearizatorPtrs[1] = &m_coverageLinearizator; - m_linearizatorPtrs[2] = &m_recursiveLinearizator; - } - - StrokeLinearizator *operator[](int i) { return m_linearizatorPtrs[i]; } - const int size() const { return nLinearizators; } + LinearizatorsSet(const TStroke &stroke, const OutlinizationData &data) + : m_lengthLinearizator(&stroke, data.m_options.m_lengthStep) + , m_coverageLinearizator(&stroke) + , m_recursiveLinearizator(&stroke, data.m_pixSize) { + m_linearizatorPtrs[0] = &m_lengthLinearizator; + m_linearizatorPtrs[1] = &m_coverageLinearizator; + m_linearizatorPtrs[2] = &m_recursiveLinearizator; + } + + StrokeLinearizator *operator[](int i) { return m_linearizatorPtrs[i]; } + const int size() const { return nLinearizators; } }; -} //namespace +} // namespace //============================================================================================ -void TOutlineUtil::makeOutline(const TStroke &stroke, - TStrokeOutline &outline, - const TOutlineUtil::OutlineParameter &options) -{ - //Build outlinization data - OutlinizationData data(options); - - //Build a set of linearizators for the specified stroke - LinearizatorsSet linearizators(stroke, data); - - std::vector cPoints, chunkPoints; - int i, chunksCount = stroke.getChunkCount(); - for (i = 0; i < chunksCount; ++i) { - chunkPoints.clear(); - chunkPoints.push_back(CenterlinePoint(i, 0.0)); - - int j, linearsCount = linearizators.size(); - for (j = 0; j < linearsCount; ++j) { - StrokeLinearizator *linearizator = linearizators[j]; - linearizator->linearize(chunkPoints, i); - } - - //These points are just PUSH_BACK'd to the vector. A sorting must be performed - //before storing them in the overall centerline points vector - std::sort(chunkPoints.begin(), chunkPoints.end()); - - cPoints.insert(cPoints.end(), chunkPoints.begin(), chunkPoints.end()); - } - - //Build the final point. - CenterlinePoint last(chunksCount - 1, 1.0); - - //In the selfLoop case, use its info to modify the initial point. - if (stroke.isSelfLoop()) { - CenterlinePoint &first = cPoints[0]; - - first.buildPos(stroke); - first.buildDirs(stroke); - last.buildPos(stroke); - last.buildDirs(stroke); - - first.m_prevD = last.m_prevD; - first.m_hasPrevD = last.m_hasPrevD; - last.m_nextD = first.m_nextD; - last.m_hasNextD = first.m_hasNextD; - first.m_covered = last.m_covered = (first.m_covered && last.m_covered); - } - - cPoints.push_back(last); - - //Now, build the outline associated to the linearized centerline - - //NOTE: It's NOT NECESSARY TO BUILD ALL THE CENTERLINE POINTS BEFORE THIS! - //It's sufficient to build the outline TOGETHER with the centeraline, for each quadratic! - buildOutline(stroke, cPoints, outline, data); +void TOutlineUtil::makeOutline(const TStroke &stroke, TStrokeOutline &outline, + const TOutlineUtil::OutlineParameter &options) { + // Build outlinization data + OutlinizationData data(options); + + // Build a set of linearizators for the specified stroke + LinearizatorsSet linearizators(stroke, data); + + std::vector cPoints, chunkPoints; + int i, chunksCount = stroke.getChunkCount(); + for (i = 0; i < chunksCount; ++i) { + chunkPoints.clear(); + chunkPoints.push_back(CenterlinePoint(i, 0.0)); + + int j, linearsCount = linearizators.size(); + for (j = 0; j < linearsCount; ++j) { + StrokeLinearizator *linearizator = linearizators[j]; + linearizator->linearize(chunkPoints, i); + } + + // These points are just PUSH_BACK'd to the vector. A sorting must be + // performed + // before storing them in the overall centerline points vector + std::sort(chunkPoints.begin(), chunkPoints.end()); + + cPoints.insert(cPoints.end(), chunkPoints.begin(), chunkPoints.end()); + } + + // Build the final point. + CenterlinePoint last(chunksCount - 1, 1.0); + + // In the selfLoop case, use its info to modify the initial point. + if (stroke.isSelfLoop()) { + CenterlinePoint &first = cPoints[0]; + + first.buildPos(stroke); + first.buildDirs(stroke); + last.buildPos(stroke); + last.buildDirs(stroke); + + first.m_prevD = last.m_prevD; + first.m_hasPrevD = last.m_hasPrevD; + last.m_nextD = first.m_nextD; + last.m_hasNextD = first.m_hasNextD; + first.m_covered = last.m_covered = (first.m_covered && last.m_covered); + } + + cPoints.push_back(last); + + // Now, build the outline associated to the linearized centerline + + // NOTE: It's NOT NECESSARY TO BUILD ALL THE CENTERLINE POINTS BEFORE THIS! + // It's sufficient to build the outline TOGETHER with the centeraline, for + // each quadratic! + buildOutline(stroke, cPoints, outline, data); } //============================================================================================ -TRectD TOutlineUtil::computeBBox(const TStroke &stroke) -{ - typedef TStroke::OutlineOptions OOpts; - - //First, calculate the usual stroke bbox - TRectD roundBBox(::computeBBox(stroke)); - const OOpts &oOptions(stroke.outlineOptions()); - - if (oOptions.m_capStyle != OOpts::PROJECTING_CAP && oOptions.m_joinStyle != OOpts::MITER_JOIN) - return roundBBox; - - //Build interesting centerline points (in this case, junction points) - std::vector cPoints; - int i, chunksCount = stroke.getChunkCount(); - for (i = 0; i < chunksCount; ++i) { - CenterlinePoint cPoint(i, 0.0); - - cPoint.buildPos(stroke); - cPoint.buildDirs(stroke); - cPoints.push_back(cPoint); - } - - //Build the final point. - CenterlinePoint last(chunksCount - 1, 1.0); - - last.buildPos(stroke); - last.buildDirs(stroke); - - //In the selfLoop case, use its info to modify the initial point. - if (stroke.isSelfLoop()) { - CenterlinePoint &first = cPoints[0]; - - first.m_prevD = last.m_prevD; - first.m_hasPrevD = last.m_hasPrevD; - last.m_nextD = first.m_nextD; - last.m_hasNextD = first.m_hasNextD; - first.m_covered = last.m_covered = (first.m_covered && last.m_covered); - } - - cPoints.push_back(last); - - //Now, add the associated 'extending' outline points - OutlineBuilder outBuilder(OutlinizationData(), stroke); - TRectD extensionBBox( - (std::numeric_limits::max)(), - (std::numeric_limits::max)(), - -(std::numeric_limits::max)(), - -(std::numeric_limits::max)()); - - unsigned int j, cPointsCount = cPoints.size(); - for (j = 0;; ++j) { - //Search the next uncovered point - for (; j < cPointsCount && cPoints[j].m_covered; ++j) - ; - - if (j >= cPointsCount) - break; - - //Build the associated outline points - outBuilder.buildOutlineExtensions(extensionBBox, cPoints[j]); - } - - //Finally, merge the 2 bboxes - return roundBBox + extensionBBox; +TRectD TOutlineUtil::computeBBox(const TStroke &stroke) { + typedef TStroke::OutlineOptions OOpts; + + // First, calculate the usual stroke bbox + TRectD roundBBox(::computeBBox(stroke)); + const OOpts &oOptions(stroke.outlineOptions()); + + if (oOptions.m_capStyle != OOpts::PROJECTING_CAP && + oOptions.m_joinStyle != OOpts::MITER_JOIN) + return roundBBox; + + // Build interesting centerline points (in this case, junction points) + std::vector cPoints; + int i, chunksCount = stroke.getChunkCount(); + for (i = 0; i < chunksCount; ++i) { + CenterlinePoint cPoint(i, 0.0); + + cPoint.buildPos(stroke); + cPoint.buildDirs(stroke); + cPoints.push_back(cPoint); + } + + // Build the final point. + CenterlinePoint last(chunksCount - 1, 1.0); + + last.buildPos(stroke); + last.buildDirs(stroke); + + // In the selfLoop case, use its info to modify the initial point. + if (stroke.isSelfLoop()) { + CenterlinePoint &first = cPoints[0]; + + first.m_prevD = last.m_prevD; + first.m_hasPrevD = last.m_hasPrevD; + last.m_nextD = first.m_nextD; + last.m_hasNextD = first.m_hasNextD; + first.m_covered = last.m_covered = (first.m_covered && last.m_covered); + } + + cPoints.push_back(last); + + // Now, add the associated 'extending' outline points + OutlineBuilder outBuilder(OutlinizationData(), stroke); + TRectD extensionBBox((std::numeric_limits::max)(), + (std::numeric_limits::max)(), + -(std::numeric_limits::max)(), + -(std::numeric_limits::max)()); + + unsigned int j, cPointsCount = cPoints.size(); + for (j = 0;; ++j) { + // Search the next uncovered point + for (; j < cPointsCount && cPoints[j].m_covered; ++j) + ; + + if (j >= cPointsCount) break; + + // Build the associated outline points + outBuilder.buildOutlineExtensions(extensionBBox, cPoints[j]); + } + + // Finally, merge the 2 bboxes + return roundBBox + extensionBBox; } diff --git a/toonz/sources/common/tvrender/tellipticbrushP.h b/toonz/sources/common/tvrender/tellipticbrushP.h index 66f9cbf..74fa13c 100644 --- a/toonz/sources/common/tvrender/tellipticbrushP.h +++ b/toonz/sources/common/tvrender/tellipticbrushP.h @@ -5,13 +5,12 @@ #include "tcurves.h" #include "tstroke.h" -#include "tgl.h" //tglPixelSize +#include "tgl.h" //tglPixelSize #include "tstrokeoutline.h" -namespace tellipticbrush -{ +namespace tellipticbrush { -//!Tolerance parameter used somewhere throughout this code. +//! Tolerance parameter used somewhere throughout this code. const double tolPar = 1e-6; //******************************************************************************** @@ -22,15 +21,21 @@ double dist(const TPointD &P1, const TPointD &P2); double dist(const TThickPoint &P1, const TThickPoint &P2); double angle(const TPointD &v1, const TPointD &v2); -TPointD intersectionCoords(const TPointD &P0, const TPointD &d0, const TPointD &P1, const TPointD &d1, - double detTol = 1e-2); +TPointD intersectionCoords(const TPointD &P0, const TPointD &d0, + const TPointD &P1, const TPointD &d1, + double detTol = 1e-2); -void buildEnvelopeDirection(const TThickPoint &p, const TThickPoint &d, bool left, TPointD &res); -void buildEnvelopeDirections(const TThickPoint &p, const TThickPoint &d, TPointD &resL, TPointD &resR); -void buildEnvelopeVector(const TThickPoint &p, const TThickPoint &d, bool left, TPointD &res); -void buildEnvelopeVectors(const TThickPoint &p, const TThickPoint &d, TPointD &resL, TPointD &resR); +void buildEnvelopeDirection(const TThickPoint &p, const TThickPoint &d, + bool left, TPointD &res); +void buildEnvelopeDirections(const TThickPoint &p, const TThickPoint &d, + TPointD &resL, TPointD &resR); +void buildEnvelopeVector(const TThickPoint &p, const TThickPoint &d, bool left, + TPointD &res); +void buildEnvelopeVectors(const TThickPoint &p, const TThickPoint &d, + TPointD &resL, TPointD &resR); -void buildAngularSubdivision(double radius, double angle, double err, int &nAngles); +void buildAngularSubdivision(double radius, double angle, double err, + int &nAngles); TRectD computeBBox(const TStroke &stroke); @@ -42,14 +47,12 @@ TRectD computeBBox(const TStroke &stroke); Structure needed to hold both external and internal outlinization parameters. */ struct OutlinizationData { - TOutlineUtil::OutlineParameter m_options; - double m_pixSize; - - OutlinizationData() : m_options(), m_pixSize(0.0) {} - OutlinizationData(const TOutlineUtil::OutlineParameter &options) - : m_options(options), m_pixSize(sqrt(tglGetPixelSize2())) - { - } + TOutlineUtil::OutlineParameter m_options; + double m_pixSize; + + OutlinizationData() : m_options(), m_pixSize(0.0) {} + OutlinizationData(const TOutlineUtil::OutlineParameter &options) + : m_options(options), m_pixSize(sqrt(tglGetPixelSize2())) {} }; //******************************************************************************** @@ -57,44 +60,52 @@ struct OutlinizationData { //******************************************************************************** /*! - CenterlinePoint contains the data a about a discretized centerline stroke point - + CenterlinePoint contains the data a about a discretized centerline stroke + point - which includes its position, and eventual forward and backward derivative-like directions. Thickness data is included in the structure. - These informations are necessary and sufficient to build associated outline points, + These informations are necessary and sufficient to build associated outline + points, and eventual additional points related to caps. */ struct CenterlinePoint { - int m_chunkIdx; //!< The quadratic chunk index containing this point - double m_t; //!< The quadratic parameter where this point can be found + int m_chunkIdx; //!< The quadratic chunk index containing this point + double m_t; //!< The quadratic parameter where this point can be found - TThickPoint m_p; //!< The point's thick coordinates - bool m_posBuilt; //!< Wheteher m_p has been calculated + TThickPoint m_p; //!< The point's thick coordinates + bool m_posBuilt; //!< Wheteher m_p has been calculated - TThickPoint m_prevD; //!< The backward direction - bool m_hasPrevD; //!< If the point has (envelopable) backward direction + TThickPoint m_prevD; //!< The backward direction + bool m_hasPrevD; //!< If the point has (envelopable) backward direction - TThickPoint m_nextD; //!< The forward direction - bool m_hasNextD; //!< If the point has (envelopable) forward direction + TThickPoint m_nextD; //!< The forward direction + bool m_hasNextD; //!< If the point has (envelopable) forward direction - bool m_dirsBuilt; //!< Whether directions have been calculated + bool m_dirsBuilt; //!< Whether directions have been calculated - bool m_covered; //!< Whether this point's outline can't be seen + bool m_covered; //!< Whether this point's outline can't be seen - int m_countIdx; //!< Additional index needed by some procedural style... + int m_countIdx; //!< Additional index needed by some procedural style... - CenterlinePoint() : m_chunkIdx(-1), m_posBuilt(false), m_dirsBuilt(false) {} - CenterlinePoint(int chunk, double t) : m_chunkIdx(chunk), m_t(t), m_posBuilt(false), m_dirsBuilt(false), m_countIdx(0) {} + CenterlinePoint() : m_chunkIdx(-1), m_posBuilt(false), m_dirsBuilt(false) {} + CenterlinePoint(int chunk, double t) + : m_chunkIdx(chunk) + , m_t(t) + , m_posBuilt(false) + , m_dirsBuilt(false) + , m_countIdx(0) {} - ~CenterlinePoint() {} + ~CenterlinePoint() {} - void buildPos(const TStroke &stroke); - void buildDirs(const TStroke &stroke); + void buildPos(const TStroke &stroke); + void buildDirs(const TStroke &stroke); - bool operator<(const CenterlinePoint &cp) const - { - return m_chunkIdx < cp.m_chunkIdx ? true : m_chunkIdx > cp.m_chunkIdx ? false : m_t < cp.m_t; - } + bool operator<(const CenterlinePoint &cp) const { + return m_chunkIdx < cp.m_chunkIdx + ? true + : m_chunkIdx > cp.m_chunkIdx ? false : m_t < cp.m_t; + } }; //******************************************************************************** @@ -105,24 +116,23 @@ struct CenterlinePoint { The StrokeLinearizator class models a stroke linearization interface that extracts points of interest from a succession of stroke quadratics. */ -class StrokeLinearizator -{ +class StrokeLinearizator { protected: - const TStroke *m_stroke; + const TStroke *m_stroke; public: - StrokeLinearizator(const TStroke *stroke) : m_stroke(stroke) {} - virtual ~StrokeLinearizator() {} - - /*! - Adds interesting stroke points to be discretized in the - chunk-th TThickQuadratic stroke. - - \note The initial point (P0) of the quadratic is always added by the - outlinization algorithm before these linearization functions are invoked - (whereas P2 belongs to the next quadratic). - */ - virtual void linearize(std::vector &cPoints, int chunk) = 0; + StrokeLinearizator(const TStroke *stroke) : m_stroke(stroke) {} + virtual ~StrokeLinearizator() {} + + /*! +Adds interesting stroke points to be discretized in the +chunk-th TThickQuadratic stroke. + +\note The initial point (P0) of the quadratic is always added by the +outlinization algorithm before these linearization functions are invoked +(whereas P2 belongs to the next quadratic). +*/ + virtual void linearize(std::vector &cPoints, int chunk) = 0; }; //******************************************************************************** @@ -135,79 +145,84 @@ public: instance and build a couple of outline points - at either side of the centerline - eventually adding (cap) points to form a smooth outline. */ -class OutlineBuilder -{ - double m_pixSize; - TStroke::OutlineOptions m_oOptions; +class OutlineBuilder { + double m_pixSize; + TStroke::OutlineOptions m_oOptions; - int m_lastChunk; + int m_lastChunk; private: - typedef void (OutlineBuilder::*OutlineBuilderFunc)( - std::vector &outPoints, const CenterlinePoint &cPoint); + typedef void (OutlineBuilder::*OutlineBuilderFunc)( + std::vector &outPoints, const CenterlinePoint &cPoint); - OutlineBuilderFunc m_addBeginCap; - OutlineBuilderFunc m_addEndCap; - OutlineBuilderFunc m_addSideCaps; + OutlineBuilderFunc m_addBeginCap; + OutlineBuilderFunc m_addEndCap; + OutlineBuilderFunc m_addSideCaps; - typedef void (OutlineBuilder::*BBoxBuilderFunc)( - TRectD &bbox, const CenterlinePoint &cPoint); + typedef void (OutlineBuilder::*BBoxBuilderFunc)( + TRectD &bbox, const CenterlinePoint &cPoint); - BBoxBuilderFunc m_addBeginCap_ext; - BBoxBuilderFunc m_addEndCap_ext; - BBoxBuilderFunc m_addSideCaps_ext; + BBoxBuilderFunc m_addBeginCap_ext; + BBoxBuilderFunc m_addEndCap_ext; + BBoxBuilderFunc m_addSideCaps_ext; private: - /* - Type-specific outline container functions. - Used with outline building sub-routines that may be used to supply - different outline container types. - For example, a TRectD may be considered a container class to be used - when building the outline bbox. - */ - template - void addEnvelopePoint(T &container, const TPointD &oPoint, int countIdx = 0); - template - void addExtensionPoint(T &container, const TPointD &oPoint, int countIdx = 0); - template - void addOutlineBuilderFunc(OutlineBuilder::OutlineBuilderFunc func, - T &container, const CenterlinePoint &cPoint); + /* +Type-specific outline container functions. +Used with outline building sub-routines that may be used to supply +different outline container types. +For example, a TRectD may be considered a container class to be used +when building the outline bbox. +*/ + template + void addEnvelopePoint(T &container, const TPointD &oPoint, int countIdx = 0); + template + void addExtensionPoint(T &container, const TPointD &oPoint, int countIdx = 0); + template + void addOutlineBuilderFunc(OutlineBuilder::OutlineBuilderFunc func, + T &container, const CenterlinePoint &cPoint); public: - OutlineBuilder(const OutlinizationData &data, const TStroke &stroke); - ~OutlineBuilder() {} + OutlineBuilder(const OutlinizationData &data, const TStroke &stroke); + ~OutlineBuilder() {} - /*! - Transforms the specified centerline point into outline points, and adds them to - the supplied outline points vector. - */ - void buildOutlinePoints( - std::vector &outPoints, const CenterlinePoint &cPoint); + /*! +Transforms the specified centerline point into outline points, and adds them to +the supplied outline points vector. +*/ + void buildOutlinePoints(std::vector &outPoints, + const CenterlinePoint &cPoint); - void buildOutlineExtensions(TRectD &bbox, const CenterlinePoint &cPoint); + void buildOutlineExtensions(TRectD &bbox, const CenterlinePoint &cPoint); private: - void addCircle(std::vector &oPoints, const CenterlinePoint &cPoint); - void addCircularArcPoints( - int idx, std::vector &outPoints, - const TPointD ¢er, const TPointD &ray, double angle, int nAngles, - int countIdx); - - void addRoundBeginCap(std::vector &oPoints, const CenterlinePoint &cPoint); - void addRoundEndCap(std::vector &oPoints, const CenterlinePoint &cPoint); - - void addButtBeginCap(std::vector &oPoints, const CenterlinePoint &cPoint); - void addButtEndCap(std::vector &oPoints, const CenterlinePoint &cPoint); - - template - void addProjectingBeginCap(T &oPoints, const CenterlinePoint &cPoint); - template - void addProjectingEndCap(T &oPoints, const CenterlinePoint &cPoint); - - void addRoundSideCaps(std::vector &oPoints, const CenterlinePoint &cPoint); - void addBevelSideCaps(std::vector &oPoints, const CenterlinePoint &cPoint); - template - void addMiterSideCaps(T &oPoints, const CenterlinePoint &cPoint); + void addCircle(std::vector &oPoints, + const CenterlinePoint &cPoint); + void addCircularArcPoints(int idx, std::vector &outPoints, + const TPointD ¢er, const TPointD &ray, + double angle, int nAngles, int countIdx); + + void addRoundBeginCap(std::vector &oPoints, + const CenterlinePoint &cPoint); + void addRoundEndCap(std::vector &oPoints, + const CenterlinePoint &cPoint); + + void addButtBeginCap(std::vector &oPoints, + const CenterlinePoint &cPoint); + void addButtEndCap(std::vector &oPoints, + const CenterlinePoint &cPoint); + + template + void addProjectingBeginCap(T &oPoints, const CenterlinePoint &cPoint); + template + void addProjectingEndCap(T &oPoints, const CenterlinePoint &cPoint); + + void addRoundSideCaps(std::vector &oPoints, + const CenterlinePoint &cPoint); + void addBevelSideCaps(std::vector &oPoints, + const CenterlinePoint &cPoint); + template + void addMiterSideCaps(T &oPoints, const CenterlinePoint &cPoint); }; //******************************************************************************** @@ -217,25 +232,22 @@ private: // Container of Outline Points (for common outline extraction) template <> -inline void OutlineBuilder::addEnvelopePoint(std::vector &oPoints, - const TPointD &oPoint, int countIdx) -{ - oPoints.push_back(TOutlinePoint(oPoint, countIdx)); +inline void OutlineBuilder::addEnvelopePoint( + std::vector &oPoints, const TPointD &oPoint, int countIdx) { + oPoints.push_back(TOutlinePoint(oPoint, countIdx)); } template <> -inline void OutlineBuilder::addExtensionPoint(std::vector &oPoints, - const TPointD &oPoint, int countIdx) -{ - oPoints.push_back(TOutlinePoint(oPoint, countIdx)); +inline void OutlineBuilder::addExtensionPoint( + std::vector &oPoints, const TPointD &oPoint, int countIdx) { + oPoints.push_back(TOutlinePoint(oPoint, countIdx)); } template <> inline void OutlineBuilder::addOutlineBuilderFunc( - OutlineBuilder::OutlineBuilderFunc func, - std::vector &oPoints, const CenterlinePoint &cPoint) -{ - (this->*func)(oPoints, cPoint); + OutlineBuilder::OutlineBuilderFunc func, + std::vector &oPoints, const CenterlinePoint &cPoint) { + (this->*func)(oPoints, cPoint); } //============================================================================================ @@ -243,33 +255,32 @@ inline void OutlineBuilder::addOutlineBuilderFunc( // Rect (for bounding box extraction) template <> -inline void OutlineBuilder::addEnvelopePoint(TRectD &bbox, const TPointD &oPoint, int countIdx) -{ -} +inline void OutlineBuilder::addEnvelopePoint(TRectD &bbox, + const TPointD &oPoint, + int countIdx) {} template <> -inline void OutlineBuilder::addExtensionPoint(TRectD &bbox, const TPointD &oPoint, int countIdx) -{ - bbox.x0 = std::min(bbox.x0, oPoint.x); - bbox.y0 = std::min(bbox.y0, oPoint.y); - bbox.x1 = std::max(bbox.x1, oPoint.x); - bbox.y1 = std::max(bbox.y1, oPoint.y); +inline void OutlineBuilder::addExtensionPoint(TRectD &bbox, + const TPointD &oPoint, + int countIdx) { + bbox.x0 = std::min(bbox.x0, oPoint.x); + bbox.y0 = std::min(bbox.y0, oPoint.y); + bbox.x1 = std::max(bbox.x1, oPoint.x); + bbox.y1 = std::max(bbox.y1, oPoint.y); } template <> inline void OutlineBuilder::addOutlineBuilderFunc( - OutlineBuilder::OutlineBuilderFunc func, - TRectD &container, const CenterlinePoint &cPoint) -{ -} + OutlineBuilder::OutlineBuilderFunc func, TRectD &container, + const CenterlinePoint &cPoint) {} //******************************************************************************** // Standard Outline Builder (from Centerline Points) //******************************************************************************** void buildOutline(const TStroke &stroke, std::vector &cPoints, - TStrokeOutline &outline, const OutlinizationData &data); + TStrokeOutline &outline, const OutlinizationData &data); -} //namespace tellipticbrush +} // namespace tellipticbrush -#endif //TELLIPTIC_BRUSH_P_H +#endif // TELLIPTIC_BRUSH_P_H diff --git a/toonz/sources/common/tvrender/tflash.cpp b/toonz/sources/common/tvrender/tflash.cpp index 8a1aead..999b837 100644 --- a/toonz/sources/common/tvrender/tflash.cpp +++ b/toonz/sources/common/tvrender/tflash.cpp @@ -30,193 +30,212 @@ TNZ_LITTLE_ENDIAN undefined !! #endif - int Tw = 0; + int Tw = 0; -bool areTwEqual(double x, double y) -{ - assert(Tw != 0); +bool areTwEqual(double x, double y) { + assert(Tw != 0); - return (int)(Tw * x) == (int)(Tw * y); + return (int)(Tw * x) == (int)(Tw * y); } -bool areTwEqual(TPointD p0, TPointD p1) -{ - assert(Tw != 0); +bool areTwEqual(TPointD p0, TPointD p1) { + assert(Tw != 0); - return areTwEqual(p0.x, p1.x) && areTwEqual(p0.y, p1.y); + return areTwEqual(p0.x, p1.x) && areTwEqual(p0.y, p1.y); } //------------------------------------------------------------------- const std::wstring TFlash::ConstantLines = L"Low: Constant Thickness"; -const std::wstring TFlash::MixedLines = L"Medium: Mixed Thickness"; +const std::wstring TFlash::MixedLines = L"Medium: Mixed Thickness"; const std::wstring TFlash::VariableLines = L"High: Variable Thickness"; Tiio::SwfWriterProperties::SwfWriterProperties() - : m_lineQuality("Curve Quality"), m_isCompressed("File Compression", true), m_autoplay("Autoplay", true), m_looping("Looping", true), m_jpgQuality("Jpg Quality", 0, 100, 90), m_url("URL", std::wstring()), m_preloader("Insert Preloader", false) -{ - m_lineQuality.addValue(TFlash::MixedLines); - m_lineQuality.addValue(TFlash::ConstantLines); - m_lineQuality.addValue(TFlash::VariableLines); - - bind(m_lineQuality); - bind(m_isCompressed); - bind(m_autoplay); - bind(m_looping); - bind(m_jpgQuality); - bind(m_url); - bind(m_preloader); - - TEnumProperty::Range range = m_lineQuality.getRange(); + : m_lineQuality("Curve Quality") + , m_isCompressed("File Compression", true) + , m_autoplay("Autoplay", true) + , m_looping("Looping", true) + , m_jpgQuality("Jpg Quality", 0, 100, 90) + , m_url("URL", std::wstring()) + , m_preloader("Insert Preloader", false) { + m_lineQuality.addValue(TFlash::MixedLines); + m_lineQuality.addValue(TFlash::ConstantLines); + m_lineQuality.addValue(TFlash::VariableLines); + + bind(m_lineQuality); + bind(m_isCompressed); + bind(m_autoplay); + bind(m_looping); + bind(m_jpgQuality); + bind(m_url); + bind(m_preloader); + + TEnumProperty::Range range = m_lineQuality.getRange(); } //------------------------------------------------------------------- -enum PolyType { None, - Centerline, - Solid, - Texture, - LinearGradient, - RadialGradient }; +enum PolyType { + None, + Centerline, + Solid, + Texture, + LinearGradient, + RadialGradient +}; -class PolyStyle -{ +class PolyStyle { public: - PolyType m_type; - TPixel32 m_color1; //only if type!=Texture - TPixel32 m_color2; //only if type==LinearGradient || type==RadialGradient - double m_smooth; //only if type==RadialGradient - double m_thickness; //only if type==Centerline - TAffine m_matrix; //only if type==Texture - TRaster32P m_texture; //only if type==Texture - //bool m_isRegion; //only if type!=Centerline - //bool m_isHole; //only if type!=Centerline && m_isRegion==true - PolyStyle() : m_type(None), m_color1(), m_color2(), m_smooth(0), m_thickness(0), m_matrix(), m_texture() /*, m_isRegion(false), m_isHole(false)*/ {} - bool operator==(const PolyStyle &p) const; - bool operator<(const PolyStyle &p) const; + PolyType m_type; + TPixel32 m_color1; // only if type!=Texture + TPixel32 m_color2; // only if type==LinearGradient || type==RadialGradient + double m_smooth; // only if type==RadialGradient + double m_thickness; // only if type==Centerline + TAffine m_matrix; // only if type==Texture + TRaster32P m_texture; // only if type==Texture + // bool m_isRegion; //only if type!=Centerline + // bool m_isHole; //only if type!=Centerline && m_isRegion==true + PolyStyle() + : m_type(None) + , m_color1() + , m_color2() + , m_smooth(0) + , m_thickness(0) + , m_matrix() + , m_texture() /*, m_isRegion(false), m_isHole(false)*/ {} + bool operator==(const PolyStyle &p) const; + bool operator<(const PolyStyle &p) const; }; -class FlashPolyline -{ +class FlashPolyline { public: - UINT m_depth; - bool m_skip; - bool m_toBeDeleted; - bool m_isPoint; - std::vector m_quads; - PolyStyle m_fillStyle1; - PolyStyle m_fillStyle2; - PolyStyle m_lineStyle; - //PolyStyle m_bgStyle; - FlashPolyline() : m_depth(0), m_skip(false), m_toBeDeleted(false), m_isPoint(false), m_fillStyle1(), m_fillStyle2(), m_lineStyle() {} - bool operator<(const FlashPolyline &p) const { return m_depth < p.m_depth; } + UINT m_depth; + bool m_skip; + bool m_toBeDeleted; + bool m_isPoint; + std::vector m_quads; + PolyStyle m_fillStyle1; + PolyStyle m_fillStyle2; + PolyStyle m_lineStyle; + // PolyStyle m_bgStyle; + FlashPolyline() + : m_depth(0) + , m_skip(false) + , m_toBeDeleted(false) + , m_isPoint(false) + , m_fillStyle1() + , m_fillStyle2() + , m_lineStyle() {} + bool operator<(const FlashPolyline &p) const { return m_depth < p.m_depth; } }; -class biPoint -{ +class biPoint { public: - TPointD p0, p1; - - biPoint(TPointD _p0, TPointD _p1) : p0(_p0), p1(_p1) {} - biPoint() {} - bool operator<(const biPoint &b) const - { - biPoint aux; - aux.p0.x = areTwEqual(p0.x, b.p0.x) ? p0.x : b.p0.x; - aux.p0.y = areTwEqual(p0.y, b.p0.y) ? p0.y : b.p0.y; - aux.p1.x = areTwEqual(p1.x, b.p1.x) ? p1.x : b.p1.x; - aux.p1.y = areTwEqual(p1.y, b.p1.y) ? p1.y : b.p1.y; - - return (p0.x == aux.p0.x) ? ((p0.y == aux.p0.y) ? ((p1.x == aux.p1.x) ? (p1.y < aux.p1.y) : (p1.x < aux.p1.x)) : (p0.y < aux.p0.y)) : p0.x < aux.p0.x; - } - void revert() { tswap(p0, p1); } + TPointD p0, p1; + + biPoint(TPointD _p0, TPointD _p1) : p0(_p0), p1(_p1) {} + biPoint() {} + bool operator<(const biPoint &b) const { + biPoint aux; + aux.p0.x = areTwEqual(p0.x, b.p0.x) ? p0.x : b.p0.x; + aux.p0.y = areTwEqual(p0.y, b.p0.y) ? p0.y : b.p0.y; + aux.p1.x = areTwEqual(p1.x, b.p1.x) ? p1.x : b.p1.x; + aux.p1.y = areTwEqual(p1.y, b.p1.y) ? p1.y : b.p1.y; + + return (p0.x == aux.p0.x) + ? ((p0.y == aux.p0.y) ? ((p1.x == aux.p1.x) ? (p1.y < aux.p1.y) + : (p1.x < aux.p1.x)) + : (p0.y < aux.p0.y)) + : p0.x < aux.p0.x; + } + void revert() { tswap(p0, p1); } }; -class wChunk -{ +class wChunk { public: - double w0, w1; - wChunk(double _w0, double _w1) : w0(_w0), w1(_w1) {} - bool operator<(const wChunk &b) const { return (w1 < b.w0); } + double w0, w1; + wChunk(double _w0, double _w1) : w0(_w0), w1(_w1) {} + bool operator<(const wChunk &b) const { return (w1 < b.w0); } }; //------------------------------------------------------------------- -const int c_soundRate = 5512; // 5512; //11025 -const int c_soundBps = 16; -const bool c_soundIsSigned = false; +const int c_soundRate = 5512; // 5512; //11025 +const int c_soundBps = 16; +const bool c_soundIsSigned = false; const int c_soundChannelNum = 1; -const int c_soundCompression = 3; //per compatibilita' con MAC!!! +const int c_soundCompression = 3; // per compatibilita' con MAC!!! //------------------------------------------------------------------- -class FlashImageData -{ +class FlashImageData { public: - FlashImageData(TAffine aff, TImageP img, const TColorFunction *cf, bool isMask, bool isMasked) - : m_aff(aff), m_img(img), m_cf(cf), m_isMask(isMask), m_isMasked(isMasked) - { - assert(!isMask || !isMasked); - } - TAffine m_aff; - const TColorFunction *m_cf; - bool m_isMask, m_isMasked; - TImageP m_img; + FlashImageData(TAffine aff, TImageP img, const TColorFunction *cf, + bool isMask, bool isMasked) + : m_aff(aff) + , m_img(img) + , m_cf(cf) + , m_isMask(isMask) + , m_isMasked(isMasked) { + assert(!isMask || !isMasked); + } + TAffine m_aff; + const TColorFunction *m_cf; + bool m_isMask, m_isMasked; + TImageP m_img; }; -double computeAverageThickness(const TStroke *s) -{ - int count = s->getControlPointCount(); - double resThick = 0; - int i; - - for (i = 0; i < s->getControlPointCount(); i++) { - double thick = s->getControlPoint(i).thick; - if (i >= 2 && i < s->getControlPointCount() - 2) - resThick += thick; - } - if (count < 6) - return s->getControlPoint(count / 2 + 1).thick; - - return resThick / (s->getControlPointCount() - 4); +double computeAverageThickness(const TStroke *s) { + int count = s->getControlPointCount(); + double resThick = 0; + int i; + + for (i = 0; i < s->getControlPointCount(); i++) { + double thick = s->getControlPoint(i).thick; + if (i >= 2 && i < s->getControlPointCount() - 2) resThick += thick; + } + if (count < 6) return s->getControlPoint(count / 2 + 1).thick; + + return resThick / (s->getControlPointCount() - 4); } -void putquads(const TStroke *s, double w0, double w1, std::vector &quads) -{ - int chunkIndex0, chunkIndex1, i; - double dummy; - bool ret; +void putquads(const TStroke *s, double w0, double w1, + std::vector &quads) { + int chunkIndex0, chunkIndex1, i; + double dummy; + bool ret; - ret = s->getChunkAndT(w0, chunkIndex0, dummy); - assert(!ret); - ret = s->getChunkAndT(w1, chunkIndex1, dummy); - assert(!ret); - assert(chunkIndex0 <= chunkIndex1); + ret = s->getChunkAndT(w0, chunkIndex0, dummy); + assert(!ret); + ret = s->getChunkAndT(w1, chunkIndex1, dummy); + assert(!ret); + assert(chunkIndex0 <= chunkIndex1); - for (i = chunkIndex0; i <= chunkIndex1; i++) - quads.push_back((TQuadratic *)s->getChunk(i)); + for (i = chunkIndex0; i <= chunkIndex1; i++) + quads.push_back((TQuadratic *)s->getChunk(i)); } //------------------------------------------------------------------- -void computeOutlineBoundary(std::vector &outlines, std::list &polylinesArray, const TPixel &color) -{ - UINT size = polylinesArray.size(); - - std::vector> quads; - computeSweepBoundary(outlines, quads); - - outlines.clear(); - std::list::iterator it = polylinesArray.begin(); - std::advance(it, size); - for (int i = 0; i < (int)quads.size(); i++) { - std::vector &q = quads[i]; - - polylinesArray.push_back(FlashPolyline()); - polylinesArray.back().m_quads = quads[i]; - polylinesArray.back().m_toBeDeleted = true; - polylinesArray.back().m_fillStyle1.m_type = Solid; - polylinesArray.back().m_fillStyle1.m_color1 = color; - } +void computeOutlineBoundary(std::vector &outlines, + std::list &polylinesArray, + const TPixel &color) { + UINT size = polylinesArray.size(); + + std::vector> quads; + computeSweepBoundary(outlines, quads); + + outlines.clear(); + std::list::iterator it = polylinesArray.begin(); + std::advance(it, size); + for (int i = 0; i < (int)quads.size(); i++) { + std::vector &q = quads[i]; + + polylinesArray.push_back(FlashPolyline()); + polylinesArray.back().m_quads = quads[i]; + polylinesArray.back().m_toBeDeleted = true; + polylinesArray.back().m_fillStyle1.m_type = Solid; + polylinesArray.back().m_fillStyle1.m_color1 = color; + } } //------------------------------------------------------------------- @@ -224,167 +243,164 @@ void computeOutlineBoundary(std::vector &outlines, std::list segmentArray, bool isGradientColor) -{ -} +void TFlash::drawSegments(const std::vector segmentArray, + bool isGradientColor) {} -void TFlash::drawquads(const std::vector quadsArray) -{ -} +void TFlash::drawquads(const std::vector quadsArray) {} //------------------------------------------------------------------- -bool PolyStyle::operator==(const PolyStyle &p) const -{ - if (m_type != p.m_type) - return false; - - switch (m_type) { - case Centerline: - return m_thickness == p.m_thickness && m_color1 == p.m_color1; - case Solid: - return m_color1 == p.m_color1; - case Texture: - return m_matrix == p.m_matrix && m_texture.getPointer() == p.m_texture.getPointer(); - case LinearGradient: - case RadialGradient: - return m_color1 == p.m_color1 && m_color2 == p.m_color2 && m_matrix == p.m_matrix && m_smooth == p.m_smooth; - default: - assert(false); - return false; - } +bool PolyStyle::operator==(const PolyStyle &p) const { + if (m_type != p.m_type) return false; + + switch (m_type) { + case Centerline: + return m_thickness == p.m_thickness && m_color1 == p.m_color1; + case Solid: + return m_color1 == p.m_color1; + case Texture: + return m_matrix == p.m_matrix && + m_texture.getPointer() == p.m_texture.getPointer(); + case LinearGradient: + case RadialGradient: + return m_color1 == p.m_color1 && m_color2 == p.m_color2 && + m_matrix == p.m_matrix && m_smooth == p.m_smooth; + default: + assert(false); + return false; + } } //------------------------------------------------------------------- -bool affineMinorThen(const TAffine &m0, const TAffine &m1) -{ - if (m0.a11 == m1.a11) { - if (m0.a12 == m1.a12) { - if (m0.a13 == m1.a13) { - if (m0.a21 == m1.a21) { - if (m0.a22 == m1.a22) - return m0.a23 < m1.a23; - else - return m0.a22 < m1.a22; - } else - return m0.a21 < m1.a21; - } else - return m0.a13 < m1.a13; - } else - return m0.a12 < m1.a12; - } else - return m0.a11 < m1.a11; +bool affineMinorThen(const TAffine &m0, const TAffine &m1) { + if (m0.a11 == m1.a11) { + if (m0.a12 == m1.a12) { + if (m0.a13 == m1.a13) { + if (m0.a21 == m1.a21) { + if (m0.a22 == m1.a22) + return m0.a23 < m1.a23; + else + return m0.a22 < m1.a22; + } else + return m0.a21 < m1.a21; + } else + return m0.a13 < m1.a13; + } else + return m0.a12 < m1.a12; + } else + return m0.a11 < m1.a11; } //------------------------------------------------------------------- -bool PolyStyle::operator<(const PolyStyle &p) const -{ - if (m_type == p.m_type) - switch (m_type) { - case Centerline: - return (m_thickness == p.m_thickness) ? m_color1 < p.m_color1 : m_thickness < p.m_thickness; - case Solid: - return m_color1 < p.m_color1; - case Texture: - return m_texture.getPointer() < p.m_texture.getPointer(); //ignoro la matrice!!!! - case LinearGradient: - case RadialGradient: - return (m_smooth == p.m_smooth) ? ((m_color1 == p.m_color1) ? ((m_color2 == p.m_color2) ? affineMinorThen(m_matrix, p.m_matrix) : m_color2 < p.m_color2) : m_color1 < p.m_color1) : m_smooth < p.m_smooth; - default: - assert(false); - return false; - } - else - return m_type < p.m_type; +bool PolyStyle::operator<(const PolyStyle &p) const { + if (m_type == p.m_type) switch (m_type) { + case Centerline: + return (m_thickness == p.m_thickness) ? m_color1 < p.m_color1 + : m_thickness < p.m_thickness; + case Solid: + return m_color1 < p.m_color1; + case Texture: + return m_texture.getPointer() < + p.m_texture.getPointer(); // ignoro la matrice!!!! + case LinearGradient: + case RadialGradient: + return (m_smooth == p.m_smooth) + ? ((m_color1 == p.m_color1) + ? ((m_color2 == p.m_color2) + ? affineMinorThen(m_matrix, p.m_matrix) + : m_color2 < p.m_color2) + : m_color1 < p.m_color1) + : m_smooth < p.m_smooth; + default: + assert(false); + return false; + } + else + return m_type < p.m_type; } //------------------------------------------------------------------- -void computeQuadChain(const TEdge &e, - std::vector &quadArray, std::vector &toBeDeleted) -{ - int chunk_b, chunk_e, chunk = -1; - double t_b, t_e, w0, w1; - TThickQuadratic *q_b = 0, *q_e = 0; - TThickQuadratic dummy; - bool reversed = false; - - if (e.m_w0 > e.m_w1) { - reversed = true; - w0 = e.m_w1; - w1 = e.m_w0; - } else { - w0 = e.m_w0; - w1 = e.m_w1; - } - - if (w0 == 0.0) - chunk_b = 0; - else { - if (e.m_s->getChunkAndT(w0, chunk, t_b)) - assert(false); - q_b = new TThickQuadratic(); - toBeDeleted.push_back(q_b); - e.m_s->getChunk(chunk)->split(t_b, dummy, *q_b); - chunk_b = chunk + 1; - } - - if (w1 == 1.0) - chunk_e = e.m_s->getChunkCount() - 1; - else { - if (e.m_s->getChunkAndT(w1, chunk_e, t_e)) - assert(false); - q_e = new TThickQuadratic(); - toBeDeleted.push_back(q_e); - if (chunk_e == chunk) { - if (q_b) { - t_e = q_b->getT(e.m_s->getChunk(chunk)->getPoint(t_e)); - q_b->split(t_e, *q_e, dummy); - } else - e.m_s->getChunk(0)->split(t_e, *q_e, dummy); - - if (!reversed) - quadArray.push_back(q_e); - else { - quadArray.push_back(new TQuadratic(q_e->getP2(), q_e->getP1(), q_e->getP0())); - toBeDeleted.push_back(quadArray.back()); - } - return; - } - e.m_s->getChunk(chunk_e)->split(t_e, *q_e, dummy); - chunk_e--; - } - - int i; - assert(chunk_e >= chunk_b - 1); - - if (reversed) { - if (q_e) { - q_e->reverse(); - quadArray.push_back(q_e); - } - for (i = chunk_e; i >= chunk_b; i--) { - const TThickQuadratic *qAux = e.m_s->getChunk(i); - quadArray.push_back(new TQuadratic(qAux->getP2(), qAux->getP1(), qAux->getP0())); - toBeDeleted.push_back(quadArray.back()); - } - - if (q_b) { - q_b->reverse(); - quadArray.push_back(q_b); - } - } else { - if (q_b) - quadArray.push_back(q_b); - for (i = chunk_b; i <= chunk_e; i++) - quadArray.push_back((TQuadratic *)e.m_s->getChunk(i)); - if (q_e) - quadArray.push_back(q_e); - } +void computeQuadChain(const TEdge &e, std::vector &quadArray, + std::vector &toBeDeleted) { + int chunk_b, chunk_e, chunk = -1; + double t_b, t_e, w0, w1; + TThickQuadratic *q_b = 0, *q_e = 0; + TThickQuadratic dummy; + bool reversed = false; + + if (e.m_w0 > e.m_w1) { + reversed = true; + w0 = e.m_w1; + w1 = e.m_w0; + } else { + w0 = e.m_w0; + w1 = e.m_w1; + } + + if (w0 == 0.0) + chunk_b = 0; + else { + if (e.m_s->getChunkAndT(w0, chunk, t_b)) assert(false); + q_b = new TThickQuadratic(); + toBeDeleted.push_back(q_b); + e.m_s->getChunk(chunk)->split(t_b, dummy, *q_b); + chunk_b = chunk + 1; + } + + if (w1 == 1.0) + chunk_e = e.m_s->getChunkCount() - 1; + else { + if (e.m_s->getChunkAndT(w1, chunk_e, t_e)) assert(false); + q_e = new TThickQuadratic(); + toBeDeleted.push_back(q_e); + if (chunk_e == chunk) { + if (q_b) { + t_e = q_b->getT(e.m_s->getChunk(chunk)->getPoint(t_e)); + q_b->split(t_e, *q_e, dummy); + } else + e.m_s->getChunk(0)->split(t_e, *q_e, dummy); + + if (!reversed) + quadArray.push_back(q_e); + else { + quadArray.push_back( + new TQuadratic(q_e->getP2(), q_e->getP1(), q_e->getP0())); + toBeDeleted.push_back(quadArray.back()); + } + return; + } + e.m_s->getChunk(chunk_e)->split(t_e, *q_e, dummy); + chunk_e--; + } + + int i; + assert(chunk_e >= chunk_b - 1); + + if (reversed) { + if (q_e) { + q_e->reverse(); + quadArray.push_back(q_e); + } + for (i = chunk_e; i >= chunk_b; i--) { + const TThickQuadratic *qAux = e.m_s->getChunk(i); + quadArray.push_back( + new TQuadratic(qAux->getP2(), qAux->getP1(), qAux->getP0())); + toBeDeleted.push_back(quadArray.back()); + } + + if (q_b) { + q_b->reverse(); + quadArray.push_back(q_b); + } + } else { + if (q_b) quadArray.push_back(q_b); + for (i = chunk_b; i <= chunk_e; i++) + quadArray.push_back((TQuadratic *)e.m_s->getChunk(i)); + if (q_e) quadArray.push_back(q_e); + } } //------------------------------------------------------------------- - - diff --git a/toonz/sources/common/tvrender/tfont_mac.cpp b/toonz/sources/common/tvrender/tfont_mac.cpp index 13fda58..d260058 100644 --- a/toonz/sources/common/tvrender/tfont_mac.cpp +++ b/toonz/sources/common/tvrender/tfont_mac.cpp @@ -15,520 +15,521 @@ using namespace std; -//----------------------------------------- structures ------------------------------------------------------------------- +//----------------------------------------- structures +//------------------------------------------------------------------- typedef struct { - Float32Point origin; // The origin of the current glyph - Boolean first; // Keeps track of which segment is first in a glyph - Float32Point current; // The current pen position (used to filter degenerate cases) + Float32Point origin; // The origin of the current glyph + Boolean first; // Keeps track of which segment is first in a glyph + Float32Point + current; // The current pen position (used to filter degenerate cases) - float adv; - TVectorImageP m_image; - std::vector m_points; + float adv; + TVectorImageP m_image; + std::vector m_points; } MyCurveCallbackData; typedef struct { - ATSGlyphRef glyphID; // The glyphID. This is simply an index into a table in the font. - Float32Point relativeOrigin; // The origin of this glyph -- relative to the origin of the line. + ATSGlyphRef glyphID; // The glyphID. This is simply an index into a table in + // the font. + Float32Point relativeOrigin; // The origin of this glyph -- relative to the + // origin of the line. } MyGlyphRecord; -//----------------------------------------- callback--------------------------------------------------------------------- +//----------------------------------------- +//callback--------------------------------------------------------------------- -OSStatus MyQuadraticLineProc(const Float32Point *pt1, const Float32Point *pt2, void *callBackDataPtr) -{ - /* - // Adjust the points according to the glyph origin - float x1 = ((MyCurveCallbackData *)callBackDataPtr)->origin.x + pt1->x; - float y1 = ((MyCurveCallbackData *)callBackDataPtr)->origin.y + pt1->y; - float x2 = ((MyCurveCallbackData *)callBackDataPtr)->origin.x + pt2->x; - float y2 = ((MyCurveCallbackData *)callBackDataPtr)->origin.y + pt2->y; - */ +OSStatus MyQuadraticLineProc(const Float32Point *pt1, const Float32Point *pt2, + void *callBackDataPtr) { + /* +// Adjust the points according to the glyph origin +float x1 = ((MyCurveCallbackData *)callBackDataPtr)->origin.x + pt1->x; +float y1 = ((MyCurveCallbackData *)callBackDataPtr)->origin.y + pt1->y; +float x2 = ((MyCurveCallbackData *)callBackDataPtr)->origin.x + pt2->x; +float y2 = ((MyCurveCallbackData *)callBackDataPtr)->origin.y + pt2->y; +*/ - MyCurveCallbackData *data = (MyCurveCallbackData *)callBackDataPtr; + MyCurveCallbackData *data = (MyCurveCallbackData *)callBackDataPtr; - if (data->m_points.empty()) - data->m_points.push_back(TThickPoint(pt1->x, pt1->y, 0)); - //else - //assert(isAlmostEqual(pt1 e back) + if (data->m_points.empty()) + data->m_points.push_back(TThickPoint(pt1->x, pt1->y, 0)); + // else + // assert(isAlmostEqual(pt1 e back) - TThickPoint lastPoint = TThickPoint(pt2->x, pt2->y, 0); - data->m_points.push_back((data->m_points.back() + lastPoint) * 0.5); - data->m_points.push_back(lastPoint); + TThickPoint lastPoint = TThickPoint(pt2->x, pt2->y, 0); + data->m_points.push_back((data->m_points.back() + lastPoint) * 0.5); + data->m_points.push_back(lastPoint); - return noErr; + return noErr; } -OSStatus MyQuadraticCurveProc(const Float32Point *pt1, const Float32Point *controlPt, const Float32Point *pt2, void *callBackDataPtr) -{ - /* - // Adjust the points according to the glyph origin - float x1 = ((MyCurveCallbackData *)callBackDataPtr)->origin.x + pt1->x; - float y1 = ((MyCurveCallbackData *)callBackDataPtr)->origin.y + pt1->y; - float x2 = ((MyCurveCallbackData *)callBackDataPtr)->origin.x + pt2->x; - float y2 = ((MyCurveCallbackData *)callBackDataPtr)->origin.y + pt2->y; - float cpx = ((MyCurveCallbackData *)callBackDataPtr)->origin.x + controlPt->x; - float cpy = ((MyCurveCallbackData *)callBackDataPtr)->origin.y + controlPt->y; - */ - MyCurveCallbackData *data = (MyCurveCallbackData *)callBackDataPtr; - - if (data->m_points.empty()) - data->m_points.push_back(TThickPoint(pt1->x, pt1->y, 0)); - //else - //assert(isAlmostEqual(pt1 e back) - - data->m_points.push_back(TThickPoint(controlPt->x, controlPt->y, 0)); - data->m_points.push_back(TThickPoint(pt2->x, pt2->y, 0)); - - return noErr; +OSStatus MyQuadraticCurveProc(const Float32Point *pt1, + const Float32Point *controlPt, + const Float32Point *pt2, void *callBackDataPtr) { + /* +// Adjust the points according to the glyph origin +float x1 = ((MyCurveCallbackData *)callBackDataPtr)->origin.x + pt1->x; +float y1 = ((MyCurveCallbackData *)callBackDataPtr)->origin.y + pt1->y; +float x2 = ((MyCurveCallbackData *)callBackDataPtr)->origin.x + pt2->x; +float y2 = ((MyCurveCallbackData *)callBackDataPtr)->origin.y + pt2->y; +float cpx = ((MyCurveCallbackData *)callBackDataPtr)->origin.x + controlPt->x; +float cpy = ((MyCurveCallbackData *)callBackDataPtr)->origin.y + controlPt->y; +*/ + MyCurveCallbackData *data = (MyCurveCallbackData *)callBackDataPtr; + + if (data->m_points.empty()) + data->m_points.push_back(TThickPoint(pt1->x, pt1->y, 0)); + // else + // assert(isAlmostEqual(pt1 e back) + + data->m_points.push_back(TThickPoint(controlPt->x, controlPt->y, 0)); + data->m_points.push_back(TThickPoint(pt2->x, pt2->y, 0)); + + return noErr; } -OSStatus MyQuadraticNewPathProc(void *callBackDataPtr) -{ - assert(((MyCurveCallbackData *)callBackDataPtr)->m_points.empty()); - return noErr; +OSStatus MyQuadraticNewPathProc(void *callBackDataPtr) { + assert(((MyCurveCallbackData *)callBackDataPtr)->m_points.empty()); + return noErr; } -OSStatus MyQuadraticClosePathProc(void *callBackDataPtr) -{ - MyCurveCallbackData *data = (MyCurveCallbackData *)callBackDataPtr; +OSStatus MyQuadraticClosePathProc(void *callBackDataPtr) { + MyCurveCallbackData *data = (MyCurveCallbackData *)callBackDataPtr; - assert(data->m_points.size() >= 3 && data->m_points.size() & 1); //il numero di punti di controllo devono essere dispari e >= 3 + assert( + data->m_points.size() >= 3 && + data->m_points.size() & + 1); // il numero di punti di controllo devono essere dispari e >= 3 - TStroke *stroke = new TStroke(data->m_points); - stroke->setSelfLoop(true); + TStroke *stroke = new TStroke(data->m_points); + stroke->setSelfLoop(true); - data->m_points.clear(); - data->m_image->addStroke(stroke); + data->m_points.clear(); + data->m_image->addStroke(stroke); - return noErr; + return noErr; } //------------------------------------------------------------------------------------------------------------------ -void GetGlyphIDsAndPositions(ATSUTextLayout iLayout, UniCharArrayOffset iStart, UniCharCount iLength, MyGlyphRecord **oGlyphRecordArray, ItemCount *oNumGlyphs) -{ - // This block of code uses the new Direct Access APIs, which are only available on Mac OS X 10.2 and later systems - // - - ATSLayoutRecord *layoutRecords; - ItemCount numRecords; - Fixed *deltaYs; - ItemCount numDeltaYs; - unsigned int i; - OSStatus status; - - // Get the arrays of glyph information - status = ATSUDirectGetLayoutDataArrayPtrFromTextLayout( - iLayout, iStart, - kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, - (void **)&layoutRecords, &numRecords); - assert(status == noErr); - - status = ATSUDirectGetLayoutDataArrayPtrFromTextLayout( - iLayout, iStart, - kATSUDirectDataBaselineDeltaFixedArray, - (void **)&deltaYs, &numDeltaYs); - assert(status == noErr); - - // Build the array of MyGlyphRecords - *oGlyphRecordArray = (MyGlyphRecord *)malloc(numRecords * sizeof(MyGlyphRecord)); - *oNumGlyphs = numRecords; - - for (i = 0; i < *oNumGlyphs; i++) { - // Fill in the glyphID - (*oGlyphRecordArray)[i].glyphID = layoutRecords[i].glyphID; - - // Set up the relative origin of the glyph - // - // The real position is the x coordinate of the glyph, relative to the beginning of the line - // The baseline delta (deltaY), if any, is the y coordinate of the glyph, relative to the baseline - // - (*oGlyphRecordArray)[i].relativeOrigin.x = Fix2X(layoutRecords[i].realPos); - - if (deltaYs == NULL) { - (*oGlyphRecordArray)[i].relativeOrigin.y = 0.0; - } else { - (*oGlyphRecordArray)[i].relativeOrigin.y = 0.0 - Fix2X(deltaYs[i]); - } - } - - // Free the arrays of glyph information - if (deltaYs != NULL) { - status = ATSUDirectReleaseLayoutDataArrayPtr(NULL, kATSUDirectDataBaselineDeltaFixedArray, (void **)&deltaYs); - assert(status == noErr); - } - status = ATSUDirectReleaseLayoutDataArrayPtr(NULL, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, (void **)&layoutRecords); - assert(status == noErr); -} - -void drawQuadratics(ATSUTextLayout iLayout, ATSUStyle iStyle, UniCharArrayOffset start, UniCharCount length, MyCurveCallbackData &data) -{ - //boh ---------------- - Fixed penX = 0; - Fixed penY = 0; - // ------------------- - - MyGlyphRecord *glyphRecordArray; - ItemCount numGlyphs; - ATSQuadraticNewPathUPP newPathProc; - ATSQuadraticLineUPP lineProc; - ATSQuadraticCurveUPP curveProc; - ATSQuadraticClosePathUPP closePathProc; - - OSStatus status; - unsigned int i; - - // Create the Quadratic callbacks - newPathProc = NewATSQuadraticNewPathUPP(MyQuadraticNewPathProc); - lineProc = NewATSQuadraticLineUPP(MyQuadraticLineProc); - curveProc = NewATSQuadraticCurveUPP(MyQuadraticCurveProc); - closePathProc = NewATSQuadraticClosePathUPP(MyQuadraticClosePathProc); - - // Get the array of glyph information - GetGlyphIDsAndPositions(iLayout, start, length, &glyphRecordArray, &numGlyphs); - - // Loop over all the glyphs - for (i = 0; i < numGlyphs; i++) { - - // Set up the absolute origin of the glyph - data.origin.x = Fix2X(penX) + glyphRecordArray[i].relativeOrigin.x; - data.origin.y = Fix2X(penY) + glyphRecordArray[i].relativeOrigin.y; - - // Reset state for quadratic drawing (the callbacks only do a MoveTo on the very first segment) - data.first = true; - - // If this is a deleted glyph (-1), don't draw it. Otherwise, go ahead. - if (glyphRecordArray[i].glyphID != kATSDeletedGlyphcode) { - status = ATSUGlyphGetQuadraticPaths(iStyle, glyphRecordArray[i].glyphID, newPathProc, lineProc, curveProc, closePathProc, &data, &status); - assert(status == noErr); - } - } - // Free the array of glyph information - free(glyphRecordArray); - - // Dispose of the Quadratic callbacks - - DisposeATSQuadraticNewPathUPP(newPathProc); - DisposeATSQuadraticLineUPP(lineProc); - DisposeATSQuadraticCurveUPP(curveProc); - DisposeATSQuadraticClosePathUPP(closePathProc); +void GetGlyphIDsAndPositions(ATSUTextLayout iLayout, UniCharArrayOffset iStart, + UniCharCount iLength, + MyGlyphRecord **oGlyphRecordArray, + ItemCount *oNumGlyphs) { + // This block of code uses the new Direct Access APIs, which are only + // available on Mac OS X 10.2 and later systems + // + + ATSLayoutRecord *layoutRecords; + ItemCount numRecords; + Fixed *deltaYs; + ItemCount numDeltaYs; + unsigned int i; + OSStatus status; + + // Get the arrays of glyph information + status = ATSUDirectGetLayoutDataArrayPtrFromTextLayout( + iLayout, iStart, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, + (void **)&layoutRecords, &numRecords); + assert(status == noErr); + + status = ATSUDirectGetLayoutDataArrayPtrFromTextLayout( + iLayout, iStart, kATSUDirectDataBaselineDeltaFixedArray, + (void **)&deltaYs, &numDeltaYs); + assert(status == noErr); + + // Build the array of MyGlyphRecords + *oGlyphRecordArray = + (MyGlyphRecord *)malloc(numRecords * sizeof(MyGlyphRecord)); + *oNumGlyphs = numRecords; + + for (i = 0; i < *oNumGlyphs; i++) { + // Fill in the glyphID + (*oGlyphRecordArray)[i].glyphID = layoutRecords[i].glyphID; + + // Set up the relative origin of the glyph + // + // The real position is the x coordinate of the glyph, relative to the + // beginning of the line + // The baseline delta (deltaY), if any, is the y coordinate of the glyph, + // relative to the baseline + // + (*oGlyphRecordArray)[i].relativeOrigin.x = Fix2X(layoutRecords[i].realPos); + + if (deltaYs == NULL) { + (*oGlyphRecordArray)[i].relativeOrigin.y = 0.0; + } else { + (*oGlyphRecordArray)[i].relativeOrigin.y = 0.0 - Fix2X(deltaYs[i]); + } + } + + // Free the arrays of glyph information + if (deltaYs != NULL) { + status = ATSUDirectReleaseLayoutDataArrayPtr( + NULL, kATSUDirectDataBaselineDeltaFixedArray, (void **)&deltaYs); + assert(status == noErr); + } + status = ATSUDirectReleaseLayoutDataArrayPtr( + NULL, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, + (void **)&layoutRecords); + assert(status == noErr); +} + +void drawQuadratics(ATSUTextLayout iLayout, ATSUStyle iStyle, + UniCharArrayOffset start, UniCharCount length, + MyCurveCallbackData &data) { + // boh ---------------- + Fixed penX = 0; + Fixed penY = 0; + // ------------------- + + MyGlyphRecord *glyphRecordArray; + ItemCount numGlyphs; + ATSQuadraticNewPathUPP newPathProc; + ATSQuadraticLineUPP lineProc; + ATSQuadraticCurveUPP curveProc; + ATSQuadraticClosePathUPP closePathProc; + + OSStatus status; + unsigned int i; + + // Create the Quadratic callbacks + newPathProc = NewATSQuadraticNewPathUPP(MyQuadraticNewPathProc); + lineProc = NewATSQuadraticLineUPP(MyQuadraticLineProc); + curveProc = NewATSQuadraticCurveUPP(MyQuadraticCurveProc); + closePathProc = NewATSQuadraticClosePathUPP(MyQuadraticClosePathProc); + + // Get the array of glyph information + GetGlyphIDsAndPositions(iLayout, start, length, &glyphRecordArray, + &numGlyphs); + + // Loop over all the glyphs + for (i = 0; i < numGlyphs; i++) { + // Set up the absolute origin of the glyph + data.origin.x = Fix2X(penX) + glyphRecordArray[i].relativeOrigin.x; + data.origin.y = Fix2X(penY) + glyphRecordArray[i].relativeOrigin.y; + + // Reset state for quadratic drawing (the callbacks only do a MoveTo on the + // very first segment) + data.first = true; + + // If this is a deleted glyph (-1), don't draw it. Otherwise, go ahead. + if (glyphRecordArray[i].glyphID != kATSDeletedGlyphcode) { + status = ATSUGlyphGetQuadraticPaths(iStyle, glyphRecordArray[i].glyphID, + newPathProc, lineProc, curveProc, + closePathProc, &data, &status); + assert(status == noErr); + } + } + // Free the array of glyph information + free(glyphRecordArray); + + // Dispose of the Quadratic callbacks + + DisposeATSQuadraticNewPathUPP(newPathProc); + DisposeATSQuadraticLineUPP(lineProc); + DisposeATSQuadraticCurveUPP(curveProc); + DisposeATSQuadraticClosePathUPP(closePathProc); } //============================================================================= struct TFont::Impl { - bool m_hasKerning; - int m_hasVertical; + bool m_hasKerning; + int m_hasVertical; - // KerningPairs m_kerningPairs; + // KerningPairs m_kerningPairs; - ATSUStyle m_style; - ATSUFontID m_fontId; - ATSUTextLayout m_layout; - Fixed m_size; - int m_ascender; - int m_descender; + ATSUStyle m_style; + ATSUFontID m_fontId; + ATSUTextLayout m_layout; + Fixed m_size; + int m_ascender; + int m_descender; - Impl(ATSUFontID fontId, int size); - ~Impl(); + Impl(ATSUFontID fontId, int size); + ~Impl(); - //void getChar(); + // void getChar(); }; //----------------------------------------------------------------------------- -TFont::TFont(ATSUFontID fontId, int size) -{ - m_pimpl = new Impl(fontId, size); -} +TFont::TFont(ATSUFontID fontId, int size) { m_pimpl = new Impl(fontId, size); } //----------------------------------------------------------------------------- -TFont::~TFont() -{ - delete m_pimpl; -} +TFont::~TFont() { delete m_pimpl; } //----------------------------------------------------------------------------- TFont::Impl::Impl(ATSUFontID fontId, int size) - : m_fontId(fontId), m_size(Long2Fix(size)) -{ - OSStatus status; + : m_fontId(fontId), m_size(Long2Fix(size)) { + OSStatus status; - long response; - status = Gestalt(gestaltATSUFeatures, &response); - assert(response & gestaltATSUDirectAccess); + long response; + status = Gestalt(gestaltATSUFeatures, &response); + assert(response & gestaltATSUDirectAccess); - status = ATSUCreateStyle(&m_style); - assert(status == noErr); + status = ATSUCreateStyle(&m_style); + assert(status == noErr); - ATSUAttributeTag tags[2]; - ByteCount sizes[2]; - ATSUAttributeValuePtr values[2]; + ATSUAttributeTag tags[2]; + ByteCount sizes[2]; + ATSUAttributeValuePtr values[2]; - tags[0] = kATSUFontTag; - sizes[0] = sizeof(ATSUFontID); - values[0] = &fontId; + tags[0] = kATSUFontTag; + sizes[0] = sizeof(ATSUFontID); + values[0] = &fontId; - tags[1] = kATSUSizeTag; - sizes[1] = sizeof(Fixed); - values[1] = &m_size; + tags[1] = kATSUSizeTag; + sizes[1] = sizeof(Fixed); + values[1] = &m_size; - status = ATSUSetAttributes(m_style, 2, tags, sizes, values); - //assert(status==noErr); + status = ATSUSetAttributes(m_style, 2, tags, sizes, values); + // assert(status==noErr); - UniChar dummyStr[] = {'H', 'e', 'l', 'l', 'o'}; - UniCharCount length = sizeof(dummyStr) / sizeof(UniChar); + UniChar dummyStr[] = {'H', 'e', 'l', 'l', 'o'}; + UniCharCount length = sizeof(dummyStr) / sizeof(UniChar); - status = ATSUCreateTextLayoutWithTextPtr( - dummyStr, kATSUFromTextBeginning, kATSUToTextEnd, length, 1, - &length, &m_style, &m_layout); - //assert(status==noErr); + status = ATSUCreateTextLayoutWithTextPtr(dummyStr, kATSUFromTextBeginning, + kATSUToTextEnd, length, 1, &length, + &m_style, &m_layout); + // assert(status==noErr); - ATSTrapezoid glyphBounds; - status = ATSUGetGlyphBounds(m_layout, 0, 0, - kATSUFromTextBeginning, kATSUToTextEnd, kATSUseFractionalOrigins, - 1, &glyphBounds, NULL); + ATSTrapezoid glyphBounds; + status = + ATSUGetGlyphBounds(m_layout, 0, 0, kATSUFromTextBeginning, kATSUToTextEnd, + kATSUseFractionalOrigins, 1, &glyphBounds, NULL); - m_ascender = -FixedToInt(glyphBounds.upperLeft.y); - assert(m_ascender > 0); - m_descender = -FixedToInt(glyphBounds.lowerLeft.y); - assert(m_descender < 0); + m_ascender = -FixedToInt(glyphBounds.upperLeft.y); + assert(m_ascender > 0); + m_descender = -FixedToInt(glyphBounds.lowerLeft.y); + assert(m_descender < 0); } //----------------------------------------------------------------------------- -TFont::Impl::~Impl() -{ -} +TFont::Impl::~Impl() {} //----------------------------------------------------------------------------- -TPoint TFont::drawChar(TVectorImageP &image, wchar_t charcode, wchar_t nextCharCode) const -{ - OSStatus status; +TPoint TFont::drawChar(TVectorImageP &image, wchar_t charcode, + wchar_t nextCharCode) const { + OSStatus status; - UniChar subString[2]; - subString[0] = charcode; - subString[1] = 0 /*nextCharCode*/; - UniCharCount length = sizeof(subString) / sizeof(UniChar); + UniChar subString[2]; + subString[0] = charcode; + subString[1] = 0 /*nextCharCode*/; + UniCharCount length = sizeof(subString) / sizeof(UniChar); - status = ATSUCreateTextLayoutWithTextPtr(subString, kATSUFromTextBeginning, kATSUToTextEnd, - length, 1, - &length, &(m_pimpl->m_style), &(m_pimpl->m_layout)); - assert(status == noErr); + status = ATSUCreateTextLayoutWithTextPtr( + subString, kATSUFromTextBeginning, kATSUToTextEnd, length, 1, &length, + &(m_pimpl->m_style), &(m_pimpl->m_layout)); + assert(status == noErr); - MyCurveCallbackData data; - data.m_image = image; + MyCurveCallbackData data; + data.m_image = image; - drawQuadratics(m_pimpl->m_layout, m_pimpl->m_style, kATSUFromTextBeginning, kATSUToTextEnd, data); - image->transform(TScale(1, -1)); + drawQuadratics(m_pimpl->m_layout, m_pimpl->m_style, kATSUFromTextBeginning, + kATSUToTextEnd, data); + image->transform(TScale(1, -1)); - image->group(0, image->getStrokeCount()); + image->group(0, image->getStrokeCount()); - return getDistance(charcode, nextCharCode); + return getDistance(charcode, nextCharCode); } //----------------------------------------------------------------------------- -namespace -{ - -void appDrawChar(TRasterGR8P &outImage, TFont::Impl *pimpl, wchar_t charcode) -{ - OSStatus status; - UniChar subString[2]; - subString[0] = charcode; - subString[1] = 0; - UniCharCount length = sizeof(subString) / sizeof(UniChar); - - status = ATSUCreateTextLayoutWithTextPtr(subString, kATSUFromTextBeginning, kATSUToTextEnd, - length, 1, - &length, &(pimpl->m_style), &(pimpl->m_layout)); - assert(status == noErr); - - ATSTrapezoid glyphBounds; - status = ATSUGetGlyphBounds(pimpl->m_layout, 0, 0, - kATSUFromTextBeginning, kATSUToTextEnd, kATSUseFractionalOrigins, - 1, &glyphBounds, NULL); - - int height = FixedToInt(glyphBounds.lowerLeft.y) - FixedToInt(glyphBounds.upperLeft.y); - int width = tmax(FixedToInt(glyphBounds.lowerRight.x), FixedToInt(glyphBounds.upperRight.x)) - - tmin(FixedToInt(glyphBounds.lowerLeft.x), FixedToInt(glyphBounds.upperLeft.x)); - - outImage = TRasterGR8P(width, height); - TPixelGR8 bgp; - bgp.value = 255; - outImage->fill(bgp); - void *data = outImage->getRawData(); - - CGColorSpaceRef grayColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray); - CGContextRef gContext = CGBitmapContextCreate(data, width, height, 8, width, grayColorSpace, kCGImageAlphaNone); +namespace { + +void appDrawChar(TRasterGR8P &outImage, TFont::Impl *pimpl, wchar_t charcode) { + OSStatus status; + UniChar subString[2]; + subString[0] = charcode; + subString[1] = 0; + UniCharCount length = sizeof(subString) / sizeof(UniChar); + + status = ATSUCreateTextLayoutWithTextPtr( + subString, kATSUFromTextBeginning, kATSUToTextEnd, length, 1, &length, + &(pimpl->m_style), &(pimpl->m_layout)); + assert(status == noErr); + + ATSTrapezoid glyphBounds; + status = ATSUGetGlyphBounds(pimpl->m_layout, 0, 0, kATSUFromTextBeginning, + kATSUToTextEnd, kATSUseFractionalOrigins, 1, + &glyphBounds, NULL); + + int height = + FixedToInt(glyphBounds.lowerLeft.y) - FixedToInt(glyphBounds.upperLeft.y); + int width = tmax(FixedToInt(glyphBounds.lowerRight.x), + FixedToInt(glyphBounds.upperRight.x)) - + tmin(FixedToInt(glyphBounds.lowerLeft.x), + FixedToInt(glyphBounds.upperLeft.x)); + + outImage = TRasterGR8P(width, height); + TPixelGR8 bgp; + bgp.value = 255; + outImage->fill(bgp); + void *data = outImage->getRawData(); + + CGColorSpaceRef grayColorSpace = + CGColorSpaceCreateWithName(kCGColorSpaceGenericGray); + CGContextRef gContext = CGBitmapContextCreate( + data, width, height, 8, width, grayColorSpace, kCGImageAlphaNone); #if defined(DEBUG) || defined(_DEBUG) - int bpc = CGBitmapContextGetBitsPerComponent(gContext); - if (bpc != 8) - std::cout << "BitsPerComponent: " << bpc << std::endl; + int bpc = CGBitmapContextGetBitsPerComponent(gContext); + if (bpc != 8) std::cout << "BitsPerComponent: " << bpc << std::endl; - int bpp = CGBitmapContextGetBitsPerPixel(gContext); - if (bpp != 8) - std::cout << "BitsPerPixel: " << bpp << std::endl; + int bpp = CGBitmapContextGetBitsPerPixel(gContext); + if (bpp != 8) std::cout << "BitsPerPixel: " << bpp << std::endl; - int bytesPerRow = CGBitmapContextGetBytesPerRow(gContext); - int newWidth = CGBitmapContextGetWidth(gContext); - if (bytesPerRow != width || newWidth != width) - std::cout << "BytesPerRow: " << bytesPerRow - << " Old width= " << width - << " New width= " << newWidth << std::endl; + int bytesPerRow = CGBitmapContextGetBytesPerRow(gContext); + int newWidth = CGBitmapContextGetWidth(gContext); + if (bytesPerRow != width || newWidth != width) + std::cout << "BytesPerRow: " << bytesPerRow << " Old width= " << width + << " New width= " << newWidth << std::endl; - int newHeight = CGBitmapContextGetHeight(gContext); - if (newHeight != height) - std::cout << " Old height= " << height << " New height= " << newHeight << std::endl; + int newHeight = CGBitmapContextGetHeight(gContext); + if (newHeight != height) + std::cout << " Old height= " << height << " New height= " << newHeight + << std::endl; - assert(CGBitmapContextGetColorSpace(gContext) == grayColorSpace); + assert(CGBitmapContextGetColorSpace(gContext) == grayColorSpace); #endif - ATSUAttributeTag tags[1]; - ByteCount sizes[1]; - ATSUAttributeValuePtr values[1]; + ATSUAttributeTag tags[1]; + ByteCount sizes[1]; + ATSUAttributeValuePtr values[1]; - tags[0] = kATSUCGContextTag; - sizes[0] = sizeof(CGContextRef); - values[0] = &gContext; - status = ATSUSetLayoutControls(pimpl->m_layout, 1, tags, sizes, values); - assert(status == noErr); + tags[0] = kATSUCGContextTag; + sizes[0] = sizeof(CGContextRef); + values[0] = &gContext; + status = ATSUSetLayoutControls(pimpl->m_layout, 1, tags, sizes, values); + assert(status == noErr); - ATSUDrawText(pimpl->m_layout, kATSUFromTextBeginning, kATSUToTextEnd, 0, glyphBounds.lowerLeft.y); + ATSUDrawText(pimpl->m_layout, kATSUFromTextBeginning, kATSUToTextEnd, 0, + glyphBounds.lowerLeft.y); } } //----------------------------------------------------------------------------- -TPoint TFont::drawChar(TRasterGR8P &outImage, TPoint &unused, wchar_t charcode, wchar_t nextCharCode) const -{ - appDrawChar(outImage, m_pimpl, charcode); - outImage->yMirror(); - return getDistance(charcode, nextCharCode); +TPoint TFont::drawChar(TRasterGR8P &outImage, TPoint &unused, wchar_t charcode, + wchar_t nextCharCode) const { + appDrawChar(outImage, m_pimpl, charcode); + outImage->yMirror(); + return getDistance(charcode, nextCharCode); } //----------------------------------------------------------------------------- -TPoint TFont::drawChar(TRasterCM32P &outImage, TPoint &unused, int inkId, wchar_t charcode, wchar_t nextCharCode) const -{ - TRasterGR8P grayAppImage; - appDrawChar(grayAppImage, m_pimpl, charcode); - - int lx = grayAppImage->getLx(); - int ly = grayAppImage->getLy(); - - outImage = TRasterCM32P(lx, ly); - - assert(TPixelCM32::getMaxTone() == 255); - TPixelCM32 bgColor(0, 0, TPixelCM32::getMaxTone()); - grayAppImage->lock(); - outImage->lock(); - int ty = 0; - for (int gy = ly - 1; gy >= 0; --gy, ++ty) { - TPixelGR8 *srcPix = grayAppImage->pixels(gy); - TPixelCM32 *tarPix = outImage->pixels(ty); - for (int x = 0; x < lx; ++x) { - int tone = srcPix->value; - - if (tone == 255) - *tarPix = bgColor; - else - *tarPix = TPixelCM32(inkId, 0, tone); - - ++srcPix; - ++tarPix; - } - } - grayAppImage->unlock(); - outImage->unlock(); - - return getDistance(charcode, nextCharCode); +TPoint TFont::drawChar(TRasterCM32P &outImage, TPoint &unused, int inkId, + wchar_t charcode, wchar_t nextCharCode) const { + TRasterGR8P grayAppImage; + appDrawChar(grayAppImage, m_pimpl, charcode); + + int lx = grayAppImage->getLx(); + int ly = grayAppImage->getLy(); + + outImage = TRasterCM32P(lx, ly); + + assert(TPixelCM32::getMaxTone() == 255); + TPixelCM32 bgColor(0, 0, TPixelCM32::getMaxTone()); + grayAppImage->lock(); + outImage->lock(); + int ty = 0; + for (int gy = ly - 1; gy >= 0; --gy, ++ty) { + TPixelGR8 *srcPix = grayAppImage->pixels(gy); + TPixelCM32 *tarPix = outImage->pixels(ty); + for (int x = 0; x < lx; ++x) { + int tone = srcPix->value; + + if (tone == 255) + *tarPix = bgColor; + else + *tarPix = TPixelCM32(inkId, 0, tone); + + ++srcPix; + ++tarPix; + } + } + grayAppImage->unlock(); + outImage->unlock(); + + return getDistance(charcode, nextCharCode); } //----------------------------------------------------------------------------- -TPoint TFont::getDistance(wchar_t firstChar, wchar_t secondChar) const -{ - OSStatus status; - UniChar subString[2]; - subString[0] = firstChar; - subString[1] = secondChar; - UniCharCount length = sizeof(subString) / sizeof(UniChar); - - status = ATSUCreateTextLayoutWithTextPtr(subString, kATSUFromTextBeginning, kATSUToTextEnd, - length, 1, - &length, &(m_pimpl->m_style), &(m_pimpl->m_layout)); - assert(status == noErr); - - MyGlyphRecord *glyphRecordArray; - ItemCount numGlyphs; - - // Get the array of glyph information - GetGlyphIDsAndPositions(m_pimpl->m_layout, kATSUFromTextBeginning, kATSUToTextEnd, &glyphRecordArray, &numGlyphs); - - assert(numGlyphs >= 2); - - assert(glyphRecordArray[0].relativeOrigin.x == 0); - int advance = (int)(glyphRecordArray[1].relativeOrigin.x - glyphRecordArray[0].relativeOrigin.x); - if (advance == 0) { - subString[1] = 0; - status = ATSUCreateTextLayoutWithTextPtr(subString, kATSUFromTextBeginning, kATSUToTextEnd, - length, 1, - &length, &(m_pimpl->m_style), &(m_pimpl->m_layout)); - - GetGlyphIDsAndPositions(m_pimpl->m_layout, kATSUFromTextBeginning, kATSUToTextEnd, &glyphRecordArray, &numGlyphs); - advance = (int)(glyphRecordArray[1].relativeOrigin.x - glyphRecordArray[0].relativeOrigin.x); - } - return TPoint(advance, 0); +TPoint TFont::getDistance(wchar_t firstChar, wchar_t secondChar) const { + OSStatus status; + UniChar subString[2]; + subString[0] = firstChar; + subString[1] = secondChar; + UniCharCount length = sizeof(subString) / sizeof(UniChar); + + status = ATSUCreateTextLayoutWithTextPtr( + subString, kATSUFromTextBeginning, kATSUToTextEnd, length, 1, &length, + &(m_pimpl->m_style), &(m_pimpl->m_layout)); + assert(status == noErr); + + MyGlyphRecord *glyphRecordArray; + ItemCount numGlyphs; + + // Get the array of glyph information + GetGlyphIDsAndPositions(m_pimpl->m_layout, kATSUFromTextBeginning, + kATSUToTextEnd, &glyphRecordArray, &numGlyphs); + + assert(numGlyphs >= 2); + + assert(glyphRecordArray[0].relativeOrigin.x == 0); + int advance = (int)(glyphRecordArray[1].relativeOrigin.x - + glyphRecordArray[0].relativeOrigin.x); + if (advance == 0) { + subString[1] = 0; + status = ATSUCreateTextLayoutWithTextPtr( + subString, kATSUFromTextBeginning, kATSUToTextEnd, length, 1, &length, + &(m_pimpl->m_style), &(m_pimpl->m_layout)); + + GetGlyphIDsAndPositions(m_pimpl->m_layout, kATSUFromTextBeginning, + kATSUToTextEnd, &glyphRecordArray, &numGlyphs); + advance = (int)(glyphRecordArray[1].relativeOrigin.x - + glyphRecordArray[0].relativeOrigin.x); + } + return TPoint(advance, 0); } //----------------------------------------------------------------------------- -int TFont::getMaxHeight() const -{ - return m_pimpl->m_ascender - m_pimpl->m_descender; +int TFont::getMaxHeight() const { + return m_pimpl->m_ascender - m_pimpl->m_descender; } //----------------------------------------------------------------------------- -int TFont::getMaxWidth() const -{ - assert(!"not implemented yet"); - return 100; +int TFont::getMaxWidth() const { + assert(!"not implemented yet"); + return 100; } //----------------------------------------------------------------------------- -int TFont::getLineAscender() const -{ - return m_pimpl->m_ascender; -} +int TFont::getLineAscender() const { return m_pimpl->m_ascender; } //----------------------------------------------------------------------------- -int TFont::getLineDescender() const -{ - return m_pimpl->m_descender; -} +int TFont::getLineDescender() const { return m_pimpl->m_descender; } //----------------------------------------------------------------------------- -bool TFont::hasKerning() const -{ - return true; -} +bool TFont::hasKerning() const { return true; } //----------------------------------------------------------------------------- -bool TFont::hasVertical() const -{ - return false; -} +bool TFont::hasVertical() const { return false; } //----------------------------------------------------------------------------- @@ -540,307 +541,256 @@ typedef std::map FontFamily; typedef std::map FamilyMap; struct TFontManager::Impl { - FamilyMap m_families; - bool m_loaded; - ATSUFontID m_currentAtsuFontId; - TFont *m_currentFont; - wstring m_currentFamily; - wstring m_currentTypeface; - int m_size; - - Impl() - : m_currentAtsuFontId(0), m_currentFont(0), m_loaded(false), m_size(70) - { - } - - bool setFontName(ATSUFontID fontId, int platform, int script, int lang); - bool addFont(ATSUFontID); - void loadFontNames(); - bool setFont(std::wstring family, std::wstring style); + FamilyMap m_families; + bool m_loaded; + ATSUFontID m_currentAtsuFontId; + TFont *m_currentFont; + wstring m_currentFamily; + wstring m_currentTypeface; + int m_size; + + Impl() + : m_currentAtsuFontId(0), m_currentFont(0), m_loaded(false), m_size(70) {} + + bool setFontName(ATSUFontID fontId, int platform, int script, int lang); + bool addFont(ATSUFontID); + void loadFontNames(); + bool setFont(std::wstring family, std::wstring style); }; using namespace std; -bool TFontManager::Impl::setFontName(ATSUFontID fontId, int platform, int script, int lang) -{ - ByteCount oActualNameLength; - ItemCount oFontCount; - OSStatus status; - - char *buffer = 0; - char *buffer2 = 0; - - // chiedo la lunhezza del Full Family Name per allocare il buffer - status = ATSUFindFontName(fontId, - kFontFullName, - platform, - script, - lang, - 0, 0, - &oActualNameLength, - 0); - - if (status != noErr || oActualNameLength <= 1) - return false; - - buffer = new char[oActualNameLength + 1]; - // chiedo il Full Family Name - status = ATSUFindFontName(fontId, - kFontFullName, - platform, - script, - lang, - oActualNameLength, buffer, - &oActualNameLength, - &oFontCount); - - if (status != noErr || oActualNameLength <= 1 || buffer[0] == '\0') { - delete[] buffer; - return false; - } - buffer[oActualNameLength] = '\0'; - - //------------------- - - // chiedo la lunhezza del Typeface Name per allocare il buffer - status = ATSUFindFontName(fontId, - kFontStyleName, - platform, - script, - lang, - 0, 0, - &oActualNameLength, - 0); - - if (status != noErr || oActualNameLength <= 1) { - delete[] buffer; - return false; - } - buffer2 = new char[oActualNameLength + 1]; - - // chiedo il Typeface Name - status = ATSUFindFontName(fontId, - kFontStyleName, - platform, - script, - lang, - oActualNameLength, buffer2, - &oActualNameLength, - &oFontCount); - - if (status != noErr || oActualNameLength <= 1 || buffer2[0] == '\0') { - delete[] buffer; - delete[] buffer2; - return false; - } else - buffer2[oActualNameLength] = '\0'; - - string s_family(buffer); - FontFamily &family = m_families[s_family]; - family[string(buffer2)] = fontId; - delete[] buffer; - delete[] buffer2; - return true; -} +bool TFontManager::Impl::setFontName(ATSUFontID fontId, int platform, + int script, int lang) { + ByteCount oActualNameLength; + ItemCount oFontCount; + OSStatus status; + + char *buffer = 0; + char *buffer2 = 0; + + // chiedo la lunhezza del Full Family Name per allocare il buffer + status = ATSUFindFontName(fontId, kFontFullName, platform, script, lang, 0, 0, + &oActualNameLength, 0); + + if (status != noErr || oActualNameLength <= 1) return false; + + buffer = new char[oActualNameLength + 1]; + // chiedo il Full Family Name + status = ATSUFindFontName(fontId, kFontFullName, platform, script, lang, + oActualNameLength, buffer, &oActualNameLength, + &oFontCount); + + if (status != noErr || oActualNameLength <= 1 || buffer[0] == '\0') { + delete[] buffer; + return false; + } + buffer[oActualNameLength] = '\0'; + + //------------------- + + // chiedo la lunhezza del Typeface Name per allocare il buffer + status = ATSUFindFontName(fontId, kFontStyleName, platform, script, lang, 0, + 0, &oActualNameLength, 0); + + if (status != noErr || oActualNameLength <= 1) { + delete[] buffer; + return false; + } + buffer2 = new char[oActualNameLength + 1]; -bool TFontManager::Impl::addFont(ATSUFontID fontId) -{ - int platform, script, lang; - - // per ottimizzare, ciclo solo sui valori - // piu' comuni - for (lang = -1; lang <= 0; lang++) - for (platform = -1; platform <= 1; platform++) - for (script = -1; script <= 0; script++) - if (setFontName(fontId, platform, script, lang)) - return true; - - //poi li provo tutti - for (lang = -1; lang <= 139; lang++) - for (script = -1; script <= 32; script++) - for (platform = -1; platform <= 4; platform++) { - // escludo quelli nel tri-ciclo for precedente. - // Purtoppo si deve fare cosi: - // non si puo' fare partendo con indici piu' alti nei cicli for! - if (-1 <= lang && lang <= 0 && - -1 <= script && script <= 0 && - -1 <= platform && platform <= 1) - continue; - - if (setFontName(fontId, platform, script, lang)) - return true; - } - - return false; + // chiedo il Typeface Name + status = ATSUFindFontName(fontId, kFontStyleName, platform, script, lang, + oActualNameLength, buffer2, &oActualNameLength, + &oFontCount); + + if (status != noErr || oActualNameLength <= 1 || buffer2[0] == '\0') { + delete[] buffer; + delete[] buffer2; + return false; + } else + buffer2[oActualNameLength] = '\0'; + + string s_family(buffer); + FontFamily &family = m_families[s_family]; + family[string(buffer2)] = fontId; + delete[] buffer; + delete[] buffer2; + return true; } -void TFontManager::Impl::loadFontNames() -{ - if (m_loaded) - return; +bool TFontManager::Impl::addFont(ATSUFontID fontId) { + int platform, script, lang; + + // per ottimizzare, ciclo solo sui valori + // piu' comuni + for (lang = -1; lang <= 0; lang++) + for (platform = -1; platform <= 1; platform++) + for (script = -1; script <= 0; script++) + if (setFontName(fontId, platform, script, lang)) return true; - ItemCount oFontCount, fontCount; - ATSUFontCount(&oFontCount); - fontCount = oFontCount; - ATSUFontID *oFontIDs = new ATSUFontID[fontCount]; - ATSUGetFontIDs(oFontIDs, fontCount, &oFontCount); - assert(fontCount == oFontCount); + // poi li provo tutti + for (lang = -1; lang <= 139; lang++) + for (script = -1; script <= 32; script++) + for (platform = -1; platform <= 4; platform++) { + // escludo quelli nel tri-ciclo for precedente. + // Purtoppo si deve fare cosi: + // non si puo' fare partendo con indici piu' alti nei cicli for! + if (-1 <= lang && lang <= 0 && -1 <= script && script <= 0 && + -1 <= platform && platform <= 1) + continue; - for (unsigned int i = 0; i < fontCount; i++) - addFont(oFontIDs[i]); + if (setFontName(fontId, platform, script, lang)) return true; + } - delete[] oFontIDs; - m_loaded = true; + return false; } -bool TFontManager::Impl::setFont(std::wstring family, std::wstring typeface) -{ - if (family == m_currentFamily && (typeface == m_currentTypeface || typeface == L"")) - return false; +void TFontManager::Impl::loadFontNames() { + if (m_loaded) return; + + ItemCount oFontCount, fontCount; + ATSUFontCount(&oFontCount); + fontCount = oFontCount; + ATSUFontID *oFontIDs = new ATSUFontID[fontCount]; + ATSUGetFontIDs(oFontIDs, fontCount, &oFontCount); + assert(fontCount == oFontCount); + + for (unsigned int i = 0; i < fontCount; i++) addFont(oFontIDs[i]); - FamilyMap::iterator family_it = m_families.find(toString(family)); - if (family_it == m_families.end()) - throw TFontCreationError(); + delete[] oFontIDs; + m_loaded = true; +} - m_currentFamily = family; - FontFamily::iterator style_it; - if (typeface == L"") { - style_it = ((*family_it).second).find(toString(m_currentTypeface)); - if (style_it == (*family_it).second.end()) - style_it = ((*family_it).second).begin(); +bool TFontManager::Impl::setFont(std::wstring family, std::wstring typeface) { + if (family == m_currentFamily && + (typeface == m_currentTypeface || typeface == L"")) + return false; - typeface = toWideString(style_it->first); - } else - style_it = ((*family_it).second).find(toString(typeface)); + FamilyMap::iterator family_it = m_families.find(toString(family)); + if (family_it == m_families.end()) throw TFontCreationError(); - if (style_it == (*family_it).second.end()) - throw TFontCreationError(); + m_currentFamily = family; + FontFamily::iterator style_it; + if (typeface == L"") { + style_it = ((*family_it).second).find(toString(m_currentTypeface)); + if (style_it == (*family_it).second.end()) + style_it = ((*family_it).second).begin(); + + typeface = toWideString(style_it->first); + } else + style_it = ((*family_it).second).find(toString(typeface)); - m_currentTypeface = typeface; - m_currentAtsuFontId = (*style_it).second; - return true; + if (style_it == (*family_it).second.end()) throw TFontCreationError(); + + m_currentTypeface = typeface; + m_currentAtsuFontId = (*style_it).second; + return true; } //--------------------------------------------------------- -TFontManager::TFontManager() -{ - m_pimpl = new TFontManager::Impl(); -} +TFontManager::TFontManager() { m_pimpl = new TFontManager::Impl(); } //--------------------------------------------------------- -TFontManager::~TFontManager() -{ - delete m_pimpl; -} +TFontManager::~TFontManager() { delete m_pimpl; } //--------------------------------------------------------- -TFontManager *TFontManager::instance() -{ - static TFontManager theManager; - return &theManager; +TFontManager *TFontManager::instance() { + static TFontManager theManager; + return &theManager; } //--------------------------------------------------------- -void TFontManager::loadFontNames() -{ - m_pimpl->loadFontNames(); -} +void TFontManager::loadFontNames() { m_pimpl->loadFontNames(); } //--------------------------------------------------------- -void TFontManager::setFamily(const wstring family) -{ - bool changed = m_pimpl->setFont(family, L""); - if (changed) { - delete m_pimpl->m_currentFont; - m_pimpl->m_currentFont = new TFont(m_pimpl->m_currentAtsuFontId, m_pimpl->m_size); - } +void TFontManager::setFamily(const wstring family) { + bool changed = m_pimpl->setFont(family, L""); + if (changed) { + delete m_pimpl->m_currentFont; + m_pimpl->m_currentFont = + new TFont(m_pimpl->m_currentAtsuFontId, m_pimpl->m_size); + } } //--------------------------------------------------------- -void TFontManager::setTypeface(const wstring typeface) -{ - bool changed = m_pimpl->setFont(m_pimpl->m_currentFamily, typeface); - if (changed) { - delete m_pimpl->m_currentFont; - m_pimpl->m_currentFont = new TFont(m_pimpl->m_currentAtsuFontId, m_pimpl->m_size); - } +void TFontManager::setTypeface(const wstring typeface) { + bool changed = m_pimpl->setFont(m_pimpl->m_currentFamily, typeface); + if (changed) { + delete m_pimpl->m_currentFont; + m_pimpl->m_currentFont = + new TFont(m_pimpl->m_currentAtsuFontId, m_pimpl->m_size); + } } //--------------------------------------------------------- -void TFontManager::setSize(int size) -{ - if (m_pimpl->m_size != size) { - m_pimpl->m_size = size; - delete m_pimpl->m_currentFont; - m_pimpl->m_currentFont = new TFont(m_pimpl->m_currentAtsuFontId, m_pimpl->m_size); - } +void TFontManager::setSize(int size) { + if (m_pimpl->m_size != size) { + m_pimpl->m_size = size; + delete m_pimpl->m_currentFont; + m_pimpl->m_currentFont = + new TFont(m_pimpl->m_currentAtsuFontId, m_pimpl->m_size); + } } //--------------------------------------------------------- -wstring TFontManager::getCurrentFamily() const -{ - return m_pimpl->m_currentFamily; +wstring TFontManager::getCurrentFamily() const { + return m_pimpl->m_currentFamily; } //--------------------------------------------------------- -wstring TFontManager::getCurrentTypeface() const -{ - return m_pimpl->m_currentTypeface; +wstring TFontManager::getCurrentTypeface() const { + return m_pimpl->m_currentTypeface; } //--------------------------------------------------------- -TFont *TFontManager::getCurrentFont() -{ - if (m_pimpl->m_currentFont) - return m_pimpl->m_currentFont; +TFont *TFontManager::getCurrentFont() { + if (m_pimpl->m_currentFont) return m_pimpl->m_currentFont; - if (!m_pimpl->m_currentFont) - loadFontNames(); + if (!m_pimpl->m_currentFont) loadFontNames(); - assert(!m_pimpl->m_families.empty()); - setFamily(toWideString(m_pimpl->m_families.begin()->first)); + assert(!m_pimpl->m_families.empty()); + setFamily(toWideString(m_pimpl->m_families.begin()->first)); - return m_pimpl->m_currentFont; + return m_pimpl->m_currentFont; } //--------------------------------------------------------- -void TFontManager::getAllFamilies(vector &families) const -{ - families.clear(); - families.reserve(m_pimpl->m_families.size()); +void TFontManager::getAllFamilies(vector &families) const { + families.clear(); + families.reserve(m_pimpl->m_families.size()); - FamilyMap::iterator it = m_pimpl->m_families.begin(); - for (; it != m_pimpl->m_families.end(); ++it) { - families.push_back(toWideString(it->first)); - } + FamilyMap::iterator it = m_pimpl->m_families.begin(); + for (; it != m_pimpl->m_families.end(); ++it) { + families.push_back(toWideString(it->first)); + } } //--------------------------------------------------------- -void TFontManager::getAllTypefaces(vector &typefaces) const -{ - typefaces.clear(); - FamilyMap::iterator it_family = m_pimpl->m_families.find(toString(m_pimpl->m_currentFamily)); - if (it_family == m_pimpl->m_families.end()) - return; - FontFamily &typefaceSet = it_family->second; - - typefaces.reserve(typefaceSet.size()); - FontFamily::iterator it_typeface = typefaceSet.begin(); - for (; it_typeface != typefaceSet.end(); ++it_typeface) { - typefaces.push_back(toWideString(it_typeface->first)); - } +void TFontManager::getAllTypefaces(vector &typefaces) const { + typefaces.clear(); + FamilyMap::iterator it_family = + m_pimpl->m_families.find(toString(m_pimpl->m_currentFamily)); + if (it_family == m_pimpl->m_families.end()) return; + FontFamily &typefaceSet = it_family->second; + + typefaces.reserve(typefaceSet.size()); + FontFamily::iterator it_typeface = typefaceSet.begin(); + for (; it_typeface != typefaceSet.end(); ++it_typeface) { + typefaces.push_back(toWideString(it_typeface->first)); + } } //--------------------------------------------------------- diff --git a/toonz/sources/common/tvrender/tfont_nt.cpp b/toonz/sources/common/tvrender/tfont_nt.cpp index 649cf13..6098a49 100644 --- a/toonz/sources/common/tvrender/tfont_nt.cpp +++ b/toonz/sources/common/tvrender/tfont_nt.cpp @@ -26,415 +26,388 @@ typedef map, int> KerningPairs; //============================================================================= struct TFont::Impl { - - bool m_hasKerning; - bool m_hasVertical; - HFONT m_font; - HDC m_hdc; - TEXTMETRICW m_metrics; - KerningPairs m_kerningPairs; - - Impl(const LOGFONTW &font, HDC hdc); - ~Impl(); + bool m_hasKerning; + bool m_hasVertical; + HFONT m_font; + HDC m_hdc; + TEXTMETRICW m_metrics; + KerningPairs m_kerningPairs; + + Impl(const LOGFONTW &font, HDC hdc); + ~Impl(); }; //----------------------------------------------------------------------------- -TFont::TFont(const LOGFONTW &font, HDC hdc) -{ - m_pimpl = new Impl(font, hdc); -} +TFont::TFont(const LOGFONTW &font, HDC hdc) { m_pimpl = new Impl(font, hdc); } //----------------------------------------------------------------------------- -TFont::~TFont() -{ - delete m_pimpl; -} +TFont::~TFont() { delete m_pimpl; } //----------------------------------------------------------------------------- -TFont::Impl::Impl(const LOGFONTW &logfont, HDC hdc) - : m_hdc(hdc) -{ - m_font = CreateFontIndirectW(&logfont); - - if (!m_font) - throw TFontCreationError(); - - HGDIOBJ hObj = SelectObject(hdc, m_font); - if (!hObj || hObj == HGDI_ERROR) - throw TFontCreationError(); - - if (!GetTextMetricsW(hdc, &m_metrics)) - throw TFontCreationError(); - - DWORD pairsCount = GetKerningPairsW(hdc, 0, 0); - if (pairsCount) { - m_hasKerning = true; - std::unique_ptr tempKernPairs(new KERNINGPAIR[pairsCount]); - GetKerningPairsW(hdc, pairsCount, tempKernPairs.get()); - for (UINT i = 0; i < pairsCount; i++) { - pair key = make_pair(tempKernPairs[i].wFirst, tempKernPairs[i].wSecond); - m_kerningPairs[key] = tempKernPairs[i].iKernAmount; - } - } else - m_hasKerning = false; - - m_hasVertical = (logfont.lfFaceName)[0] == '@'; +TFont::Impl::Impl(const LOGFONTW &logfont, HDC hdc) : m_hdc(hdc) { + m_font = CreateFontIndirectW(&logfont); + + if (!m_font) throw TFontCreationError(); + + HGDIOBJ hObj = SelectObject(hdc, m_font); + if (!hObj || hObj == HGDI_ERROR) throw TFontCreationError(); + + if (!GetTextMetricsW(hdc, &m_metrics)) throw TFontCreationError(); + + DWORD pairsCount = GetKerningPairsW(hdc, 0, 0); + if (pairsCount) { + m_hasKerning = true; + std::unique_ptr tempKernPairs(new KERNINGPAIR[pairsCount]); + GetKerningPairsW(hdc, pairsCount, tempKernPairs.get()); + for (UINT i = 0; i < pairsCount; i++) { + pair key = + make_pair(tempKernPairs[i].wFirst, tempKernPairs[i].wSecond); + m_kerningPairs[key] = tempKernPairs[i].iKernAmount; + } + } else + m_hasKerning = false; + + m_hasVertical = (logfont.lfFaceName)[0] == '@'; } //----------------------------------------------------------------------------- -TFont::Impl::~Impl() -{ - //delete m_advances; - DeleteObject(m_font); +TFont::Impl::~Impl() { + // delete m_advances; + DeleteObject(m_font); } //----------------------------------------------------------------------------- -namespace -{ -inline TThickPoint toThickPoint(POINTFX point) -{ - double app1 = point.x.value + ((double)point.x.fract) / (std::numeric_limits::max)(); - double app2 = point.y.value + ((double)point.y.fract) / (std::numeric_limits::max)(); - return TThickPoint(app1, app2, 0); +namespace { +inline TThickPoint toThickPoint(POINTFX point) { + double app1 = point.x.value + + ((double)point.x.fract) / (std::numeric_limits::max)(); + double app2 = point.y.value + + ((double)point.y.fract) / (std::numeric_limits::max)(); + return TThickPoint(app1, app2, 0); } } //----------------------------------------------------------------------------- -TPoint TFont::drawChar(TVectorImageP &image, wchar_t charcode, wchar_t nextCharCode) const - +TPoint TFont::drawChar(TVectorImageP &image, wchar_t charcode, + wchar_t nextCharCode) const + { + GLYPHMETRICS gm; + MAT2 mat2; + mat2.eM11.fract = 0; + mat2.eM12.fract = 0; + mat2.eM21.fract = 0; + mat2.eM22.fract = 0; + mat2.eM11.value = 1; + mat2.eM12.value = 0; + mat2.eM21.value = 0; + mat2.eM22.value = 1; + + vector points; + + UINT j = 0; + + DWORD charMemorySize = + GetGlyphOutlineW(m_pimpl->m_hdc, charcode, GGO_NATIVE, &gm, 0, 0, &mat2); + if (charMemorySize == GDI_ERROR) { + assert(0); + return TPoint(); + } + + std::unique_ptr lpvBuffer(new char[charMemorySize]); + + charMemorySize = GetGlyphOutlineW(m_pimpl->m_hdc, charcode, GGO_NATIVE, &gm, + charMemorySize, lpvBuffer.get(), &mat2); + if (charMemorySize == GDI_ERROR) { + assert(0); + return TPoint(); + } - GLYPHMETRICS gm; - MAT2 mat2; - mat2.eM11.fract = 0; - mat2.eM12.fract = 0; - mat2.eM21.fract = 0; - mat2.eM22.fract = 0; - mat2.eM11.value = 1; - mat2.eM12.value = 0; - mat2.eM21.value = 0; - mat2.eM22.value = 1; - - vector points; - - UINT j = 0; - - DWORD charMemorySize = GetGlyphOutlineW(m_pimpl->m_hdc, charcode, GGO_NATIVE, &gm, 0, 0, &mat2); - if (charMemorySize == GDI_ERROR) { - assert(0); - return TPoint(); - } - - std::unique_ptr lpvBuffer(new char[charMemorySize]); - - charMemorySize = GetGlyphOutlineW(m_pimpl->m_hdc, charcode, GGO_NATIVE, &gm, charMemorySize, lpvBuffer.get(), &mat2); - if (charMemorySize == GDI_ERROR) { - assert(0); - return TPoint(); - } - - TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)lpvBuffer.get(); - - while ((char *)header < (char *)lpvBuffer.get() + charMemorySize) { - points.clear(); - TThickPoint startPoint = toThickPoint(header->pfxStart); - points.push_back(startPoint); - - if (header->dwType != TT_POLYGON_TYPE) { - assert(0); - } - int memorySize = header->cb; - - TTPOLYCURVE *curve = (TTPOLYCURVE *)(header + 1); - - while ((char *)curve < (char *)header + memorySize) { - switch (curve->wType) { - case TT_PRIM_LINE: - - for (j = 0; j < curve->cpfx; j++) { - TThickPoint p0 = points.back(); - TThickPoint p1 = toThickPoint(((*curve).apfx[j])); - points.push_back((p0 + p1) * 0.5); - points.push_back(p1); - } - - break; - - case TT_PRIM_QSPLINE: - - for (j = 0; (int)j + 2 < curve->cpfx; j++) { - TThickPoint p1 = toThickPoint(((*curve).apfx[j])); - TThickPoint p2 = toThickPoint(((*curve).apfx[j + 1])); - - points.push_back(p1); - points.push_back((p1 + p2) * 0.5); - } - points.push_back(toThickPoint(((*curve).apfx[j++]))); - points.push_back(toThickPoint(((*curve).apfx[j++]))); - - break; - case TT_PRIM_CSPLINE: - assert(0); - break; - default: - assert(0); - } - - curve = (TTPOLYCURVE *)(&(curve->apfx)[j]); - } - - TThickPoint p0 = points.back(); - if (!isAlmostZero(p0.x - startPoint.x) || !isAlmostZero(p0.y - startPoint.y)) { - points.push_back((p0 + startPoint) * 0.5); - points.push_back(startPoint); - } - - TStroke *stroke = new TStroke(); - stroke->reshape(&(points[0]), points.size()); - stroke->setSelfLoop(true); - image->addStroke(stroke); - - header = (TTPOLYGONHEADER *)curve; - } - - image->group(0, image->getStrokeCount()); - - return getDistance(charcode, nextCharCode); + TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)lpvBuffer.get(); + + while ((char *)header < (char *)lpvBuffer.get() + charMemorySize) { + points.clear(); + TThickPoint startPoint = toThickPoint(header->pfxStart); + points.push_back(startPoint); + + if (header->dwType != TT_POLYGON_TYPE) { + assert(0); + } + int memorySize = header->cb; + + TTPOLYCURVE *curve = (TTPOLYCURVE *)(header + 1); + + while ((char *)curve < (char *)header + memorySize) { + switch (curve->wType) { + case TT_PRIM_LINE: + + for (j = 0; j < curve->cpfx; j++) { + TThickPoint p0 = points.back(); + TThickPoint p1 = toThickPoint(((*curve).apfx[j])); + points.push_back((p0 + p1) * 0.5); + points.push_back(p1); + } + + break; + + case TT_PRIM_QSPLINE: + + for (j = 0; (int)j + 2 < curve->cpfx; j++) { + TThickPoint p1 = toThickPoint(((*curve).apfx[j])); + TThickPoint p2 = toThickPoint(((*curve).apfx[j + 1])); + + points.push_back(p1); + points.push_back((p1 + p2) * 0.5); + } + points.push_back(toThickPoint(((*curve).apfx[j++]))); + points.push_back(toThickPoint(((*curve).apfx[j++]))); + + break; + case TT_PRIM_CSPLINE: + assert(0); + break; + default: + assert(0); + } + + curve = (TTPOLYCURVE *)(&(curve->apfx)[j]); + } + + TThickPoint p0 = points.back(); + if (!isAlmostZero(p0.x - startPoint.x) || + !isAlmostZero(p0.y - startPoint.y)) { + points.push_back((p0 + startPoint) * 0.5); + points.push_back(startPoint); + } + + TStroke *stroke = new TStroke(); + stroke->reshape(&(points[0]), points.size()); + stroke->setSelfLoop(true); + image->addStroke(stroke); + + header = (TTPOLYGONHEADER *)curve; + } + + image->group(0, image->getStrokeCount()); + + return getDistance(charcode, nextCharCode); } //----------------------------------------------------------------------------- -namespace -{ +namespace { -TPoint appDrawChar(TRasterGR8P &outImage, HDC hdc, wchar_t charcode) -{ - GLYPHMETRICS gm; - MAT2 mat2; - mat2.eM11.fract = 0; - mat2.eM12.fract = 0; - mat2.eM21.fract = 0; - mat2.eM22.fract = 0; - mat2.eM11.value = 1; - mat2.eM12.value = 0; - mat2.eM21.value = 0; - mat2.eM22.value = 1; - - DWORD charMemorySize = GetGlyphOutlineW(hdc, charcode, GGO_GRAY8_BITMAP, &gm, 0, 0, &mat2); - - if (charMemorySize == GDI_ERROR) { - assert(0); - } - - int lx = gm.gmBlackBoxX; - int ly = gm.gmBlackBoxY; - - int wrap = ((lx + 3) >> 2) << 2; - - TRasterGR8P appImage = TRasterGR8P(wrap, ly); - appImage->clear(); - outImage = appImage->extract(0, 0, lx - 1, ly - 1); - outImage->lock(); - GetGlyphOutlineW(hdc, charcode, GGO_GRAY8_BITMAP, &gm, wrap * ly, outImage->getRawData(), &mat2); - outImage->unlock(); - TPoint glyphOrig; - glyphOrig.x = gm.gmptGlyphOrigin.x; - glyphOrig.y = gm.gmptGlyphOrigin.y; - return glyphOrig; +TPoint appDrawChar(TRasterGR8P &outImage, HDC hdc, wchar_t charcode) { + GLYPHMETRICS gm; + MAT2 mat2; + mat2.eM11.fract = 0; + mat2.eM12.fract = 0; + mat2.eM21.fract = 0; + mat2.eM22.fract = 0; + mat2.eM11.value = 1; + mat2.eM12.value = 0; + mat2.eM21.value = 0; + mat2.eM22.value = 1; + + DWORD charMemorySize = + GetGlyphOutlineW(hdc, charcode, GGO_GRAY8_BITMAP, &gm, 0, 0, &mat2); + + if (charMemorySize == GDI_ERROR) { + assert(0); + } + + int lx = gm.gmBlackBoxX; + int ly = gm.gmBlackBoxY; + + int wrap = ((lx + 3) >> 2) << 2; + + TRasterGR8P appImage = TRasterGR8P(wrap, ly); + appImage->clear(); + outImage = appImage->extract(0, 0, lx - 1, ly - 1); + outImage->lock(); + GetGlyphOutlineW(hdc, charcode, GGO_GRAY8_BITMAP, &gm, wrap * ly, + outImage->getRawData(), &mat2); + outImage->unlock(); + TPoint glyphOrig; + glyphOrig.x = gm.gmptGlyphOrigin.x; + glyphOrig.y = gm.gmptGlyphOrigin.y; + return glyphOrig; } } //----------------------------------------------------------------------------- -//valori compresi tra 0 e 64 (si si, proprio 64 e non 63: sono 65 valori) - -TPoint TFont::drawChar(TRasterGR8P &outImage, TPoint &glyphOrigin, wchar_t charcode, wchar_t nextCharCode) const -{ - TRasterGR8P grayAppImage; - - TPoint glyphOrig = appDrawChar(grayAppImage, m_pimpl->m_hdc, charcode); - - if (glyphOrig.x < 0) { - glyphOrigin.x = glyphOrig.x; - glyphOrig.x = 0; - } else - glyphOrigin.x = 0; - - if (glyphOrig.y < 0) { - glyphOrigin.y = glyphOrig.y; - glyphOrig.y = 0; - } else - glyphOrigin.y = 0; - - int srcLx = grayAppImage->getLx(); - int srcLy = grayAppImage->getLy(); - - int dstLx = srcLx + glyphOrig.x; - int dstLy = getMaxHeight(); - - outImage = TRasterGR8P(dstLx, dstLy); - outImage->clear(); - - int ty = m_pimpl->m_metrics.tmDescent - 1 + glyphOrig.y; - assert(ty < dstLy); - assert(ty >= srcLy - 1); - grayAppImage->lock(); - outImage->lock(); - - for (int sy = 0; sy < srcLy; ++sy, --ty) { - TPixelGR8 *srcPix = grayAppImage->pixels(sy); - TPixelGR8 *tarPix = outImage->pixels(ty) + glyphOrig.x; - for (int x = 0; x < srcLx; ++x) { - assert(srcPix->value < 65); - - switch (srcPix->value) { - case 0: - tarPix->value = 0; - break; - default: - tarPix->value = (srcPix->value << 2) - 1; - break; - } - ++srcPix; - ++tarPix; - } - } - grayAppImage->unlock(); - outImage->unlock(); - - return getDistance(charcode, nextCharCode); +// valori compresi tra 0 e 64 (si si, proprio 64 e non 63: sono 65 valori) + +TPoint TFont::drawChar(TRasterGR8P &outImage, TPoint &glyphOrigin, + wchar_t charcode, wchar_t nextCharCode) const { + TRasterGR8P grayAppImage; + + TPoint glyphOrig = appDrawChar(grayAppImage, m_pimpl->m_hdc, charcode); + + if (glyphOrig.x < 0) { + glyphOrigin.x = glyphOrig.x; + glyphOrig.x = 0; + } else + glyphOrigin.x = 0; + + if (glyphOrig.y < 0) { + glyphOrigin.y = glyphOrig.y; + glyphOrig.y = 0; + } else + glyphOrigin.y = 0; + + int srcLx = grayAppImage->getLx(); + int srcLy = grayAppImage->getLy(); + + int dstLx = srcLx + glyphOrig.x; + int dstLy = getMaxHeight(); + + outImage = TRasterGR8P(dstLx, dstLy); + outImage->clear(); + + int ty = m_pimpl->m_metrics.tmDescent - 1 + glyphOrig.y; + assert(ty < dstLy); + assert(ty >= srcLy - 1); + grayAppImage->lock(); + outImage->lock(); + + for (int sy = 0; sy < srcLy; ++sy, --ty) { + TPixelGR8 *srcPix = grayAppImage->pixels(sy); + TPixelGR8 *tarPix = outImage->pixels(ty) + glyphOrig.x; + for (int x = 0; x < srcLx; ++x) { + assert(srcPix->value < 65); + + switch (srcPix->value) { + case 0: + tarPix->value = 0; + break; + default: + tarPix->value = (srcPix->value << 2) - 1; + break; + } + ++srcPix; + ++tarPix; + } + } + grayAppImage->unlock(); + outImage->unlock(); + + return getDistance(charcode, nextCharCode); } //----------------------------------------------------------------------------- -TPoint TFont::drawChar(TRasterCM32P &outImage, TPoint &glyphOrigin, int inkId, wchar_t charcode, wchar_t nextCharCode) const -{ - TRasterGR8P grayAppImage; - TPoint glyphOrig = appDrawChar(grayAppImage, m_pimpl->m_hdc, charcode); - - if (glyphOrig.x < 0) { - glyphOrigin.x = glyphOrig.x; - glyphOrig.x = 0; - } else - glyphOrigin.x = 0; - - if (glyphOrig.y < 0) { - glyphOrigin.y = glyphOrig.y; - glyphOrig.y = 0; - } else - glyphOrigin.y = 0; - - int srcLx = grayAppImage->getLx(); - int srcLy = grayAppImage->getLy(); - - int dstLx = srcLx + glyphOrig.x; - int dstLy = getMaxHeight(); - - outImage = TRasterCM32P(dstLx, dstLy); - outImage->clear(); - - assert(TPixelCM32::getMaxTone() == 255); - // TPixelCM32 bgColor(BackgroundStyle,BackgroundStyle,TPixelCM32::getMaxTone()); - TPixelCM32 bgColor; - - int ty = m_pimpl->m_metrics.tmDescent - 1 + glyphOrig.y; - assert(ty < dstLy); - assert(ty >= srcLy - 1); - grayAppImage->lock(); - outImage->lock(); - - for (int sy = 0; sy < srcLy; ++sy, --ty) { - TPixelGR8 *srcPix = grayAppImage->pixels(sy); - TPixelCM32 *tarPix = outImage->pixels(ty) + glyphOrig.x; - for (int x = 0; x < srcLx; ++x) { - int tone = 256 - (srcPix->value << 2); - - // grayScale ToonzImage tone Meaning - // 0 255 Bg = PurePaint - // 1 252 - // ... - // 63 4 - // 64 0 Fg = Pure Ink - - if (tone < 0) - tone = 0; - - if (tone >= 255) - *tarPix = bgColor; - else - *tarPix = TPixelCM32(inkId, 0, tone); // BackgroundStyle,tone); - - ++srcPix; - ++tarPix; - } - } - grayAppImage->unlock(); - outImage->unlock(); - - return getDistance(charcode, nextCharCode); +TPoint TFont::drawChar(TRasterCM32P &outImage, TPoint &glyphOrigin, int inkId, + wchar_t charcode, wchar_t nextCharCode) const { + TRasterGR8P grayAppImage; + TPoint glyphOrig = appDrawChar(grayAppImage, m_pimpl->m_hdc, charcode); + + if (glyphOrig.x < 0) { + glyphOrigin.x = glyphOrig.x; + glyphOrig.x = 0; + } else + glyphOrigin.x = 0; + + if (glyphOrig.y < 0) { + glyphOrigin.y = glyphOrig.y; + glyphOrig.y = 0; + } else + glyphOrigin.y = 0; + + int srcLx = grayAppImage->getLx(); + int srcLy = grayAppImage->getLy(); + + int dstLx = srcLx + glyphOrig.x; + int dstLy = getMaxHeight(); + + outImage = TRasterCM32P(dstLx, dstLy); + outImage->clear(); + + assert(TPixelCM32::getMaxTone() == 255); + // TPixelCM32 + // bgColor(BackgroundStyle,BackgroundStyle,TPixelCM32::getMaxTone()); + TPixelCM32 bgColor; + + int ty = m_pimpl->m_metrics.tmDescent - 1 + glyphOrig.y; + assert(ty < dstLy); + assert(ty >= srcLy - 1); + grayAppImage->lock(); + outImage->lock(); + + for (int sy = 0; sy < srcLy; ++sy, --ty) { + TPixelGR8 *srcPix = grayAppImage->pixels(sy); + TPixelCM32 *tarPix = outImage->pixels(ty) + glyphOrig.x; + for (int x = 0; x < srcLx; ++x) { + int tone = 256 - (srcPix->value << 2); + + // grayScale ToonzImage tone Meaning + // 0 255 Bg = PurePaint + // 1 252 + // ... + // 63 4 + // 64 0 Fg = Pure Ink + + if (tone < 0) tone = 0; + + if (tone >= 255) + *tarPix = bgColor; + else + *tarPix = TPixelCM32(inkId, 0, tone); // BackgroundStyle,tone); + + ++srcPix; + ++tarPix; + } + } + grayAppImage->unlock(); + outImage->unlock(); + + return getDistance(charcode, nextCharCode); } //----------------------------------------------------------------------------- -TPoint TFont::getDistance(wchar_t firstChar, wchar_t secondChar) const -{ - int advance; - BOOL result = GetCharWidth32W(m_pimpl->m_hdc, firstChar, firstChar, &advance); - assert(result); - if (m_pimpl->m_hasKerning && secondChar) { - KerningPairs::iterator it = m_pimpl->m_kerningPairs.find(make_pair(firstChar, secondChar)); - if (it != m_pimpl->m_kerningPairs.end()) { - advance += it->second; - } - } - return TPoint(advance, 0); +TPoint TFont::getDistance(wchar_t firstChar, wchar_t secondChar) const { + int advance; + BOOL result = GetCharWidth32W(m_pimpl->m_hdc, firstChar, firstChar, &advance); + assert(result); + if (m_pimpl->m_hasKerning && secondChar) { + KerningPairs::iterator it = + m_pimpl->m_kerningPairs.find(make_pair(firstChar, secondChar)); + if (it != m_pimpl->m_kerningPairs.end()) { + advance += it->second; + } + } + return TPoint(advance, 0); } //----------------------------------------------------------------------------- -int TFont::getMaxHeight() const -{ - return m_pimpl->m_metrics.tmHeight; -} +int TFont::getMaxHeight() const { return m_pimpl->m_metrics.tmHeight; } //----------------------------------------------------------------------------- -int TFont::getMaxWidth() const -{ - return m_pimpl->m_metrics.tmMaxCharWidth; -} +int TFont::getMaxWidth() const { return m_pimpl->m_metrics.tmMaxCharWidth; } //----------------------------------------------------------------------------- -int TFont::getLineAscender() const -{ - return m_pimpl->m_metrics.tmAscent; -} +int TFont::getLineAscender() const { return m_pimpl->m_metrics.tmAscent; } //----------------------------------------------------------------------------- -int TFont::getLineDescender() const -{ - return -m_pimpl->m_metrics.tmDescent; -} +int TFont::getLineDescender() const { return -m_pimpl->m_metrics.tmDescent; } //----------------------------------------------------------------------------- -bool TFont::hasKerning() const -{ - return m_pimpl->m_hasKerning; -} +bool TFont::hasKerning() const { return m_pimpl->m_hasKerning; } //----------------------------------------------------------------------------- -bool TFont::hasVertical() const -{ - return m_pimpl->m_hasVertical; -} +bool TFont::hasVertical() const { return m_pimpl->m_hasVertical; } //============================================================================= //==================== TFontManager ===================================== @@ -443,259 +416,227 @@ bool TFont::hasVertical() const //--------------------------------------------------------- struct TFontManager::Impl { - WindowsFontTable m_families; - bool m_loaded; + WindowsFontTable m_families; + bool m_loaded; - LOGFONTW m_currentLogFont; - TFont *m_currentFont; + LOGFONTW m_currentLogFont; + TFont *m_currentFont; - // this option is set by library user when he wants to write vertically. - // In this implementation, if m_vertical is true and the font - // has the @-version, the library use it. - bool m_vertical; + // this option is set by library user when he wants to write vertically. + // In this implementation, if m_vertical is true and the font + // has the @-version, the library use it. + bool m_vertical; - TFontManager::Impl() - : m_loaded(false), m_currentFont(0), m_vertical(false) - { - } + TFontManager::Impl() : m_loaded(false), m_currentFont(0), m_vertical(false) {} }; //--------------------------------------------------------- -TFontManager::TFontManager() -{ - m_pimpl = new TFontManager::Impl(); -} +TFontManager::TFontManager() { m_pimpl = new TFontManager::Impl(); } //--------------------------------------------------------- -TFontManager::~TFontManager() -{ - delete m_pimpl; -} +TFontManager::~TFontManager() { delete m_pimpl; } //--------------------------------------------------------- -TFontManager *TFontManager::instance() -{ - static TFontManager theManager; - return &theManager; +TFontManager *TFontManager::instance() { + static TFontManager theManager; + return &theManager; } //--------------------------------------------------------- -namespace -{ -BOOL CALLBACK EnumFamCallBack( - CONST LOGFONTW *lplf, - CONST TEXTMETRICW *, - DWORD FontType, - LPARAM data) -{ - if (FontType & TRUETYPE_FONTTYPE) { - LOGFONTW newLplf = *lplf; - newLplf.lfHeight = 200; - newLplf.lfWidth = 0; - WindowsFontTable &table = *(WindowsFontTable *)data; - table[lplf->lfFaceName] = newLplf; - return TRUE; - } - return TRUE; +namespace { +BOOL CALLBACK EnumFamCallBack(CONST LOGFONTW *lplf, CONST TEXTMETRICW *, + DWORD FontType, LPARAM data) { + if (FontType & TRUETYPE_FONTTYPE) { + LOGFONTW newLplf = *lplf; + newLplf.lfHeight = 200; + newLplf.lfWidth = 0; + WindowsFontTable &table = *(WindowsFontTable *)data; + table[lplf->lfFaceName] = newLplf; + return TRUE; + } + return TRUE; } } //--------------------------------------------------------- -void TFontManager::loadFontNames() -{ - if (m_pimpl->m_loaded) - return; - - HDC hdc = CreateCompatibleDC(NULL); - if (!hdc) - throw TFontLibraryLoadingError(); - EnumFontFamiliesW(hdc, - (LPCWSTR)NULL, - (FONTENUMPROCW)EnumFamCallBack, - (LPARAM) & (m_pimpl->m_families)); - DeleteDC(hdc); - hdc = 0; - if (m_pimpl->m_families.empty()) - throw TFontLibraryLoadingError(); - - m_pimpl->m_loaded = true; +void TFontManager::loadFontNames() { + if (m_pimpl->m_loaded) return; + + HDC hdc = CreateCompatibleDC(NULL); + if (!hdc) throw TFontLibraryLoadingError(); + EnumFontFamiliesW(hdc, (LPCWSTR)NULL, (FONTENUMPROCW)EnumFamCallBack, + (LPARAM) & (m_pimpl->m_families)); + DeleteDC(hdc); + hdc = 0; + if (m_pimpl->m_families.empty()) throw TFontLibraryLoadingError(); + + m_pimpl->m_loaded = true; } //--------------------------------------------------------- -void TFontManager::setFamily(const wstring family) -{ - - wstring userFamilyName = ((family.c_str())[0] == L'@') ? wstring(family.c_str() + 1) : family; - wstring realFamilyName = (m_pimpl->m_vertical && (family.c_str())[0] != L'@') ? L"@" + family : family; - - wstring currentFamilyName = wstring(m_pimpl->m_currentLogFont.lfFaceName); - - if (currentFamilyName == realFamilyName) - return; - - LOGFONTW logfont; - if (m_pimpl->m_vertical) { - WindowsFontTable::iterator it = m_pimpl->m_families.find(realFamilyName); - if (it != m_pimpl->m_families.end()) - logfont = it->second; - else { - it = m_pimpl->m_families.find(userFamilyName); - assert(it != m_pimpl->m_families.end()); - if (it != m_pimpl->m_families.end()) - logfont = it->second; - else - throw TFontCreationError(); - } - } else { - WindowsFontTable::iterator it = m_pimpl->m_families.find(userFamilyName); - assert(it != m_pimpl->m_families.end()); - if (it != m_pimpl->m_families.end()) - logfont = it->second; - else - throw TFontCreationError(); - } - - if (m_pimpl->m_currentFont) { - logfont.lfHeight = m_pimpl->m_currentLogFont.lfHeight; - logfont.lfItalic = m_pimpl->m_currentLogFont.lfItalic; - logfont.lfWeight = m_pimpl->m_currentLogFont.lfWeight; - } else - logfont.lfHeight = 200; - - try { - HDC hdc = CreateCompatibleDC(NULL); - TFont *newfont = new TFont(logfont, hdc); - delete m_pimpl->m_currentFont; - m_pimpl->m_currentFont = newfont; - m_pimpl->m_currentLogFont = logfont; - } catch (TException &) { - throw TFontCreationError(); - } +void TFontManager::setFamily(const wstring family) { + wstring userFamilyName = + ((family.c_str())[0] == L'@') ? wstring(family.c_str() + 1) : family; + wstring realFamilyName = (m_pimpl->m_vertical && (family.c_str())[0] != L'@') + ? L"@" + family + : family; + + wstring currentFamilyName = wstring(m_pimpl->m_currentLogFont.lfFaceName); + + if (currentFamilyName == realFamilyName) return; + + LOGFONTW logfont; + if (m_pimpl->m_vertical) { + WindowsFontTable::iterator it = m_pimpl->m_families.find(realFamilyName); + if (it != m_pimpl->m_families.end()) + logfont = it->second; + else { + it = m_pimpl->m_families.find(userFamilyName); + assert(it != m_pimpl->m_families.end()); + if (it != m_pimpl->m_families.end()) + logfont = it->second; + else + throw TFontCreationError(); + } + } else { + WindowsFontTable::iterator it = m_pimpl->m_families.find(userFamilyName); + assert(it != m_pimpl->m_families.end()); + if (it != m_pimpl->m_families.end()) + logfont = it->second; + else + throw TFontCreationError(); + } + + if (m_pimpl->m_currentFont) { + logfont.lfHeight = m_pimpl->m_currentLogFont.lfHeight; + logfont.lfItalic = m_pimpl->m_currentLogFont.lfItalic; + logfont.lfWeight = m_pimpl->m_currentLogFont.lfWeight; + } else + logfont.lfHeight = 200; + + try { + HDC hdc = CreateCompatibleDC(NULL); + TFont *newfont = new TFont(logfont, hdc); + delete m_pimpl->m_currentFont; + m_pimpl->m_currentFont = newfont; + m_pimpl->m_currentLogFont = logfont; + } catch (TException &) { + throw TFontCreationError(); + } } //--------------------------------------------------------- -void TFontManager::setTypeface(const wstring typeface) -{ - LOGFONTW logfont = m_pimpl->m_currentLogFont; - logfont.lfItalic = (typeface == L"Italic" || - typeface == L"Bold Italic") - ? TRUE - : FALSE; - logfont.lfWeight = (typeface == L"Bold" || - typeface == L"Bold Italic") - ? 700 - : 400; - - try { - HDC hdc = CreateCompatibleDC(NULL); - TFont *newfont = new TFont(logfont, hdc); - delete m_pimpl->m_currentFont; - m_pimpl->m_currentFont = newfont; - m_pimpl->m_currentLogFont = logfont; - } catch (TException &) { - throw TFontCreationError(); - } +void TFontManager::setTypeface(const wstring typeface) { + LOGFONTW logfont = m_pimpl->m_currentLogFont; + logfont.lfItalic = + (typeface == L"Italic" || typeface == L"Bold Italic") ? TRUE : FALSE; + logfont.lfWeight = + (typeface == L"Bold" || typeface == L"Bold Italic") ? 700 : 400; + + try { + HDC hdc = CreateCompatibleDC(NULL); + TFont *newfont = new TFont(logfont, hdc); + delete m_pimpl->m_currentFont; + m_pimpl->m_currentFont = newfont; + m_pimpl->m_currentLogFont = logfont; + } catch (TException &) { + throw TFontCreationError(); + } } //--------------------------------------------------------- -void TFontManager::setSize(int size) -{ - LOGFONTW logfont = m_pimpl->m_currentLogFont; - logfont.lfHeight = size; - try { - HDC hdc = CreateCompatibleDC(NULL); - TFont *newfont = new TFont(logfont, hdc); - delete m_pimpl->m_currentFont; - m_pimpl->m_currentFont = newfont; - m_pimpl->m_currentLogFont = logfont; - } catch (TException &) { - throw TFontCreationError(); - } +void TFontManager::setSize(int size) { + LOGFONTW logfont = m_pimpl->m_currentLogFont; + logfont.lfHeight = size; + try { + HDC hdc = CreateCompatibleDC(NULL); + TFont *newfont = new TFont(logfont, hdc); + delete m_pimpl->m_currentFont; + m_pimpl->m_currentFont = newfont; + m_pimpl->m_currentLogFont = logfont; + } catch (TException &) { + throw TFontCreationError(); + } } //--------------------------------------------------------- -wstring TFontManager::getCurrentFamily() const -{ - wstring currentFamilyName = (m_pimpl->m_currentLogFont.lfFaceName[0] == L'@') ? wstring(m_pimpl->m_currentLogFont.lfFaceName + 1) : wstring(m_pimpl->m_currentLogFont.lfFaceName); - return currentFamilyName; +wstring TFontManager::getCurrentFamily() const { + wstring currentFamilyName = + (m_pimpl->m_currentLogFont.lfFaceName[0] == L'@') + ? wstring(m_pimpl->m_currentLogFont.lfFaceName + 1) + : wstring(m_pimpl->m_currentLogFont.lfFaceName); + return currentFamilyName; } //--------------------------------------------------------- -wstring TFontManager::getCurrentTypeface() const -{ - if (m_pimpl->m_currentLogFont.lfItalic) { - if (m_pimpl->m_currentLogFont.lfWeight == 700) - return L"Bold Italic"; - else - return L"Italic"; - } else { - if (m_pimpl->m_currentLogFont.lfWeight == 700) - return L"Bold"; - else - return L"Regular"; - } +wstring TFontManager::getCurrentTypeface() const { + if (m_pimpl->m_currentLogFont.lfItalic) { + if (m_pimpl->m_currentLogFont.lfWeight == 700) + return L"Bold Italic"; + else + return L"Italic"; + } else { + if (m_pimpl->m_currentLogFont.lfWeight == 700) + return L"Bold"; + else + return L"Regular"; + } } //--------------------------------------------------------- -TFont *TFontManager::getCurrentFont() -{ - if (m_pimpl->m_currentFont) - return m_pimpl->m_currentFont; +TFont *TFontManager::getCurrentFont() { + if (m_pimpl->m_currentFont) return m_pimpl->m_currentFont; - if (!m_pimpl->m_currentFont) - loadFontNames(); + if (!m_pimpl->m_currentFont) loadFontNames(); - assert(!m_pimpl->m_families.empty()); - setFamily(m_pimpl->m_families.begin()->first); + assert(!m_pimpl->m_families.empty()); + setFamily(m_pimpl->m_families.begin()->first); - return m_pimpl->m_currentFont; + return m_pimpl->m_currentFont; } //--------------------------------------------------------- -void TFontManager::getAllFamilies(vector &families) const -{ - families.clear(); - families.reserve(m_pimpl->m_families.size()); - WindowsFontTable::iterator it = m_pimpl->m_families.begin(); - for (; it != m_pimpl->m_families.end(); ++it) { - if ((it->first)[0] != L'@') - families.push_back(it->first); - } +void TFontManager::getAllFamilies(vector &families) const { + families.clear(); + families.reserve(m_pimpl->m_families.size()); + WindowsFontTable::iterator it = m_pimpl->m_families.begin(); + for (; it != m_pimpl->m_families.end(); ++it) { + if ((it->first)[0] != L'@') families.push_back(it->first); + } } //--------------------------------------------------------- -void TFontManager::getAllTypefaces(vector &typefaces) const -{ - typefaces.resize(4); - typefaces[0] = L"Regular"; - typefaces[1] = L"Italic"; - typefaces[2] = L"Bold"; - typefaces[3] = L"Bold Italic"; +void TFontManager::getAllTypefaces(vector &typefaces) const { + typefaces.resize(4); + typefaces[0] = L"Regular"; + typefaces[1] = L"Italic"; + typefaces[2] = L"Bold"; + typefaces[3] = L"Bold Italic"; } //--------------------------------------------------------- -void TFontManager::setVertical(bool vertical) -{ - if (m_pimpl->m_vertical == vertical) - return; - m_pimpl->m_vertical = vertical; - - wstring currentFamilyName = (m_pimpl->m_currentLogFont.lfFaceName[0] == L'@') ? wstring(m_pimpl->m_currentLogFont.lfFaceName + 1) : wstring(m_pimpl->m_currentLogFont.lfFaceName); - if (vertical) - currentFamilyName = L'@' + currentFamilyName; - setFamily(currentFamilyName); +void TFontManager::setVertical(bool vertical) { + if (m_pimpl->m_vertical == vertical) return; + m_pimpl->m_vertical = vertical; + + wstring currentFamilyName = + (m_pimpl->m_currentLogFont.lfFaceName[0] == L'@') + ? wstring(m_pimpl->m_currentLogFont.lfFaceName + 1) + : wstring(m_pimpl->m_currentLogFont.lfFaceName); + if (vertical) currentFamilyName = L'@' + currentFamilyName; + setFamily(currentFamilyName); } diff --git a/toonz/sources/common/tvrender/tfont_proxy.cpp b/toonz/sources/common/tvrender/tfont_proxy.cpp index 68b6e36..77c5726 100644 --- a/toonz/sources/common/tvrender/tfont_proxy.cpp +++ b/toonz/sources/common/tvrender/tfont_proxy.cpp @@ -2,12 +2,12 @@ #ifdef __LP64__ -//Toonz includes +// Toonz includes #include "tvectorimage.h" #include "tstroke.h" #include "trop.h" -//Qt includes +// Qt includes #include /* @@ -18,7 +18,7 @@ が T=TThickPoint でインスタンス化されようとして曖昧ですエラーになる */ -//tipc includes +// tipc includes #include "tipc.h" #include "t32bitsrv_wrap.h" @@ -28,30 +28,27 @@ // Local namespace stuff //************************************************************************** -namespace -{ +namespace { -QDataStream &operator>>(QDataStream &ds, TThickPoint &p) -{ - return ds >> p.x >> p.y >> p.thick; +QDataStream &operator>>(QDataStream &ds, TThickPoint &p) { + return ds >> p.x >> p.y >> p.thick; } -void readVImage(TVectorImageP &vi, tipc::Message &msg) -{ - std::vector strokeCPs; +void readVImage(TVectorImageP &vi, tipc::Message &msg) { + std::vector strokeCPs; - //Read in all strokes - while (!msg.ds().atEnd()) { - strokeCPs.clear(); - msg >> strokeCPs; + // Read in all strokes + while (!msg.ds().atEnd()) { + strokeCPs.clear(); + msg >> strokeCPs; - vi->addStroke(new TStroke(strokeCPs)); - } + vi->addStroke(new TStroke(strokeCPs)); + } - vi->group(0, vi->getStrokeCount()); + vi->group(0, vi->getStrokeCount()); } -} //namespace +} // namespace //************************************************************************** // TFontManager Private stuff @@ -62,371 +59,346 @@ void readVImage(TVectorImageP &vi, tipc::Message &msg) background counterpart */ struct TFontManager::Impl { - int m_ascender; - int m_descender; + int m_ascender; + int m_descender; - Impl() {} - ~Impl() {} + Impl() {} + ~Impl() {} }; //************************************************************************** // TFontManager Proxied implementation //************************************************************************** -TFontManager::TFontManager() -{ - m_pimpl = new TFontManager::Impl(); -} +TFontManager::TFontManager() { m_pimpl = new TFontManager::Impl(); } //-------------------------------------------------------------- -TFontManager::~TFontManager() -{ - delete m_pimpl; -} +TFontManager::~TFontManager() { delete m_pimpl; } //-------------------------------------------------------------- -TFontManager *TFontManager::instance() -{ - static TFontManager theInstance; - return &theInstance; +TFontManager *TFontManager::instance() { + static TFontManager theInstance; + return &theInstance; } //-------------------------------------------------------------- -//!This function is retained from old 32-bit legacy code. -//!Its use is now forbidden - use the TFontManager directly instead. -TFont *TFontManager::getCurrentFont() -{ - assert(false); - return 0; +//! This function is retained from old 32-bit legacy code. +//! Its use is now forbidden - use the TFontManager directly instead. +TFont *TFontManager::getCurrentFont() { + assert(false); + return 0; } //-------------------------------------------------------------- //!\note Throws TFontLibraryLoadingError if fonts could not be loaded -void TFontManager::loadFontNames() -{ - //Connect to the 32-bit background server process - QLocalSocket socket; - tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1, t32bitsrv::srvCmdline()); - - tipc::Stream stream(&socket); - tipc::Message msg; - - stream << (msg << QString("$FNTloadFontNames")); - if (tipc::readMessage(stream, msg) != "ok") - throw TFontLibraryLoadingError(); +void TFontManager::loadFontNames() { + // Connect to the 32-bit background server process + QLocalSocket socket; + tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1, + t32bitsrv::srvCmdline()); + + tipc::Stream stream(&socket); + tipc::Message msg; + + stream << (msg << QString("$FNTloadFontNames")); + if (tipc::readMessage(stream, msg) != "ok") throw TFontLibraryLoadingError(); } //-------------------------------------------------------------- //!\note Throws TFontCreationError if the font could not be created, and -//!leaves the old font as current. -void TFontManager::setFamily(const std::wstring family) -{ - QLocalSocket socket; - tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1, t32bitsrv::srvCmdline()); - - tipc::Stream stream(&socket); - tipc::Message msg; - - stream << (msg << QString("$FNTsetFamily") << family); - if (tipc::readMessage(stream, msg) != "ok") - throw TFontCreationError(); +//! leaves the old font as current. +void TFontManager::setFamily(const std::wstring family) { + QLocalSocket socket; + tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1, + t32bitsrv::srvCmdline()); + + tipc::Stream stream(&socket); + tipc::Message msg; + + stream << (msg << QString("$FNTsetFamily") << family); + if (tipc::readMessage(stream, msg) != "ok") throw TFontCreationError(); } //-------------------------------------------------------------- //!\note Throws TFontCreationError if the font could not be created, and -//!leaves the old font as current. -void TFontManager::setTypeface(const std::wstring typeface) -{ - QLocalSocket socket; - tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1, t32bitsrv::srvCmdline()); +//! leaves the old font as current. +void TFontManager::setTypeface(const std::wstring typeface) { + QLocalSocket socket; + tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1, + t32bitsrv::srvCmdline()); - tipc::Stream stream(&socket); - tipc::Message msg; + tipc::Stream stream(&socket); + tipc::Message msg; - stream << (msg << QString("$FNTsetTypeface") << typeface); - if (tipc::readMessage(stream, msg) != "ok") - throw TFontCreationError(); + stream << (msg << QString("$FNTsetTypeface") << typeface); + if (tipc::readMessage(stream, msg) != "ok") throw TFontCreationError(); - //Also, store the font's ascender and descender - msg >> m_pimpl->m_ascender >> m_pimpl->m_descender; + // Also, store the font's ascender and descender + msg >> m_pimpl->m_ascender >> m_pimpl->m_descender; } //-------------------------------------------------------------- -std::wstring TFontManager::getCurrentFamily() const -{ - QLocalSocket socket; - tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1, t32bitsrv::srvCmdline()); +std::wstring TFontManager::getCurrentFamily() const { + QLocalSocket socket; + tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1, + t32bitsrv::srvCmdline()); - tipc::Stream stream(&socket); - tipc::Message msg; + tipc::Stream stream(&socket); + tipc::Message msg; - stream << (msg << QString("$FNTgetCurrentFamily")); - if (tipc::readMessage(stream, msg) != "ok") - throw TException("Could not get font family"); + stream << (msg << QString("$FNTgetCurrentFamily")); + if (tipc::readMessage(stream, msg) != "ok") + throw TException("Could not get font family"); - std::wstring family; - msg >> family; - return family; + std::wstring family; + msg >> family; + return family; } //-------------------------------------------------------------- -std::wstring TFontManager::getCurrentTypeface() const -{ - QLocalSocket socket; - tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1, t32bitsrv::srvCmdline()); +std::wstring TFontManager::getCurrentTypeface() const { + QLocalSocket socket; + tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1, + t32bitsrv::srvCmdline()); - tipc::Stream stream(&socket); - tipc::Message msg; + tipc::Stream stream(&socket); + tipc::Message msg; - stream << (msg << QString("$FNTgetCurrentTypeface")); - if (tipc::readMessage(stream, msg) != "ok") - throw TException("Could not get font typeface"); + stream << (msg << QString("$FNTgetCurrentTypeface")); + if (tipc::readMessage(stream, msg) != "ok") + throw TException("Could not get font typeface"); - std::wstring typeface; - msg >> typeface; - return typeface; + std::wstring typeface; + msg >> typeface; + return typeface; } //-------------------------------------------------------------- -void TFontManager::getAllFamilies(std::vector &families) const -{ - QLocalSocket socket; - tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1, t32bitsrv::srvCmdline()); +void TFontManager::getAllFamilies(std::vector &families) const { + QLocalSocket socket; + tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1, + t32bitsrv::srvCmdline()); - tipc::Stream stream(&socket); - tipc::Message msg; + tipc::Stream stream(&socket); + tipc::Message msg; - stream << (msg << QString("$FNTgetAllFamilies")); - if (tipc::readMessage(stream, msg) != "ok") - throw TException("Could not get font families"); + stream << (msg << QString("$FNTgetAllFamilies")); + if (tipc::readMessage(stream, msg) != "ok") + throw TException("Could not get font families"); - msg >> families; + msg >> families; } //-------------------------------------------------------------- -void TFontManager::getAllTypefaces(std::vector &typefaces) const -{ - QLocalSocket socket; - tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1, t32bitsrv::srvCmdline()); +void TFontManager::getAllTypefaces(std::vector &typefaces) const { + QLocalSocket socket; + tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1, + t32bitsrv::srvCmdline()); - tipc::Stream stream(&socket); - tipc::Message msg; + tipc::Stream stream(&socket); + tipc::Message msg; - stream << (msg << QString("$FNTgetAllTypefaces")); - if (tipc::readMessage(stream, msg) != "ok") - throw TException("Could not get font typefaces"); + stream << (msg << QString("$FNTgetAllTypefaces")); + if (tipc::readMessage(stream, msg) != "ok") + throw TException("Could not get font typefaces"); - msg >> typefaces; + msg >> typefaces; } //-------------------------------------------------------------- -void TFontManager::setVertical(bool vertical) -{ -} +void TFontManager::setVertical(bool vertical) {} //-------------------------------------------------------------- -void TFontManager::setSize(int size) -{ - QLocalSocket socket; - tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1, t32bitsrv::srvCmdline()); +void TFontManager::setSize(int size) { + QLocalSocket socket; + tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1, + t32bitsrv::srvCmdline()); - tipc::Stream stream(&socket); - tipc::Message msg; + tipc::Stream stream(&socket); + tipc::Message msg; - stream << (msg << QString("$FNTsetSize") << size); - if (tipc::readMessage(stream, msg) != "ok") - throw TException("Unexpected error"); + stream << (msg << QString("$FNTsetSize") << size); + if (tipc::readMessage(stream, msg) != "ok") + throw TException("Unexpected error"); - //Also, update ascender and descender - msg >> m_pimpl->m_ascender >> m_pimpl->m_descender; + // Also, update ascender and descender + msg >> m_pimpl->m_ascender >> m_pimpl->m_descender; } //-------------------------------------------------------------- -TPoint TFontManager::getDistance(wchar_t firstChar, wchar_t secondChar) -{ - QLocalSocket socket; - tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1, t32bitsrv::srvCmdline()); +TPoint TFontManager::getDistance(wchar_t firstChar, wchar_t secondChar) { + QLocalSocket socket; + tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1, + t32bitsrv::srvCmdline()); - tipc::Stream stream(&socket); - tipc::Message msg; + tipc::Stream stream(&socket); + tipc::Message msg; - stream << (msg << QString("$FNTgetDistance") << firstChar << secondChar); - if (tipc::readMessage(stream, msg) != "ok") - throw TException("Unexpected error"); + stream << (msg << QString("$FNTgetDistance") << firstChar << secondChar); + if (tipc::readMessage(stream, msg) != "ok") + throw TException("Unexpected error"); - TPoint d; - msg >> d.x >> d.y; - return d; + TPoint d; + msg >> d.x >> d.y; + return d; } //-------------------------------------------------------------- -int TFontManager::getMaxHeight() -{ - return m_pimpl->m_ascender - m_pimpl->m_descender; +int TFontManager::getMaxHeight() { + return m_pimpl->m_ascender - m_pimpl->m_descender; } //-------------------------------------------------------------- -int TFontManager::getMaxWidth() -{ - assert(!"not implemented yet"); - return 100; +int TFontManager::getMaxWidth() { + assert(!"not implemented yet"); + return 100; } //-------------------------------------------------------------- -bool TFontManager::hasVertical() -{ - return false; -} +bool TFontManager::hasVertical() { return false; } //-------------------------------------------------------------- -bool TFontManager::hasKerning() -{ - return true; -} +bool TFontManager::hasKerning() { return true; } //-------------------------------------------------------------- -int TFontManager::getLineAscender() -{ - return m_pimpl->m_ascender; -} +int TFontManager::getLineAscender() { return m_pimpl->m_ascender; } //-------------------------------------------------------------- -int TFontManager::getLineDescender() -{ - return m_pimpl->m_descender; -} +int TFontManager::getLineDescender() { return m_pimpl->m_descender; } //-------------------------------------------------------------- -TPoint TFontManager::drawChar(TVectorImageP &outImage, wchar_t charcode, wchar_t nextCode) -{ - QLocalSocket socket; - tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1, t32bitsrv::srvCmdline()); +TPoint TFontManager::drawChar(TVectorImageP &outImage, wchar_t charcode, + wchar_t nextCode) { + QLocalSocket socket; + tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1, + t32bitsrv::srvCmdline()); - tipc::Stream stream(&socket); - tipc::Message msg; + tipc::Stream stream(&socket); + tipc::Message msg; - stream << (msg << QString("$FNTdrawCharVI") << charcode << nextCode); - if (tipc::readMessage(stream, msg) != "ok") - throw TException("Unexpected error"); + stream << (msg << QString("$FNTdrawCharVI") << charcode << nextCode); + if (tipc::readMessage(stream, msg) != "ok") + throw TException("Unexpected error"); - TPoint ret; - msg >> ret.x >> ret.y; - ::readVImage(outImage, msg); + TPoint ret; + msg >> ret.x >> ret.y; + ::readVImage(outImage, msg); - return ret; + return ret; } //-------------------------------------------------------------- -TPoint TFontManager::drawChar(TRasterGR8P &outImage, TPoint &glyphOrigin, wchar_t charcode, wchar_t nextCode) -{ - QLocalSocket socket; - tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1, t32bitsrv::srvCmdline()); - - tipc::Stream stream(&socket); - tipc::Message msg; - - QString shMemId(tipc::uniqueId()), res; - { - //Invoke the appropriate command - stream << (msg << QString("$FNTdrawCharGR") - << shMemId << charcode << nextCode); - if (tipc::readMessage(stream, msg) != "ok") - throw TException("Unexpected error"); - } - - TDimension dim(0, 0); - msg >> dim.lx >> dim.ly; - TPoint ret; - msg >> ret.x >> ret.y; - - //Create outImage - outImage = TRasterGR8P(dim.lx, dim.ly); - - QSharedMemory shmem(shMemId); - shmem.attach(); - shmem.lock(); - - //Copy the returned image to outImage - TRasterGR8P ras(dim.lx, dim.ly, dim.lx, (TPixelGR8 *)shmem.data()); - TRop::copy(outImage, ras); - - shmem.unlock(); - shmem.detach(); - - //Release the shared segment - stream << (msg << tipc::clr << QString("$shmem_release") << shMemId); - if (tipc::readMessage(stream, msg) != "ok") - throw TException("Unexpected error"); - - return ret; +TPoint TFontManager::drawChar(TRasterGR8P &outImage, TPoint &glyphOrigin, + wchar_t charcode, wchar_t nextCode) { + QLocalSocket socket; + tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1, + t32bitsrv::srvCmdline()); + + tipc::Stream stream(&socket); + tipc::Message msg; + + QString shMemId(tipc::uniqueId()), res; + { + // Invoke the appropriate command + stream << (msg << QString("$FNTdrawCharGR") << shMemId << charcode + << nextCode); + if (tipc::readMessage(stream, msg) != "ok") + throw TException("Unexpected error"); + } + + TDimension dim(0, 0); + msg >> dim.lx >> dim.ly; + TPoint ret; + msg >> ret.x >> ret.y; + + // Create outImage + outImage = TRasterGR8P(dim.lx, dim.ly); + + QSharedMemory shmem(shMemId); + shmem.attach(); + shmem.lock(); + + // Copy the returned image to outImage + TRasterGR8P ras(dim.lx, dim.ly, dim.lx, (TPixelGR8 *)shmem.data()); + TRop::copy(outImage, ras); + + shmem.unlock(); + shmem.detach(); + + // Release the shared segment + stream << (msg << tipc::clr << QString("$shmem_release") << shMemId); + if (tipc::readMessage(stream, msg) != "ok") + throw TException("Unexpected error"); + + return ret; } //-------------------------------------------------------------- TPoint TFontManager::drawChar(TRasterCM32P &outImage, TPoint &glyphOrigin, - int inkId, wchar_t charcode, wchar_t nextCode) -{ - QLocalSocket socket; - tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1, t32bitsrv::srvCmdline()); - - tipc::Stream stream(&socket); - tipc::Message msg; - - QString shMemId(tipc::uniqueId()), res; - { - //Invoke the appropriate command - stream << (msg << QString("$FNTdrawCharCM") - << inkId << shMemId << charcode << nextCode); - if (tipc::readMessage(stream, msg) != "ok") - throw TException("Unexpected error"); - } - - TDimension dim(0, 0); - msg >> dim.lx >> dim.ly; - TPoint ret; - msg >> ret.x >> ret.y; - - //Create outImage - outImage = TRasterCM32P(dim.lx, dim.ly); - - QSharedMemory shmem(shMemId); - shmem.attach(); - shmem.lock(); - - //Copy the returned image to outImage - TRasterCM32P ras(dim.lx, dim.ly, dim.lx, (TPixelCM32 *)shmem.data()); - TRop::copy(outImage, ras); - - shmem.unlock(); - shmem.detach(); - - //Release the shared segment - stream << (msg << tipc::clr << QString("$shmem_release") << shMemId); - if (tipc::readMessage(stream, msg) != "ok") - throw TException("Unexpected error"); - - return ret; + int inkId, wchar_t charcode, wchar_t nextCode) { + QLocalSocket socket; + tipc::startSlaveConnection(&socket, t32bitsrv::srvName(), -1, + t32bitsrv::srvCmdline()); + + tipc::Stream stream(&socket); + tipc::Message msg; + + QString shMemId(tipc::uniqueId()), res; + { + // Invoke the appropriate command + stream << (msg << QString("$FNTdrawCharCM") << inkId << shMemId << charcode + << nextCode); + if (tipc::readMessage(stream, msg) != "ok") + throw TException("Unexpected error"); + } + + TDimension dim(0, 0); + msg >> dim.lx >> dim.ly; + TPoint ret; + msg >> ret.x >> ret.y; + + // Create outImage + outImage = TRasterCM32P(dim.lx, dim.ly); + + QSharedMemory shmem(shMemId); + shmem.attach(); + shmem.lock(); + + // Copy the returned image to outImage + TRasterCM32P ras(dim.lx, dim.ly, dim.lx, (TPixelCM32 *)shmem.data()); + TRop::copy(outImage, ras); + + shmem.unlock(); + shmem.detach(); + + // Release the shared segment + stream << (msg << tipc::clr << QString("$shmem_release") << shMemId); + if (tipc::readMessage(stream, msg) != "ok") + throw TException("Unexpected error"); + + return ret; } #endif diff --git a/toonz/sources/common/tvrender/tglcurves.cpp b/toonz/sources/common/tvrender/tglcurves.cpp index 83cc834..49f6a93 100644 --- a/toonz/sources/common/tvrender/tglcurves.cpp +++ b/toonz/sources/common/tvrender/tglcurves.cpp @@ -11,45 +11,43 @@ //============================================================================= #ifdef SPOSTATOINTGLREGIONS -void tglDraw(const TVectorRenderData &rd, const TStroke *s) -{ - assert(s); - if (!s) - return; - - const TStroke &stroke = *s; - - // initialize information for aaliasing - glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - glEnable(GL_LINE_SMOOTH); - - // it's necessary to do line function of pixel size ? - glLineWidth((float)1.0); - - assert(rd.m_palette); - TStrokeProp *prop = stroke.getProp(/*rd.m_palette*/); - /////questo codice stava dentro tstroke::getprop///////// - TColorStyle *style = rd.m_palette->getStyle(stroke->getStyle() /*m_imp->m_styleId*/); - if (!style->isStrokeStyle() || style->isEnabled() == false) { - prop = 0; - } else { - if (!prop || style != prop->getColorStyle()) { - stroke->setProp(style->makeStrokeProp(stroke)); - prop = stroke->getProp(); - } - } - /// - //--------------------- - if (prop) - prop->draw(rd); - //--------------------- - - tglColor(TPixel32::White); - - glDisable(GL_BLEND); - glDisable(GL_LINE_SMOOTH); +void tglDraw(const TVectorRenderData &rd, const TStroke *s) { + assert(s); + if (!s) return; + + const TStroke &stroke = *s; + + // initialize information for aaliasing + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + glEnable(GL_LINE_SMOOTH); + + // it's necessary to do line function of pixel size ? + glLineWidth((float)1.0); + + assert(rd.m_palette); + TStrokeProp *prop = stroke.getProp(/*rd.m_palette*/); + /////questo codice stava dentro tstroke::getprop///////// + TColorStyle *style = + rd.m_palette->getStyle(stroke->getStyle() /*m_imp->m_styleId*/); + if (!style->isStrokeStyle() || style->isEnabled() == false) { + prop = 0; + } else { + if (!prop || style != prop->getColorStyle()) { + stroke->setProp(style->makeStrokeProp(stroke)); + prop = stroke->getProp(); + } + } + /// + //--------------------- + if (prop) prop->draw(rd); + //--------------------- + + tglColor(TPixel32::White); + + glDisable(GL_BLEND); + glDisable(GL_LINE_SMOOTH); } #endif //----------------------------------------------------------------------------- diff --git a/toonz/sources/common/tvrender/tglregions.cpp b/toonz/sources/common/tvrender/tglregions.cpp index 746ef59..8bf6004 100644 --- a/toonz/sources/common/tvrender/tglregions.cpp +++ b/toonz/sources/common/tvrender/tglregions.cpp @@ -22,17 +22,17 @@ #endif #ifndef checkErrorsByGL -#define checkErrorsByGL \ - { \ - GLenum err = glGetError(); \ - assert(err != GL_INVALID_ENUM); \ - assert(err != GL_INVALID_VALUE); \ - assert(err != GL_INVALID_OPERATION); \ - assert(err != GL_STACK_OVERFLOW); \ - assert(err != GL_STACK_UNDERFLOW); \ - assert(err != GL_OUT_OF_MEMORY); \ - assert(err == GL_NO_ERROR); \ - } +#define checkErrorsByGL \ + { \ + GLenum err = glGetError(); \ + assert(err != GL_INVALID_ENUM); \ + assert(err != GL_INVALID_VALUE); \ + assert(err != GL_INVALID_OPERATION); \ + assert(err != GL_STACK_OVERFLOW); \ + assert(err != GL_STACK_UNDERFLOW); \ + assert(err != GL_OUT_OF_MEMORY); \ + assert(err == GL_NO_ERROR); \ + } #endif #undef checkErrorsByGL @@ -49,8 +49,8 @@ DV_EXPORT_API void mylog(std::string s) std::ofstream os("C:\\gmt\\buttami\\bu.txt", std::ios::app); LARGE_INTEGER ticksPerSecond; - LARGE_INTEGER tick; - static LARGE_INTEGER firstTick; + LARGE_INTEGER tick; + static LARGE_INTEGER firstTick; static bool firstTime = true; long dt = 0; @@ -59,7 +59,8 @@ DV_EXPORT_API void mylog(std::string s) if(firstTime) {firstTick = tick;firstTime=false;} else { - dt = (long)(1000000*(tick.QuadPart-firstTick.QuadPart)/ticksPerSecond.QuadPart); + dt = +(long)(1000000*(tick.QuadPart-firstTick.QuadPart)/ticksPerSecond.QuadPart); } os << dt << ":" << s << std::endl; } @@ -68,67 +69,65 @@ DV_EXPORT_API void mylog(std::string s) //============================================================================= #ifdef _DEBUG -bool checkQuadraticDistance(TStroke *stroke, bool checkThickness) -{ - UINT i, qCount = stroke->getChunkCount(); - const TThickQuadratic *q; - TThickPoint p1, p2, p3; - - //se i punti coincidono e' una stroke puntiforme ed e' ammessa - if (qCount == 1) - return true; - - for (i = 0; i != qCount; i++) { - q = stroke->getChunk(i); - p1 = q->getThickP0(); - p2 = q->getThickP1(); - p3 = q->getThickP2(); - - if (areAlmostEqual(p1.x, p2.x) && areAlmostEqual(p2.x, p3.x) && - areAlmostEqual(p1.y, p2.y) && areAlmostEqual(p2.y, p3.y) && - (!checkThickness || - (areAlmostEqual(p1.thick, p2.thick) && areAlmostEqual(p2.thick, p3.thick)))) - return false; - } - return true; +bool checkQuadraticDistance(TStroke *stroke, bool checkThickness) { + UINT i, qCount = stroke->getChunkCount(); + const TThickQuadratic *q; + TThickPoint p1, p2, p3; + + // se i punti coincidono e' una stroke puntiforme ed e' ammessa + if (qCount == 1) return true; + + for (i = 0; i != qCount; i++) { + q = stroke->getChunk(i); + p1 = q->getThickP0(); + p2 = q->getThickP1(); + p3 = q->getThickP2(); + + if (areAlmostEqual(p1.x, p2.x) && areAlmostEqual(p2.x, p3.x) && + areAlmostEqual(p1.y, p2.y) && areAlmostEqual(p2.y, p3.y) && + (!checkThickness || (areAlmostEqual(p1.thick, p2.thick) && + areAlmostEqual(p2.thick, p3.thick)))) + return false; + } + return true; } //----------------------------------------------------------------------------- -void drawControlPoints(const TVectorRenderData &rd, TStroke *stroke, double pixelSize, bool allPoints = true) -{ - int i; - TPointD p; - glPushMatrix(); - - tglMultMatrix(rd.m_aff); - - glPointSize(2.0); - glBegin(GL_POINTS); - - if (allPoints) { - int n = stroke->getControlPointCount(); - for (i = 0; i < n; ++i) { - p = stroke->getControlPoint(i); - glColor3d((i + 1) & 1, i & 1, 0.0); - glVertex2d(p.x, p.y); - } - } else { - int n = stroke->getChunkCount(); - for (i = 0; i < n; ++i) { - const TThickQuadratic *chunk = stroke->getChunk(i); - p = chunk->getP0(); - glColor3d(1.0, 0.0, 0.0); - glVertex2d(p.x, p.y); - } - const TThickQuadratic *chunk = stroke->getChunk(n - 1); - glColor3d(1.0, 0.0, 0.0); - p = chunk->getP2(); - glVertex2d(p.x, p.y); - } - - glEnd(); - glPopMatrix(); +void drawControlPoints(const TVectorRenderData &rd, TStroke *stroke, + double pixelSize, bool allPoints = true) { + int i; + TPointD p; + glPushMatrix(); + + tglMultMatrix(rd.m_aff); + + glPointSize(2.0); + glBegin(GL_POINTS); + + if (allPoints) { + int n = stroke->getControlPointCount(); + for (i = 0; i < n; ++i) { + p = stroke->getControlPoint(i); + glColor3d((i + 1) & 1, i & 1, 0.0); + glVertex2d(p.x, p.y); + } + } else { + int n = stroke->getChunkCount(); + for (i = 0; i < n; ++i) { + const TThickQuadratic *chunk = stroke->getChunk(i); + p = chunk->getP0(); + glColor3d(1.0, 0.0, 0.0); + glVertex2d(p.x, p.y); + } + const TThickQuadratic *chunk = stroke->getChunk(n - 1); + glColor3d(1.0, 0.0, 0.0); + p = chunk->getP2(); + glVertex2d(p.x, p.y); + } + + glEnd(); + glPopMatrix(); } #endif @@ -139,468 +138,452 @@ void drawControlPoints(const TVectorRenderData &rd, TStroke *stroke, double pixe TPixel TransparencyCheckWhiteBgInk = TPixel(0,0,0); TPixel TransparencyCheckPaint = TPixel(127,127,127);*/ static int Index = 0; -void tglDraw(const TVectorRenderData &rd, TRegion *r, bool pushAttribs) -{ - checkErrorsByGL; - assert(r); - checkErrorsByGL; - if (!r) - return; - bool alphaChannel = rd.m_alphaChannel; - checkErrorsByGL; - - int j = 0; - bool visible = false; - int colorCount = 0; - - TColorStyleP style; - if (rd.m_paintCheckEnabled && r->getStyle() == rd.m_colorCheckIndex) { - static TSolidColorStyle *redColor = new TSolidColorStyle(); - redColor->addRef(); - redColor->setMainColor(TPixel::Red); - style = redColor; - } else if (rd.m_tcheckEnabled) { - static TSolidColorStyle *color = new TSolidColorStyle(); - color->addRef(); - color->setMainColor(rd.m_tCheckPaint); - style = color; - } else - style = rd.m_palette->getStyle(r->getStyle()); - - colorCount = style->getColorParamCount(); - if (colorCount == 0) { //for example texture - visible = true; - } else { - visible = false; - for (j = 0; j < colorCount && !visible; j++) { - TPixel32 color = style->getColorParamValue(j); - if (rd.m_cf) - color = (*(rd.m_cf))(color); - if (color.m != 0) - visible = true; - } - } - if (visible) { - TRegionProp *prop = r->getProp(/*rd.m_palette*/); - ///questo codice satva dentro tregion::getprop///// - int styleId = r->getStyle(); - if (styleId) { - // TColorStyle * style = rd.m_palette->getStyle(styleId); - if (!style->isRegionStyle() || style->isEnabled() == false) { - prop = 0; - } else { - //Warning: The same remark of stroke props holds here. - if (!prop || style.getPointer() != prop->getColorStyle()) { - r->setProp(style->makeRegionProp(r)); - prop = r->getProp(); - } - } - } - - ////// draw - if (prop) { - if (pushAttribs) - glPushAttrib(GL_ALL_ATTRIB_BITS); - - tglEnableLineSmooth(true); +void tglDraw(const TVectorRenderData &rd, TRegion *r, bool pushAttribs) { + checkErrorsByGL; + assert(r); + checkErrorsByGL; + if (!r) return; + bool alphaChannel = rd.m_alphaChannel; + checkErrorsByGL; + + int j = 0; + bool visible = false; + int colorCount = 0; + + TColorStyleP style; + if (rd.m_paintCheckEnabled && r->getStyle() == rd.m_colorCheckIndex) { + static TSolidColorStyle *redColor = new TSolidColorStyle(); + redColor->addRef(); + redColor->setMainColor(TPixel::Red); + style = redColor; + } else if (rd.m_tcheckEnabled) { + static TSolidColorStyle *color = new TSolidColorStyle(); + color->addRef(); + color->setMainColor(rd.m_tCheckPaint); + style = color; + } else + style = rd.m_palette->getStyle(r->getStyle()); + + colorCount = style->getColorParamCount(); + if (colorCount == 0) { // for example texture + visible = true; + } else { + visible = false; + for (j = 0; j < colorCount && !visible; j++) { + TPixel32 color = style->getColorParamValue(j); + if (rd.m_cf) color = (*(rd.m_cf))(color); + if (color.m != 0) visible = true; + } + } + if (visible) { + TRegionProp *prop = r->getProp(/*rd.m_palette*/); + /// questo codice satva dentro tregion::getprop///// + int styleId = r->getStyle(); + if (styleId) { + // TColorStyle * style = rd.m_palette->getStyle(styleId); + if (!style->isRegionStyle() || style->isEnabled() == false) { + prop = 0; + } else { + // Warning: The same remark of stroke props holds here. + if (!prop || style.getPointer() != prop->getColorStyle()) { + r->setProp(style->makeRegionProp(r)); + prop = r->getProp(); + } + } + } + + ////// draw + if (prop) { + if (pushAttribs) glPushAttrib(GL_ALL_ATTRIB_BITS); + + tglEnableLineSmooth(true); //#define DRAW_EDGE_NUMBERS #ifdef DRAW_EDGE_NUMBERS - glPushMatrix(); - tglMultMatrix(rd.m_aff); - switch (Index % 7) { - case 0: - tglColor(TPixel::Red); - break; - case 1: - tglColor(TPixel::Green); - break; - case 2: - tglColor(TPixel::Blue); - break; - case 3: - tglColor(TPixel::Cyan); - break; - case 4: - tglColor(TPixel::Magenta); - break; - case 5: - tglColor(TPixel::Yellow); - break; - case 6: - tglColor(TPixel::Black); - break; - default: - tglColor(TPixel::Red); - break; - } - - Index++; - if (rIndex == 2) { - double y = r->getEdge(0)->m_s->getThickPoint((r->getEdge(0)->m_w0 + r->getEdge(0)->m_w1) / 2.0).y; - tglDrawSegment(TPointD(-1000, y), TPointD(1000, y)); - } - - for (int i = 0; i < (int)r->getEdgeCount(); i++) { - TEdge *e = r->getEdge(i); - TPointD p = e->m_s->getPoint(0.8 * e->m_w0 + 0.2 * e->m_w1); - if (i == 0) - tglDrawText(p, (QString::number(rIndex) + QString("-0")).toStdString()); - else - tglDrawText(p, QString::number(i).toStdString()); - if (e->m_index == 3) { - tglColor(TPixel::Black); - TStroke *s = e->m_s; - drawPoint(s->getChunk(0)->getP0(), .3); - tglColor(TPixel::Red); - tglDrawText(s->getChunk(0)->getP0(), QString::number(0).toStdString()); - for (int ii = 0; ii < s->getChunkCount(); ii++) { - drawPoint(s->getChunk(ii)->getP2(), .3); - if (ii < s->getChunkCount() - 1) { - tglColor(TPixel::Red); - tglDrawText(s->getChunk(ii)->getP2(), QString::number(ii + 1).toStdString()); - } - } - } - } - glPopMatrix(); + glPushMatrix(); + tglMultMatrix(rd.m_aff); + switch (Index % 7) { + case 0: + tglColor(TPixel::Red); + break; + case 1: + tglColor(TPixel::Green); + break; + case 2: + tglColor(TPixel::Blue); + break; + case 3: + tglColor(TPixel::Cyan); + break; + case 4: + tglColor(TPixel::Magenta); + break; + case 5: + tglColor(TPixel::Yellow); + break; + case 6: + tglColor(TPixel::Black); + break; + default: + tglColor(TPixel::Red); + break; + } + + Index++; + if (rIndex == 2) { + double y = r->getEdge(0) + ->m_s + ->getThickPoint( + (r->getEdge(0)->m_w0 + r->getEdge(0)->m_w1) / 2.0) + .y; + tglDrawSegment(TPointD(-1000, y), TPointD(1000, y)); + } + + for (int i = 0; i < (int)r->getEdgeCount(); i++) { + TEdge *e = r->getEdge(i); + TPointD p = e->m_s->getPoint(0.8 * e->m_w0 + 0.2 * e->m_w1); + if (i == 0) + tglDrawText(p, + (QString::number(rIndex) + QString("-0")).toStdString()); + else + tglDrawText(p, QString::number(i).toStdString()); + if (e->m_index == 3) { + tglColor(TPixel::Black); + TStroke *s = e->m_s; + drawPoint(s->getChunk(0)->getP0(), .3); + tglColor(TPixel::Red); + tglDrawText(s->getChunk(0)->getP0(), + QString::number(0).toStdString()); + for (int ii = 0; ii < s->getChunkCount(); ii++) { + drawPoint(s->getChunk(ii)->getP2(), .3); + if (ii < s->getChunkCount() - 1) { + tglColor(TPixel::Red); + tglDrawText(s->getChunk(ii)->getP2(), + QString::number(ii + 1).toStdString()); + } + } + } + } + glPopMatrix(); #endif - if (alphaChannel) { - GLboolean red, green, blue, alpha; - tglGetColorMask(red, green, blue, alpha); - - //Draw RGB channels - tglEnableBlending(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glColorMask(red, green, blue, GL_FALSE); - prop->draw(rd); - - //Draw Matte channel - tglEnableBlending(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, alpha); - prop->draw(rd); - - glColorMask(red, green, blue, alpha); - } else { - //pezza: in render, le aree fillate dei custom styles sparivano. - if (!rd.m_isOfflineRender || !rd.m_isImagePattern) - tglRgbOnlyColorMask(); //RGB components only - - prop->draw(rd); - } - - if (pushAttribs) - glPopAttrib(); - } - } - - for (UINT i = 0; i < r->getSubregionCount(); i++) - tglDraw(rd, r->getSubregion(i), pushAttribs); - checkErrorsByGL; + if (alphaChannel) { + GLboolean red, green, blue, alpha; + tglGetColorMask(red, green, blue, alpha); + + // Draw RGB channels + tglEnableBlending(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glColorMask(red, green, blue, GL_FALSE); + prop->draw(rd); + + // Draw Matte channel + tglEnableBlending(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, alpha); + prop->draw(rd); + + glColorMask(red, green, blue, alpha); + } else { + // pezza: in render, le aree fillate dei custom styles sparivano. + if (!rd.m_isOfflineRender || !rd.m_isImagePattern) + tglRgbOnlyColorMask(); // RGB components only + + prop->draw(rd); + } + + if (pushAttribs) glPopAttrib(); + } + } + + for (UINT i = 0; i < r->getSubregionCount(); i++) + tglDraw(rd, r->getSubregion(i), pushAttribs); + checkErrorsByGL; } //----------------------------------------------------------------------------- -void tglDrawMask(const TVectorRenderData &rd1, const TVectorImage *vim) -{ - UINT i; - assert(vim); - if (!vim) - return; - TVectorRenderData rd(rd1); - - glPushAttrib(GL_ALL_ATTRIB_BITS); - - if (!rd.m_palette) { - TPalette *vPalette = vim->getPalette(); - assert(vPalette); - rd.m_palette = vPalette; - } - for (i = 0; i < vim->getRegionCount(); i++) - tglDraw(rd, vim->getRegion(i), false); - - glPopAttrib(); +void tglDrawMask(const TVectorRenderData &rd1, const TVectorImage *vim) { + UINT i; + assert(vim); + if (!vim) return; + TVectorRenderData rd(rd1); + + glPushAttrib(GL_ALL_ATTRIB_BITS); + + if (!rd.m_palette) { + TPalette *vPalette = vim->getPalette(); + assert(vPalette); + rd.m_palette = vPalette; + } + for (i = 0; i < vim->getRegionCount(); i++) + tglDraw(rd, vim->getRegion(i), false); + + glPopAttrib(); } //----------------------------------------------------------------------------- -namespace -{ -bool isOThick(const TStroke *s) -{ - int i; - for (i = 0; i < s->getControlPointCount(); i++) - if (s->getControlPoint(i).thick != 0) - return false; - return true; +namespace { +bool isOThick(const TStroke *s) { + int i; + for (i = 0; i < s->getControlPointCount(); i++) + if (s->getControlPoint(i).thick != 0) return false; + return true; } } -void tglDraw(const TVectorRenderData &rd, const TStroke *s, bool pushAttribs) -{ - assert(s); - if (!s) - return; - - TStrokeProp *prop = 0; - bool pushedAttribs = false; - - try { - TColorStyleP style; - TStroke *stroke = const_cast(s); - if (rd.m_inkCheckEnabled && s->getStyle() == rd.m_colorCheckIndex) { - static TSolidColorStyle *redColor = new TSolidColorStyle(); - redColor->addRef(); - redColor->setMainColor(TPixel::Red); - style = redColor; - } else if (rd.m_tcheckEnabled) { - static TSolidColorStyle *color = new TSolidColorStyle(); - color->addRef(); - color->setMainColor(rd.m_tCheckInk); - style = color; - } else - style = rd.m_palette->getStyle(stroke->getStyle()); - - if (!rd.m_show0ThickStrokes && isOThick(s) && dynamic_cast(style.getPointer()) // This is probably to exclude TCenterlineStrokeStyle-like styles - && !rd.m_tcheckEnabled) // I wonder why this? - return; - - // const TStroke& stroke = *s; //serve??? - - assert(rd.m_palette); - - prop = s->getProp(/*rd.m_palette*/); - /////questo codice stava dentro tstroke::getprop///////// - if (prop) - prop->getMutex()->lock(); - - if (!style->isStrokeStyle() || style->isEnabled() == false) { - if (prop) - prop->getMutex()->unlock(); - - prop = 0; - } else { - //Warning: the following pointers check is conceptually wrong - we - //keep it because the props maintain SMART POINTER-like reference to - //the associated style. This prevents the style from being destroyed - //while still referenced by the prop. - if (!prop || style.getPointer() != prop->getColorStyle()) { - if (prop) - prop->getMutex()->unlock(); - - stroke->setProp(style->makeStrokeProp(stroke)); - prop = stroke->getProp(); - if (prop) - prop->getMutex()->lock(); - } - } - - //--------- draw ------------ - if (!prop) - return; - - if (pushAttribs) - glPushAttrib(GL_ALL_ATTRIB_BITS), pushedAttribs = true; - - bool alphaChannel = rd.m_alphaChannel, antialias = rd.m_antiAliasing; - TVectorImagePatternStrokeProp *aux = dynamic_cast(prop); - if (aux) //gli image pattern vettoriali tornano in questa funzione....non facendo il corpo dell'else'si evita di disegnarli due volte! - prop->draw(rd); - else { - if (antialias) - tglEnableLineSmooth(true); - else - tglEnableLineSmooth(false); - - if (alphaChannel) { - GLboolean red, green, blue, alpha; - tglGetColorMask(red, green, blue, alpha); - - //Draw RGB channels - tglEnableBlending(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glColorMask(red, green, blue, GL_FALSE); - prop->draw(rd); - - //Draw Matte channel - tglEnableBlending(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, alpha); - prop->draw(rd); - - glColorMask(red, green, blue, alpha); - } else { - tglEnableBlending(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - prop->draw(rd); - } - } - - if (pushAttribs) - glPopAttrib(), pushedAttribs = false; - - prop->getMutex()->unlock(); - //--------------------- - } catch (...) { - if (prop) - prop->getMutex()->unlock(); - if (pushedAttribs) - glPopAttrib(); - } +void tglDraw(const TVectorRenderData &rd, const TStroke *s, bool pushAttribs) { + assert(s); + if (!s) return; + + TStrokeProp *prop = 0; + bool pushedAttribs = false; + + try { + TColorStyleP style; + TStroke *stroke = const_cast(s); + if (rd.m_inkCheckEnabled && s->getStyle() == rd.m_colorCheckIndex) { + static TSolidColorStyle *redColor = new TSolidColorStyle(); + redColor->addRef(); + redColor->setMainColor(TPixel::Red); + style = redColor; + } else if (rd.m_tcheckEnabled) { + static TSolidColorStyle *color = new TSolidColorStyle(); + color->addRef(); + color->setMainColor(rd.m_tCheckInk); + style = color; + } else + style = rd.m_palette->getStyle(stroke->getStyle()); + + if (!rd.m_show0ThickStrokes && isOThick(s) && + dynamic_cast( + style.getPointer()) // This is probably to exclude + // TCenterlineStrokeStyle-like styles + && !rd.m_tcheckEnabled) // I wonder why this? + return; + + // const TStroke& stroke = *s; //serve??? + + assert(rd.m_palette); + + prop = s->getProp(/*rd.m_palette*/); + /////questo codice stava dentro tstroke::getprop///////// + if (prop) prop->getMutex()->lock(); + + if (!style->isStrokeStyle() || style->isEnabled() == false) { + if (prop) prop->getMutex()->unlock(); + + prop = 0; + } else { + // Warning: the following pointers check is conceptually wrong - we + // keep it because the props maintain SMART POINTER-like reference to + // the associated style. This prevents the style from being destroyed + // while still referenced by the prop. + if (!prop || style.getPointer() != prop->getColorStyle()) { + if (prop) prop->getMutex()->unlock(); + + stroke->setProp(style->makeStrokeProp(stroke)); + prop = stroke->getProp(); + if (prop) prop->getMutex()->lock(); + } + } + + //--------- draw ------------ + if (!prop) return; + + if (pushAttribs) glPushAttrib(GL_ALL_ATTRIB_BITS), pushedAttribs = true; + + bool alphaChannel = rd.m_alphaChannel, antialias = rd.m_antiAliasing; + TVectorImagePatternStrokeProp *aux = + dynamic_cast(prop); + if (aux) // gli image pattern vettoriali tornano in questa funzione....non + // facendo il corpo dell'else'si evita di disegnarli due volte! + prop->draw(rd); + else { + if (antialias) + tglEnableLineSmooth(true); + else + tglEnableLineSmooth(false); + + if (alphaChannel) { + GLboolean red, green, blue, alpha; + tglGetColorMask(red, green, blue, alpha); + + // Draw RGB channels + tglEnableBlending(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glColorMask(red, green, blue, GL_FALSE); + prop->draw(rd); + + // Draw Matte channel + tglEnableBlending(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, alpha); + prop->draw(rd); + + glColorMask(red, green, blue, alpha); + } else { + tglEnableBlending(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + prop->draw(rd); + } + } + + if (pushAttribs) glPopAttrib(), pushedAttribs = false; + + prop->getMutex()->unlock(); + //--------------------- + } catch (...) { + if (prop) prop->getMutex()->unlock(); + if (pushedAttribs) glPopAttrib(); + } } //------------------------------------------------------------------------------------ -void tglDoDraw(const TVectorRenderData &rd, TRegion *r) -{ - bool visible = false; - int colorCount = 0; - if (!r) - return; - - TColorStyleP style = rd.m_palette->getStyle(r->getStyle()); - colorCount = style->getColorParamCount(); - if (colorCount == 0) //for example texture - visible = true; - else { - visible = false; - for (int j = 0; j < colorCount && !visible; j++) { - TPixel32 color = style->getColorParamValue(j); - if (rd.m_cf) - color = (*(rd.m_cf))(color); - if (color.m != 0) - visible = true; - } - } - if (visible) - tglDraw(rd, r, false); - else - for (UINT j = 0; j < r->getSubregionCount(); j++) - tglDraw(rd, r->getSubregion(j), false); +void tglDoDraw(const TVectorRenderData &rd, TRegion *r) { + bool visible = false; + int colorCount = 0; + if (!r) return; + + TColorStyleP style = rd.m_palette->getStyle(r->getStyle()); + colorCount = style->getColorParamCount(); + if (colorCount == 0) // for example texture + visible = true; + else { + visible = false; + for (int j = 0; j < colorCount && !visible; j++) { + TPixel32 color = style->getColorParamValue(j); + if (rd.m_cf) color = (*(rd.m_cf))(color); + if (color.m != 0) visible = true; + } + } + if (visible) + tglDraw(rd, r, false); + else + for (UINT j = 0; j < r->getSubregionCount(); j++) + tglDraw(rd, r->getSubregion(j), false); } //------------------------------------------------------------------------------------ -void tglDoDraw(const TVectorRenderData &rd, const TStroke *s) -{ - bool visible = false; - int colorCount = 0; - - const TPalette *palette = rd.m_palette; - - int styleId = s->getStyle(); - //assert(0<=styleId && styleIdgetStyle(styleId); - assert(style); - colorCount = style->getColorParamCount(); - if (colorCount == 0) - visible = true; - else { - visible = false; - for (int j = 0; j < style->getColorParamCount() && !visible; j++) { - TPixel32 color = style->getColorParamValue(j); - if (rd.m_cf) - color = (*(rd.m_cf))(color); - if (color.m != 0) - visible = true; - } - } +void tglDoDraw(const TVectorRenderData &rd, const TStroke *s) { + bool visible = false; + int colorCount = 0; + + const TPalette *palette = rd.m_palette; + + int styleId = s->getStyle(); + // assert(0<=styleId && styleIdgetStyle(styleId); + assert(style); + colorCount = style->getColorParamCount(); + if (colorCount == 0) + visible = true; + else { + visible = false; + for (int j = 0; j < style->getColorParamCount() && !visible; j++) { + TPixel32 color = style->getColorParamValue(j); + if (rd.m_cf) color = (*(rd.m_cf))(color); + if (color.m != 0) visible = true; + } + } #if DISEGNO_OUTLINE == 0 - if (visible) + if (visible) #endif - tglDraw(rd, s, false); + tglDraw(rd, s, false); #ifdef _DEBUG -//drawControlPoints(rd, vim->getStroke(i), sqrt(tglGetPixelSize2()), true); -//assert(checkQuadraticDistance(vim->getStroke(i),true)); +// drawControlPoints(rd, vim->getStroke(i), sqrt(tglGetPixelSize2()), true); +// assert(checkQuadraticDistance(vim->getStroke(i),true)); #endif } //------------------------------------------------------------------------------------ -namespace -{ +namespace { -void doDraw(const TVectorImage *vim, const TVectorRenderData &_rd, bool drawEnteredGroup) -{ - static TOnionFader *fade = new TOnionFader(TPixel::White, 0.5); - - TVectorRenderData rd(_rd); - - if (!rd.m_palette) { - TPalette *vPalette = vim->getPalette(); - rd.m_palette = vPalette; - if (!vPalette) - return; - } - - if (!drawEnteredGroup && !rd.m_isIcon && vim->isInsideGroup() > 0) - rd.m_cf = fade; - - TVectorRenderData rdRegions = rd; - - /*if (rd.m_drawRegions && rd.m_isImagePattern)//gli image pattern hanno bisogno dell'antialiasig per le linee, ma sulle aree ci sarebbero un sacco di assert - rdRegions.m_alphaChannel = rdRegions.m_antiAliasing = false;*/ - UINT strokeIndex = 0; - Index = 0; - - while (strokeIndex < vim->getStrokeCount()) // ogni ciclo di while disegna un gruppo - { - int currStrokeIndex = strokeIndex; - if (!rd.m_isIcon && vim->isInsideGroup() > 0 && - ((drawEnteredGroup && !vim->isEnteredGroupStroke(strokeIndex)) || - !drawEnteredGroup && vim->isEnteredGroupStroke(strokeIndex))) { - while (strokeIndex < vim->getStrokeCount() && vim->sameGroup(strokeIndex, currStrokeIndex)) - strokeIndex++; - continue; - } - - if (rd.m_drawRegions) - for (UINT regionIndex = 0; regionIndex < vim->getRegionCount(); regionIndex++) - if (vim->sameGroupStrokeAndRegion(currStrokeIndex, regionIndex)) - tglDoDraw(rdRegions, vim->getRegion(regionIndex)); - while (strokeIndex < vim->getStrokeCount() && vim->sameGroup(strokeIndex, currStrokeIndex)) { +void doDraw(const TVectorImage *vim, const TVectorRenderData &_rd, + bool drawEnteredGroup) { + static TOnionFader *fade = new TOnionFader(TPixel::White, 0.5); + + TVectorRenderData rd(_rd); + + if (!rd.m_palette) { + TPalette *vPalette = vim->getPalette(); + rd.m_palette = vPalette; + if (!vPalette) return; + } + + if (!drawEnteredGroup && !rd.m_isIcon && vim->isInsideGroup() > 0) + rd.m_cf = fade; + + TVectorRenderData rdRegions = rd; + + /*if (rd.m_drawRegions && rd.m_isImagePattern)//gli image pattern hanno +bisogno dell'antialiasig per le linee, ma sulle aree ci sarebbero un sacco di +assert +rdRegions.m_alphaChannel = rdRegions.m_antiAliasing = false;*/ + UINT strokeIndex = 0; + Index = 0; + + while (strokeIndex < + vim->getStrokeCount()) // ogni ciclo di while disegna un gruppo + { + int currStrokeIndex = strokeIndex; + if (!rd.m_isIcon && vim->isInsideGroup() > 0 && + ((drawEnteredGroup && !vim->isEnteredGroupStroke(strokeIndex)) || + !drawEnteredGroup && vim->isEnteredGroupStroke(strokeIndex))) { + while (strokeIndex < vim->getStrokeCount() && + vim->sameGroup(strokeIndex, currStrokeIndex)) + strokeIndex++; + continue; + } + + if (rd.m_drawRegions) + for (UINT regionIndex = 0; regionIndex < vim->getRegionCount(); + regionIndex++) + if (vim->sameGroupStrokeAndRegion(currStrokeIndex, regionIndex)) + tglDoDraw(rdRegions, vim->getRegion(regionIndex)); + while (strokeIndex < vim->getStrokeCount() && + vim->sameGroup(strokeIndex, currStrokeIndex)) { #if DISEGNO_OUTLINE == 1 - CurrStrokeIndex = strokeIndex; - CurrVimg = vim; + CurrStrokeIndex = strokeIndex; + CurrVimg = vim; #endif - tglDoDraw(rd, vim->getStroke(strokeIndex)); - strokeIndex++; - } - } + tglDoDraw(rd, vim->getStroke(strokeIndex)); + strokeIndex++; + } + } } } //------------------------------------------------------------------------------------ -void tglDraw(const TVectorRenderData &rd, const TVectorImage *vim) -{ - assert(vim); - if (!vim) - return; +void tglDraw(const TVectorRenderData &rd, const TVectorImage *vim) { + assert(vim); + if (!vim) return; - QMutexLocker sl(vim->getMutex()); + QMutexLocker sl(vim->getMutex()); - checkErrorsByGL; - checkErrorsByGL; + checkErrorsByGL; + checkErrorsByGL; - glPushAttrib(GL_ALL_ATTRIB_BITS); + glPushAttrib(GL_ALL_ATTRIB_BITS); - //if(!rd.m_palette) rd.m_palette = vim->getPalette(); - //mylog("tglDraw start; mutex=" + toString((unsigned long)&vim->getMutex())); + // if(!rd.m_palette) rd.m_palette = vim->getPalette(); + // mylog("tglDraw start; mutex=" + toString((unsigned long)&vim->getMutex())); - glEnable(GL_ALPHA_TEST); - glAlphaFunc(GL_GREATER, 0); + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GREATER, 0); - doDraw(vim, rd, false); - if (!rd.m_isIcon && vim->isInsideGroup() > 0) - doDraw(vim, rd, true); + doDraw(vim, rd, false); + if (!rd.m_isIcon && vim->isInsideGroup() > 0) doDraw(vim, rd, true); - glDisable(GL_ALPHA_TEST); + glDisable(GL_ALPHA_TEST); - glPopAttrib(); + glPopAttrib(); #ifdef _DEBUG - vim->drawAutocloses(rd); + vim->drawAutocloses(rd); #endif - checkErrorsByGL; - //mylog("tglDraw stop"); + checkErrorsByGL; + // mylog("tglDraw stop"); } //----------------------------------------------------------------------------- diff --git a/toonz/sources/common/tvrender/tinbetween.cpp b/toonz/sources/common/tvrender/tinbetween.cpp index d6443ad..2849912 100644 --- a/toonz/sources/common/tvrender/tinbetween.cpp +++ b/toonz/sources/common/tvrender/tinbetween.cpp @@ -18,1499 +18,1538 @@ //#include "tdebugmessage.h" //-------------------------------------------------------------------------------------- -double average(std::vector &values, double range = 2.5) -{ - UINT size = values.size(); - if (size == 0) - return std::numeric_limits::signaling_NaN(); - - if (size == 1) - return values[0]; - - double sum = 0; - UINT j = 0; - for (; j < size; j++) { - sum += values[j]; - } - - double average = sum / size; - - double variance = 0; - for (j = 0; j < size; j++) { - variance += (average - values[j]) * (average - values[j]); - } - variance /= size; - - double err; - int acceptedNum = 0; - sum = 0; - for (j = 0; j < size; j++) { - err = values[j] - average; - err *= err; - if (err <= range * variance) { - sum += values[j]; - acceptedNum++; - } - } - - assert(acceptedNum > 0); - return (acceptedNum > 0) ? sum / (double)acceptedNum : average; +double average(std::vector &values, double range = 2.5) { + UINT size = values.size(); + if (size == 0) return std::numeric_limits::signaling_NaN(); + + if (size == 1) return values[0]; + + double sum = 0; + UINT j = 0; + for (; j < size; j++) { + sum += values[j]; + } + + double average = sum / size; + + double variance = 0; + for (j = 0; j < size; j++) { + variance += (average - values[j]) * (average - values[j]); + } + variance /= size; + + double err; + int acceptedNum = 0; + sum = 0; + for (j = 0; j < size; j++) { + err = values[j] - average; + err *= err; + if (err <= range * variance) { + sum += values[j]; + acceptedNum++; + } + } + + assert(acceptedNum > 0); + return (acceptedNum > 0) ? sum / (double)acceptedNum : average; } //-------------------------------------------------------------------------------------- -double weightedAverage(std::vector &values, std::vector &weights, double range = 2.5) -{ - UINT size = values.size(); - if (size == 0) - return std::numeric_limits::signaling_NaN(); - - double sum = 0; - double totalWeight = 0; - UINT j = 0; - for (; j < size; j++) { - sum += weights[j] * values[j]; - totalWeight += weights[j]; - } - - assert(totalWeight > 0); - if (totalWeight == 0) - return std::numeric_limits::signaling_NaN(); - - double average = sum / totalWeight; - - double variance = 0; - for (j = 0; j < size; j++) { - variance += weights[j] * (average - values[j]) * (average - values[j]); - } - variance /= totalWeight; - - double err; - totalWeight = 0; - sum = 0; - for (j = 0; j < size; j++) { - err = values[j] - average; - err *= err; - if (err <= range * variance) { - sum += weights[j] * values[j]; - totalWeight += weights[j]; - } - } - - assert(totalWeight > 0); - return (totalWeight != 0) ? sum / totalWeight : average; +double weightedAverage(std::vector &values, + std::vector &weights, double range = 2.5) { + UINT size = values.size(); + if (size == 0) return std::numeric_limits::signaling_NaN(); + + double sum = 0; + double totalWeight = 0; + UINT j = 0; + for (; j < size; j++) { + sum += weights[j] * values[j]; + totalWeight += weights[j]; + } + + assert(totalWeight > 0); + if (totalWeight == 0) return std::numeric_limits::signaling_NaN(); + + double average = sum / totalWeight; + + double variance = 0; + for (j = 0; j < size; j++) { + variance += weights[j] * (average - values[j]) * (average - values[j]); + } + variance /= totalWeight; + + double err; + totalWeight = 0; + sum = 0; + for (j = 0; j < size; j++) { + err = values[j] - average; + err *= err; + if (err <= range * variance) { + sum += weights[j] * values[j]; + totalWeight += weights[j]; + } + } + + assert(totalWeight > 0); + return (totalWeight != 0) ? sum / totalWeight : average; } //-------------------------------------------------------------------------------------- -inline UINT angleNumber(const std::vector> &corners, double angle) -{ - UINT count = 0; - UINT size = corners.size(); - for (UINT j = 0; j < size; j++) - if (corners[j].second >= angle) - count++; +inline UINT angleNumber(const std::vector> &corners, + double angle) { + UINT count = 0; + UINT size = corners.size(); + for (UINT j = 0; j < size; j++) + if (corners[j].second >= angle) count++; - return count; + return count; } //-------------------------------------------------------------------------------------- -inline bool isTooComplex(UINT n1, UINT n2, UINT maxSubsetNumber = 100) -{ - UINT n, r; - if (n1 > n2) { - n = n1; - r = n2; - } else if (n1 < n2) { - n = n2; - r = n1; - } else { - assert(!"equal angle number"); - return false; - } +inline bool isTooComplex(UINT n1, UINT n2, UINT maxSubsetNumber = 100) { + UINT n, r; + if (n1 > n2) { + n = n1; + r = n2; + } else if (n1 < n2) { + n = n2; + r = n1; + } else { + assert(!"equal angle number"); + return false; + } - if (n - r < r) - r = n - r; + if (n - r < r) r = n - r; - /* + /* - n*(n-1)* ...(n-r+1) < n^r that must be <= 2^(num bits of UINT)-1 - - s:=sizeof(UINT)*8 - - if - n <= 2^( (s-1)/r) => +n*(n-1)* ...(n-r+1) < n^r that must be <= 2^(num bits of UINT)-1 - log n <= (s-1)/r (the base of log is 2) => +s:=sizeof(UINT)*8 - r*log n <= s-1 => +if +n <= 2^( (s-1)/r) => - log n^r <= log 2^(s-1) => +log n <= (s-1)/r (the base of log is 2) => - n^r <= 2^(s-1) < (2^s)-1 - - */ +r*log n <= s-1 => - const UINT one = 1; - if (n > (one << ((sizeof(UINT) * 8 - 1) / r))) - return true; +log n^r <= log 2^(s-1) => - UINT product1 = n; //product1 = n*(n-1)* ...(n-r+1) - for (UINT i = 1; i < r; i++) - product1 *= --n; +n^r <= 2^(s-1) < (2^s)-1 + +*/ - UINT rFact = r; + const UINT one = 1; + if (n > (one << ((sizeof(UINT) * 8 - 1) / r))) return true; - while (r > 1) - rFact *= --r; + UINT product1 = n; // product1 = n*(n-1)* ...(n-r+1) + for (UINT i = 1; i < r; i++) product1 *= --n; - return (product1 / rFact > maxSubsetNumber); - //product1/rFact is number of combination - // ( n ) - // ( r ) + UINT rFact = r; + + while (r > 1) rFact *= --r; + + return (product1 / rFact > maxSubsetNumber); + // product1/rFact is number of combination + // ( n ) + // ( r ) } //-------------------------------------------------------------------------------------- -void eraseSmallAngles(std::vector> &corners, double angle) -{ - std::vector>::iterator it = corners.begin(); - - while (it != corners.end()) { - if ((*it).second < angle) - it = corners.erase(it); - else - ++it; - } +void eraseSmallAngles(std::vector> &corners, + double angle) { + std::vector>::iterator it = corners.begin(); + + while (it != corners.end()) { + if ((*it).second < angle) + it = corners.erase(it); + else + ++it; + } } //-------------------------------------------------------------------------------------- -//output: -// min is the minimum angle greater or equal to minDegree (i.e the minimum angle of the corners) +// output: +// min is the minimum angle greater or equal to minDegree (i.e the minimum angle +// of the corners) // max is tha maximum angle greater or equal to minDegree void detectCorners(const TStroke *stroke, double minDegree, - std::vector> &corners, double &min, double &max) -{ - const double minSin = fabs(sin(minDegree * TConsts::pi_180)); - double angle, vectorialProduct, metaCornerLen, partialLen; - - UINT quadCount1 = stroke->getChunkCount(); - TPointD speed1, speed2; - int j; - - TPointD tan1, tan2; - min = 180; - max = minDegree; - for (j = 1; j < (int)quadCount1; j++) { - speed1 = stroke->getChunk(j - 1)->getSpeed(1); - speed2 = stroke->getChunk(j)->getSpeed(0); - if (!(speed1 == TPointD() || speed2 == TPointD())) { - tan1 = normalize(speed1); - tan2 = normalize(speed2); - - vectorialProduct = fabs(cross(tan1, tan2)); - - if (tan1 * tan2 < 0) { - angle = 180 - asin(tcrop(vectorialProduct, -1.0, 1.0)) * TConsts::invOf_pi_180; - corners.push_back(std::make_pair(j, angle)); - - //------------------------------------------ - // TDebugMessage::getStream()< angle) - min = angle; - if (max < angle) - max = angle; - } else if (vectorialProduct >= minSin) { - angle = asin(tcrop(vectorialProduct, -1.0, 1.0)) * TConsts::invOf_pi_180; - corners.push_back(std::make_pair(j, angle)); - - //------------------------------------------ - // TDebugMessage::getStream()< angle) - min = angle; - if (max < angle) - max = angle; - } - } - } - - const double ratioLen = 2.5; - const double ratioAngle = 0.2; - std::vector>::iterator it = corners.begin(); - - for (j = 1; j < (int)quadCount1; j++) //"meta angoli" ( meta perche' derivabili) - { - if (it != corners.end() && j == (*it).first) { - ++it; - continue; - } - - if (j - 2 >= 0 && (corners.empty() || it == corners.begin() || j - 1 != (*(it - 1)).first) && j + 1 < (int)quadCount1 && (corners.empty() || it == corners.end() || j + 1 != (*it).first)) { - speed1 = stroke->getChunk(j - 2)->getSpeed(1); - speed2 = stroke->getChunk(j + 1)->getSpeed(0); - if (!(speed1 == TPointD() || speed2 == TPointD())) { - tan1 = normalize(speed1); - tan2 = normalize(speed2); - vectorialProduct = fabs(cross(tan1, tan2)); - - if (tan1 * tan2 < 0) { - angle = 180 - asin(tcrop(vectorialProduct, -1.0, 1.0)) * TConsts::invOf_pi_180; - - metaCornerLen = ratioLen * (stroke->getChunk(j - 1)->getLength() + stroke->getChunk(j)->getLength()); - partialLen = 0; - bool goodAngle = false; - - for (int i = j - 3; i >= 0 && (corners.empty() || it == corners.begin() || i + 1 != (*(it - 1)).first); i--) { - tan1 = stroke->getChunk(i)->getSpeed(1); - if (tan1 == TPointD()) - continue; - tan1 = normalize(tan1); - - tan2 = stroke->getChunk(i + 1)->getSpeed(1); - if (tan2 == TPointD()) - continue; - tan2 = normalize(tan2); - - vectorialProduct = fabs(cross(tan1, tan2)); - double nearAngle = asin(tcrop(vectorialProduct, -1.0, 1.0)) * TConsts::invOf_pi_180; - if (tan1 * tan2 < 0) - nearAngle = 180 - nearAngle; - - if (nearAngle > ratioAngle * angle) - break; - - partialLen += stroke->getChunk(i)->getLength(); - if (partialLen > metaCornerLen) { - goodAngle = true; - break; - } - } - if (goodAngle) { - partialLen = 0; - for (int i = j + 2; i + 1 < (int)quadCount1 && (corners.empty() || it == corners.end() || i + 1 != (*it).first); i++) { - tan1 = stroke->getChunk(i)->getSpeed(0); - if (tan1 == TPointD()) - continue; - tan1 = normalize(tan1); - - tan2 = stroke->getChunk(i + 1)->getSpeed(0); - if (tan2 == TPointD()) - continue; - tan2 = normalize(tan2); - - vectorialProduct = fabs(cross(tan1, tan2)); - double nearAngle = asin(tcrop(vectorialProduct, -1.0, 1.0)) * TConsts::invOf_pi_180; - if (tan1 * tan2 < 0) - nearAngle = 180 - nearAngle; - - if (nearAngle > 0.1 * angle) - break; - - partialLen += stroke->getChunk(i)->getLength(); - if (partialLen > metaCornerLen) { - goodAngle = true; - break; - } - } - } - - if (goodAngle) { - //l'angolo viene un po' declassato in quanto meta - it = corners.insert(it, std::make_pair(j, angle * 0.7)) + 1; - if (min > angle) - min = angle; - if (max < angle) - max = angle; - - // TDebugMessage::getStream()<> &corners, double &min, + double &max) { + const double minSin = fabs(sin(minDegree * M_PI_180)); + double angle, vectorialProduct, metaCornerLen, partialLen; + + UINT quadCount1 = stroke->getChunkCount(); + TPointD speed1, speed2; + int j; + + TPointD tan1, tan2; + min = 180; + max = minDegree; + for (j = 1; j < (int)quadCount1; j++) { + speed1 = stroke->getChunk(j - 1)->getSpeed(1); + speed2 = stroke->getChunk(j)->getSpeed(0); + if (!(speed1 == TPointD() || speed2 == TPointD())) { + tan1 = normalize(speed1); + tan2 = normalize(speed2); + + vectorialProduct = fabs(cross(tan1, tan2)); + + if (tan1 * tan2 < 0) { + angle = 180 - asin(tcrop(vectorialProduct, -1.0, 1.0)) * M_180_PI; + corners.push_back(std::make_pair(j, angle)); + + //------------------------------------------ + // TDebugMessage::getStream()< angle) min = angle; + if (max < angle) max = angle; + } else if (vectorialProduct >= minSin) { + angle = asin(tcrop(vectorialProduct, -1.0, 1.0)) * M_180_PI; + corners.push_back(std::make_pair(j, angle)); + + //------------------------------------------ + // TDebugMessage::getStream()< angle) min = angle; + if (max < angle) max = angle; + } + } + } + + const double ratioLen = 2.5; + const double ratioAngle = 0.2; + std::vector>::iterator it = corners.begin(); + + for (j = 1; j < (int)quadCount1; + j++) //"meta angoli" ( meta perche' derivabili) + { + if (it != corners.end() && j == (*it).first) { + ++it; + continue; + } + + if (j - 2 >= 0 && (corners.empty() || it == corners.begin() || + j - 1 != (*(it - 1)).first) && + j + 1 < (int)quadCount1 && + (corners.empty() || it == corners.end() || j + 1 != (*it).first)) { + speed1 = stroke->getChunk(j - 2)->getSpeed(1); + speed2 = stroke->getChunk(j + 1)->getSpeed(0); + if (!(speed1 == TPointD() || speed2 == TPointD())) { + tan1 = normalize(speed1); + tan2 = normalize(speed2); + vectorialProduct = fabs(cross(tan1, tan2)); + + if (tan1 * tan2 < 0) { + angle = 180 - asin(tcrop(vectorialProduct, -1.0, 1.0)) * M_180_PI; + + metaCornerLen = ratioLen * (stroke->getChunk(j - 1)->getLength() + + stroke->getChunk(j)->getLength()); + partialLen = 0; + bool goodAngle = false; + + for (int i = j - 3; + i >= 0 && (corners.empty() || it == corners.begin() || + i + 1 != (*(it - 1)).first); + i--) { + tan1 = stroke->getChunk(i)->getSpeed(1); + if (tan1 == TPointD()) continue; + tan1 = normalize(tan1); + + tan2 = stroke->getChunk(i + 1)->getSpeed(1); + if (tan2 == TPointD()) continue; + tan2 = normalize(tan2); + + vectorialProduct = fabs(cross(tan1, tan2)); + double nearAngle = + asin(tcrop(vectorialProduct, -1.0, 1.0)) * M_180_PI; + if (tan1 * tan2 < 0) nearAngle = 180 - nearAngle; + + if (nearAngle > ratioAngle * angle) break; + + partialLen += stroke->getChunk(i)->getLength(); + if (partialLen > metaCornerLen) { + goodAngle = true; + break; + } + } + if (goodAngle) { + partialLen = 0; + for (int i = j + 2; i + 1 < (int)quadCount1 && + (corners.empty() || it == corners.end() || + i + 1 != (*it).first); + i++) { + tan1 = stroke->getChunk(i)->getSpeed(0); + if (tan1 == TPointD()) continue; + tan1 = normalize(tan1); + + tan2 = stroke->getChunk(i + 1)->getSpeed(0); + if (tan2 == TPointD()) continue; + tan2 = normalize(tan2); + + vectorialProduct = fabs(cross(tan1, tan2)); + double nearAngle = + asin(tcrop(vectorialProduct, -1.0, 1.0)) * M_180_PI; + if (tan1 * tan2 < 0) nearAngle = 180 - nearAngle; + + if (nearAngle > 0.1 * angle) break; + + partialLen += stroke->getChunk(i)->getLength(); + if (partialLen > metaCornerLen) { + goodAngle = true; + break; + } + } + } + + if (goodAngle) { + // l'angolo viene un po' declassato in quanto meta + it = corners.insert(it, std::make_pair(j, angle * 0.7)) + 1; + if (min > angle) min = angle; + if (max < angle) max = angle; + + // TDebugMessage::getStream()< &values) -{ - UINT size = values.size(); - if (size == 0) - return std::numeric_limits::signaling_NaN(); +double variance(std::vector &values) { + UINT size = values.size(); + if (size == 0) return std::numeric_limits::signaling_NaN(); - double sum = 0; - UINT j = 0; - for (; j < size; j++) { - sum += values[j]; - } + double sum = 0; + UINT j = 0; + for (; j < size; j++) { + sum += values[j]; + } - double average = sum / size; + double average = sum / size; - double variance = 0; - for (j = 0; j < size; j++) { - variance += (average - values[j]) * (average - values[j]); - } + double variance = 0; + for (j = 0; j < size; j++) { + variance += (average - values[j]) * (average - values[j]); + } - return variance / size; + return variance / size; } //-------------------------------------------------------------------------------------- void findBestSolution(const TStroke *stroke1, const TStroke *stroke2, - std::pair *partialAngles1, UINT partialAngles1Size, - const std::vector> &angles2, - UINT r, std::list> &partialSolution, - double &bestValue, - std::vector &bestVector) + std::pair *partialAngles1, + UINT partialAngles1Size, + const std::vector> &angles2, + UINT r, + std::list> &partialSolution, + double &bestValue, std::vector &bestVector) { + //------------------------------------------------------------------- + if (r == partialAngles1Size) { + UINT j; + std::vector> angles1; + + std::list>::iterator it = partialSolution.begin(); + + for (; it != partialSolution.end(); ++it) { + angles1.push_back(*it); + } + for (j = 0; j < partialAngles1Size; j++) { + angles1.push_back(partialAngles1[j]); + } + + UINT angles1Size = angles1.size(); + std::vector rationAngles(angles1Size), ratioLength(angles1Size + 1); + std::vector ratioX, ratioY; + + for (j = 0; j < angles1Size; j++) { + rationAngles[j] = fabs(angles1[j].second - angles2[j].second) / + (angles1[j].second + angles2[j].second); + } + + UINT firstQuad1 = 0; + UINT firstQuad2 = 0; + UINT nextQuad1, nextQuad2; + + TRectD bbox1 = stroke1->getBBox(); + TRectD bbox2 = stroke2->getBBox(); + + double app, div; + double invTotalLen1 = stroke1->getLength(); + assert(invTotalLen1 > 0); + invTotalLen1 = 1.0 / invTotalLen1; + + double invTotalLen2 = stroke2->getLength(); + assert(invTotalLen2 > 0); + invTotalLen2 = 1.0 / invTotalLen2; + + for (j = 0; j <= angles1Size; j++) { + if (j < angles1Size) { + nextQuad1 = angles1[j].first; + nextQuad2 = angles2[j].first; + } else { + nextQuad1 = stroke1->getChunkCount(); + nextQuad2 = stroke2->getChunkCount(); + } + + ratioLength[j] = + fabs(stroke1->getLengthAtControlPoint(nextQuad1 * 2) * invTotalLen1 - + stroke2->getLengthAtControlPoint(nextQuad2 * 2) * invTotalLen2); + + TPointD p1(stroke1->getChunk(nextQuad1 - 1)->getP2() - + stroke1->getChunk(firstQuad1)->getP0()); + p1.x = fabs(p1.x); + p1.y = fabs(p1.y); + + TPointD p2(stroke2->getChunk(nextQuad2 - 1)->getP2() - + stroke2->getChunk(firstQuad2)->getP0()); + p2.x = fabs(p2.x); + p2.y = fabs(p2.y); + + app = fabs(bbox1.getLx() * p2.x - bbox2.getLx() * p1.x); + div = (bbox1.getLx() * p2.x + bbox2.getLx() * p1.x); + if (div) ratioX.push_back(app / div); + + app = fabs(bbox1.getLy() * p2.y - bbox2.getLy() * p1.y); + div = (bbox1.getLy() * p2.y + bbox2.getLy() * p1.y); + if (div) ratioY.push_back(app / div); + + firstQuad1 = nextQuad1; + firstQuad2 = nextQuad2; + } + + double varAng, varX, varY, varLen; + + varX = average(ratioX); + varY = average(ratioY); + varLen = average(ratioLength); + varAng = average(rationAngles); + + double estimate = varX + varY + varAng + varLen; + /* +#ifdef _DEBUG +for(UINT dI=0; dI> angles1; - - std::list>::iterator it = partialSolution.begin(); - - for (; it != partialSolution.end(); ++it) { - angles1.push_back(*it); - } - for (j = 0; j < partialAngles1Size; j++) { - angles1.push_back(partialAngles1[j]); - } - - UINT angles1Size = angles1.size(); - std::vector rationAngles(angles1Size), ratioLength(angles1Size + 1); - std::vector ratioX, ratioY; - - for (j = 0; j < angles1Size; j++) { - rationAngles[j] = fabs(angles1[j].second - angles2[j].second) / (angles1[j].second + angles2[j].second); - } - - UINT firstQuad1 = 0; - UINT firstQuad2 = 0; - UINT nextQuad1, nextQuad2; - - TRectD bbox1 = stroke1->getBBox(); - TRectD bbox2 = stroke2->getBBox(); - - double app, div; - double invTotalLen1 = stroke1->getLength(); - assert(invTotalLen1 > 0); - invTotalLen1 = 1.0 / invTotalLen1; - - double invTotalLen2 = stroke2->getLength(); - assert(invTotalLen2 > 0); - invTotalLen2 = 1.0 / invTotalLen2; - - for (j = 0; j <= angles1Size; j++) { - - if (j < angles1Size) { - nextQuad1 = angles1[j].first; - nextQuad2 = angles2[j].first; - } else { - nextQuad1 = stroke1->getChunkCount(); - nextQuad2 = stroke2->getChunkCount(); - } - - ratioLength[j] = fabs(stroke1->getLengthAtControlPoint(nextQuad1 * 2) * invTotalLen1 - stroke2->getLengthAtControlPoint(nextQuad2 * 2) * invTotalLen2); - - TPointD p1(stroke1->getChunk(nextQuad1 - 1)->getP2() - - stroke1->getChunk(firstQuad1)->getP0()); - p1.x = fabs(p1.x); - p1.y = fabs(p1.y); - - TPointD p2(stroke2->getChunk(nextQuad2 - 1)->getP2() - - stroke2->getChunk(firstQuad2)->getP0()); - p2.x = fabs(p2.x); - p2.y = fabs(p2.y); - - app = fabs(bbox1.getLx() * p2.x - bbox2.getLx() * p1.x); - div = (bbox1.getLx() * p2.x + bbox2.getLx() * p1.x); - if (div) - ratioX.push_back(app / div); - - app = fabs(bbox1.getLy() * p2.y - bbox2.getLy() * p1.y); - div = (bbox1.getLy() * p2.y + bbox2.getLy() * p1.y); - if (div) - ratioY.push_back(app / div); - - firstQuad1 = nextQuad1; - firstQuad2 = nextQuad2; - } - - double varAng, varX, varY, varLen; - - varX = average(ratioX); - varY = average(ratioY); - varLen = average(ratioLength); - varAng = average(rationAngles); - - double estimate = varX + varY + varAng + varLen; - /* - #ifdef _DEBUG - for(UINT dI=0; dI> &angles1, - const std::vector> &angles2, - double &bestValue, - std::vector &bestVector) -{ - assert(angles1.size() > angles2.size()); + std::vector> &angles1, + const std::vector> &angles2, + double &bestValue, std::vector &bestVector) { + assert(angles1.size() > angles2.size()); - std::list> partialSolution; + std::list> partialSolution; - findBestSolution(stroke1, stroke2, - &(angles1[0]), angles1.size(), - angles2, - angles2.size(), partialSolution, - bestValue, bestVector); + findBestSolution(stroke1, stroke2, &(angles1[0]), angles1.size(), angles2, + angles2.size(), partialSolution, bestValue, bestVector); } //-------------------------------------------------------------------------------------- void trivialSolution(const TStroke *stroke1, const TStroke *stroke2, - const std::vector> &angles1, - const std::vector> &angles2, - std::vector &solution) -{ - assert(angles1.size() > angles2.size()); - - UINT j; - double subStrokeRatio2; - - double invTotalLen2 = stroke2->getLength(); - assert(invTotalLen2); - invTotalLen2 = 1.0 / invTotalLen2; - - double invTotalLen1 = stroke1->getLength(); - assert(invTotalLen1 > 0); - invTotalLen1 = 1.0 / invTotalLen1; - - if (solution.size() != angles2.size()) { - assert(!"bad size for solution"); - solution.resize(angles2.size()); - } - - int toBeErased = angles1.size() - angles2.size(); - UINT count = 0; - - double diff, ratio, oldRatio = 100; - - subStrokeRatio2 = stroke2->getLengthAtControlPoint(angles2[count].first * 2) * invTotalLen2; - - for (j = 0; j < angles1.size() && count < solution.size(); j++) { - if (toBeErased == 0) { - solution[count++] = angles1[j].first; - } else { - ratio = stroke1->getLengthAtControlPoint(angles1[j].first * 2) * invTotalLen1; - assert(ratio > 0 && ratio <= 1); - - diff = ratio - subStrokeRatio2; - if (diff >= 0) { - if (fabs(diff) < fabs(oldRatio - subStrokeRatio2)) { - solution[count] = angles1[j].first; - oldRatio = 100; - } else { - assert(j > 0); - solution[count] = angles1[j - 1].first; - } - count++; - if (angles2.size() < count) - subStrokeRatio2 = stroke2->getLengthAtControlPoint(angles2[count].first * 2) * invTotalLen2; - else - subStrokeRatio2 = 1; - } else { - toBeErased--; - oldRatio = ratio; - } - } - } - assert(count == solution.size()); + const std::vector> &angles1, + const std::vector> &angles2, + std::vector &solution) { + assert(angles1.size() > angles2.size()); + + UINT j; + double subStrokeRatio2; + + double invTotalLen2 = stroke2->getLength(); + assert(invTotalLen2); + invTotalLen2 = 1.0 / invTotalLen2; + + double invTotalLen1 = stroke1->getLength(); + assert(invTotalLen1 > 0); + invTotalLen1 = 1.0 / invTotalLen1; + + if (solution.size() != angles2.size()) { + assert(!"bad size for solution"); + solution.resize(angles2.size()); + } + + int toBeErased = angles1.size() - angles2.size(); + UINT count = 0; + + double diff, ratio, oldRatio = 100; + + subStrokeRatio2 = + stroke2->getLengthAtControlPoint(angles2[count].first * 2) * invTotalLen2; + + for (j = 0; j < angles1.size() && count < solution.size(); j++) { + if (toBeErased == 0) { + solution[count++] = angles1[j].first; + } else { + ratio = + stroke1->getLengthAtControlPoint(angles1[j].first * 2) * invTotalLen1; + assert(ratio > 0 && ratio <= 1); + + diff = ratio - subStrokeRatio2; + if (diff >= 0) { + if (fabs(diff) < fabs(oldRatio - subStrokeRatio2)) { + solution[count] = angles1[j].first; + oldRatio = 100; + } else { + assert(j > 0); + solution[count] = angles1[j - 1].first; + } + count++; + if (angles2.size() < count) + subStrokeRatio2 = + stroke2->getLengthAtControlPoint(angles2[count].first * 2) * + invTotalLen2; + else + subStrokeRatio2 = 1; + } else { + toBeErased--; + oldRatio = ratio; + } + } + } + assert(count == solution.size()); } //-------------------------------------------------------------------------------------- -TStroke *extract(const TStroke *source, UINT firstQuad, UINT lastQuad) -{ - UINT quadCount = source->getChunkCount(); - if (firstQuad >= quadCount) { - assert(!"bad quadric index"); - firstQuad = quadCount - 1; - } - if (lastQuad < firstQuad) { - assert(!"bad quadric index"); - lastQuad = firstQuad; - } - if (lastQuad >= quadCount) { - assert(!"bad quadric index"); - lastQuad = quadCount - 1; - } - - UINT cpIndex0 = firstQuad * 2; - UINT cpIndex1 = lastQuad * 2 + 2; - - std::vector points(cpIndex1 - cpIndex0 + 1); - UINT count = 0; - for (UINT j = cpIndex0; j <= cpIndex1; j++) { - points[count++] = source->getControlPoint(j); - } - - return new TStroke(points); +TStroke *extract(const TStroke *source, UINT firstQuad, UINT lastQuad) { + UINT quadCount = source->getChunkCount(); + if (firstQuad >= quadCount) { + assert(!"bad quadric index"); + firstQuad = quadCount - 1; + } + if (lastQuad < firstQuad) { + assert(!"bad quadric index"); + lastQuad = firstQuad; + } + if (lastQuad >= quadCount) { + assert(!"bad quadric index"); + lastQuad = quadCount - 1; + } + + UINT cpIndex0 = firstQuad * 2; + UINT cpIndex1 = lastQuad * 2 + 2; + + std::vector points(cpIndex1 - cpIndex0 + 1); + UINT count = 0; + for (UINT j = cpIndex0; j <= cpIndex1; j++) { + points[count++] = source->getControlPoint(j); + } + + return new TStroke(points); } //-------------------------------------------------------------------------------------- -void sample(const TStroke *stroke, int samplingSize, std::vector &sampledPoint) -{ - double samplingFrequency = 1.0 / (double)samplingSize; - sampledPoint.resize(samplingSize); - - double totalLen = stroke->getLength(); - double step = totalLen * samplingFrequency; - double len = 0; - - for (int p = 0; p < samplingSize - 1; p++) { - sampledPoint[p] = stroke->getPointAtLength(len); - len += step; - } - sampledPoint.back() = stroke->getControlPoint(stroke->getControlPointCount() - 1); +void sample(const TStroke *stroke, int samplingSize, + std::vector &sampledPoint) { + double samplingFrequency = 1.0 / (double)samplingSize; + sampledPoint.resize(samplingSize); + + double totalLen = stroke->getLength(); + double step = totalLen * samplingFrequency; + double len = 0; + + for (int p = 0; p < samplingSize - 1; p++) { + sampledPoint[p] = stroke->getPointAtLength(len); + len += step; + } + sampledPoint.back() = + stroke->getControlPoint(stroke->getControlPointCount() - 1); } //-------------------------------------------------------------------------------------- -class TInbetween::Imp -{ - +class TInbetween::Imp { public: - //---------------------- + //---------------------- - struct StrokeTransform { - typedef enum { - EQUAL, - POINT, - GENERAL - } TransformationType; + struct StrokeTransform { + typedef enum { EQUAL, POINT, GENERAL } TransformationType; - TPointD m_translate; - TPointD m_rotationAndScaleCenter; - double m_scaleX, m_scaleY, m_rotation; + TPointD m_translate; + TPointD m_rotationAndScaleCenter; + double m_scaleX, m_scaleY, m_rotation; - TransformationType m_type; + TransformationType m_type; - //saved for optimization - TAffine m_inverse; + // saved for optimization + TAffine m_inverse; - std::vector m_firstStrokeCornerIndexes; - std::vector m_secondStrokeCornerIndexes; - }; + std::vector m_firstStrokeCornerIndexes; + std::vector m_secondStrokeCornerIndexes; + }; - //---------------------- + //---------------------- - TVectorImageP m_firstImage, m_lastImage; + TVectorImageP m_firstImage, m_lastImage; - std::vector m_transformation; + std::vector m_transformation; - void computeTransformation(); + void computeTransformation(); - void transferColor(const TVectorImageP &destination) const; + void transferColor(const TVectorImageP &destination) const; - TVectorImageP tween(double t) const; + TVectorImageP tween(double t) const; - Imp(const TVectorImageP firstImage, const TVectorImageP lastImage) - : m_firstImage(firstImage), m_lastImage(lastImage) - { - computeTransformation(); - } + Imp(const TVectorImageP firstImage, const TVectorImageP lastImage) + : m_firstImage(firstImage), m_lastImage(lastImage) { + computeTransformation(); + } }; //------------------------------------------------------------------- -TInbetween::TInbetween(const TVectorImageP firstImage, const TVectorImageP lastImage) - : m_imp(new TInbetween::Imp(firstImage, lastImage)) -{ -} +TInbetween::TInbetween(const TVectorImageP firstImage, + const TVectorImageP lastImage) + : m_imp(new TInbetween::Imp(firstImage, lastImage)) {} //------------------------------------------------------------------- -TInbetween::~TInbetween() -{ -} +TInbetween::~TInbetween() {} //------------------------------------------------------------------- -void TInbetween::Imp::computeTransformation() -{ - const UINT samplingPointNumber = 10; - const UINT bboxSamplingWeight = samplingPointNumber / 2; - - StrokeTransform transform; - double cs, sn, totalLen1, totalLen2, constK, constQ, constB, constD, constA; - UINT cpCount1, cpCount2; - TPointD stroke1Centroid, stroke2Centroid, stroke1Begin, stroke2Begin, stroke1End, stroke2End, versor1, versor2; - std::vector samplingPoint1(samplingPointNumber), samplingPoint2(samplingPointNumber); - TStroke *stroke1, *stroke2; - std::vector ratioSampling, weigths, subStrokeXScaling, subStrokeYScaling; - - UINT strokeCount1 = m_firstImage->getStrokeCount(); - UINT strokeCount2 = m_lastImage->getStrokeCount(); - if (strokeCount1 > strokeCount2) - strokeCount1 = strokeCount2; - - m_transformation.clear(); - m_transformation.reserve(strokeCount1); - - const int maxSubSetNum = (strokeCount1) ? 1000 / strokeCount1 : 1; - - UINT j, p; - - for (UINT i = 0; i < strokeCount1; i++) { - stroke1 = m_firstImage->getStroke(i); - stroke2 = m_lastImage->getStroke(i); - - //check if the strokes are equal - cpCount1 = stroke1->getControlPointCount(); - cpCount2 = stroke2->getControlPointCount(); - - transform.m_firstStrokeCornerIndexes.clear(); - transform.m_secondStrokeCornerIndexes.clear(); - transform.m_translate = TPointD(); - transform.m_rotationAndScaleCenter = TPointD(); - transform.m_scaleX = 0; - transform.m_scaleY = 0; - transform.m_rotation = 0; - - bool isEqual = true; - - if (cpCount1 == cpCount2) { - for (j = 0; j < cpCount1 && isEqual; j++) { - isEqual = (stroke1->getControlPoint(j) == stroke2->getControlPoint(j)); - } - } else - isEqual = false; - - if (isEqual) { - transform.m_type = StrokeTransform::EQUAL; - } else { - totalLen1 = stroke1->getLength(); - totalLen2 = stroke2->getLength(); - - if (totalLen1 == 0 || totalLen2 == 0) { - if (totalLen1 == 0 && totalLen2 == 0) { - transform.m_type = StrokeTransform::POINT; - } else { - transform.m_inverse = TAffine(); - transform.m_firstStrokeCornerIndexes.resize(2); - transform.m_firstStrokeCornerIndexes[0] = 0; - transform.m_firstStrokeCornerIndexes[1] = stroke1->getChunkCount(); - transform.m_secondStrokeCornerIndexes.resize(2); - transform.m_secondStrokeCornerIndexes[0] = 0; - transform.m_secondStrokeCornerIndexes[1] = stroke2->getChunkCount(); - } - } else { - - const double startMinAngle = 30.0; - std::vector> angles1, angles2; - - transform.m_type = StrokeTransform::GENERAL; - - double minAngle, maxAngle; - int minAngle1, maxAngle1, minAngle2, maxAngle2; - - angles1.clear(); - angles2.clear(); - - // TDebugMessage::getStream()<::max)(); - - if (angles1.size() != angles2.size()) { - bestValue = (std::numeric_limits::max)(); - - //-------------------------------------------------------------------------- - - if (isTooComplex(angles1.size(), angles2.size(), maxSubSetNum)) { - //debugStream <<"is too complex" << endl; - int firstAngle = (int)((angles1.size() < angles2.size()) ? minAngle2 : minAngle1); - int lastAngle = (int)((angles1.size() < angles2.size()) ? maxAngle1 : maxAngle2); - int bestAngle = (int)startMinAngle; - - if ((int)(angles1.size() + angles2.size()) < lastAngle - firstAngle + 1) { - double tempAngle; - std::vector sortedAngles1, sortedAngles2; - sortedAngles1.reserve(angles1.size()); - sortedAngles2.reserve(angles2.size()); - for (j = 0; j < angles1.size(); j++) { - tempAngle = angles1[j].second; - if (tempAngle >= firstAngle && tempAngle <= lastAngle) - sortedAngles1.push_back(tempAngle); - } - for (j = 0; j < angles2.size(); j++) { - tempAngle = angles2[j].second; - if (tempAngle >= firstAngle && tempAngle <= lastAngle) - sortedAngles2.push_back(tempAngle); - } - std::vector sortedAngles(sortedAngles1.size() + sortedAngles2.size()); - - std::sort(sortedAngles1.begin(), sortedAngles1.end()); - std::sort(sortedAngles2.begin(), sortedAngles2.end()); - std::merge(sortedAngles1.begin(), sortedAngles1.end(), sortedAngles2.begin(), sortedAngles2.end(), sortedAngles.begin()); - - for (j = 0; j < sortedAngles.size(); j++) { - int numAng1 = angleNumber(angles1, sortedAngles[j]); - int numAng2 = angleNumber(angles2, sortedAngles[j]); - double val = (numAng1 == numAng2) ? 0 : fabs((float)(numAng1 - numAng2)) / (numAng1 + numAng2); - if (val < bestValue) { - bestValue = val; - bestAngle = (int)(sortedAngles[j]); - if (bestValue == 0 || !isTooComplex(numAng1, numAng2, maxSubSetNum)) - break; - } - } - - } else //----------------------------------------------------- - { - for (int angle = firstAngle; angle <= lastAngle; angle++) { - int numAng1 = angleNumber(angles1, angle); - int numAng2 = angleNumber(angles2, angle); - double val = (numAng1 == numAng2) ? 0 : fabs((float)(numAng1 - numAng2)) / (numAng1 + numAng2); - if (val < bestValue) { - bestValue = val; - bestAngle = angle; - if (bestValue == 0 || !isTooComplex(numAng1, numAng2, maxSubSetNum)) - break; - } - } - } - - eraseSmallAngles(angles1, bestAngle); - eraseSmallAngles(angles2, bestAngle); - - /* - debugStream <<"bestAngle: "<< bestAngle << endl; - debugStream <<"num angoli 1: "<< angles1.size() << endl; - debugStream <<"num angoli 2: "<< angles2.size() << endl; - */ - } - //-------------------------------------------------------------------------- - - bestValue = (std::numeric_limits::max)(); - - if (angles1.size() == angles2.size()) { - transform.m_firstStrokeCornerIndexes.push_back(0); - for (j = 0; j < angles1.size(); j++) - transform.m_firstStrokeCornerIndexes.push_back(angles1[j].first); - transform.m_firstStrokeCornerIndexes.push_back(stroke1->getChunkCount()); - - transform.m_secondStrokeCornerIndexes.push_back(0); - for (j = 0; j < angles2.size(); j++) - transform.m_secondStrokeCornerIndexes.push_back(angles2[j].first); - transform.m_secondStrokeCornerIndexes.push_back(stroke2->getChunkCount()); - } else { - if (isTooComplex(angles1.size(), angles2.size(), maxSubSetNum)) { - if (angles1.size() > angles2.size()) { - transform.m_firstStrokeCornerIndexes.resize(angles2.size()); - trivialSolution(stroke1, stroke2, angles1, angles2, transform.m_firstStrokeCornerIndexes); - transform.m_firstStrokeCornerIndexes.insert(transform.m_firstStrokeCornerIndexes.begin(), 0); - transform.m_firstStrokeCornerIndexes.push_back(stroke1->getChunkCount()); - - transform.m_secondStrokeCornerIndexes.push_back(0); - for (j = 0; j < angles2.size(); j++) - transform.m_secondStrokeCornerIndexes.push_back(angles2[j].first); - transform.m_secondStrokeCornerIndexes.push_back(stroke2->getChunkCount()); - } else { - transform.m_firstStrokeCornerIndexes.push_back(0); - for (j = 0; j < angles1.size(); j++) - transform.m_firstStrokeCornerIndexes.push_back(angles1[j].first); - transform.m_firstStrokeCornerIndexes.push_back(stroke1->getChunkCount()); - - transform.m_secondStrokeCornerIndexes.resize(angles1.size()); - trivialSolution(stroke2, stroke1, angles2, angles1, transform.m_secondStrokeCornerIndexes); - transform.m_secondStrokeCornerIndexes.insert(transform.m_secondStrokeCornerIndexes.begin(), 0); - transform.m_secondStrokeCornerIndexes.push_back(stroke2->getChunkCount()); - } - } else { - if (angles1.size() > angles2.size()) { - transform.m_firstStrokeCornerIndexes.resize(angles2.size()); - findBestSolution(stroke1, stroke2, angles1, angles2, bestValue, transform.m_firstStrokeCornerIndexes); - transform.m_firstStrokeCornerIndexes.insert(transform.m_firstStrokeCornerIndexes.begin(), 0); - transform.m_firstStrokeCornerIndexes.push_back(stroke1->getChunkCount()); - - transform.m_secondStrokeCornerIndexes.push_back(0); - for (j = 0; j < angles2.size(); j++) - transform.m_secondStrokeCornerIndexes.push_back(angles2[j].first); - transform.m_secondStrokeCornerIndexes.push_back(stroke2->getChunkCount()); - } else { - transform.m_firstStrokeCornerIndexes.push_back(0); - for (j = 0; j < angles1.size(); j++) - transform.m_firstStrokeCornerIndexes.push_back(angles1[j].first); - transform.m_firstStrokeCornerIndexes.push_back(stroke1->getChunkCount()); - - transform.m_secondStrokeCornerIndexes.resize(angles1.size()); - findBestSolution(stroke2, stroke1, angles2, angles1, bestValue, transform.m_secondStrokeCornerIndexes); - transform.m_secondStrokeCornerIndexes.insert(transform.m_secondStrokeCornerIndexes.begin(), 0); - transform.m_secondStrokeCornerIndexes.push_back(stroke2->getChunkCount()); - } - } - } - } else { - transform.m_firstStrokeCornerIndexes.push_back(0); - for (j = 0; j < angles1.size(); j++) - transform.m_firstStrokeCornerIndexes.push_back(angles1[j].first); - transform.m_firstStrokeCornerIndexes.push_back(stroke1->getChunkCount()); - - transform.m_secondStrokeCornerIndexes.push_back(0); - for (j = 0; j < angles2.size(); j++) - transform.m_secondStrokeCornerIndexes.push_back(angles2[j].first); - transform.m_secondStrokeCornerIndexes.push_back(stroke2->getChunkCount()); - } - - UINT cornerSize = transform.m_firstStrokeCornerIndexes.size(); - assert(cornerSize == transform.m_secondStrokeCornerIndexes.size()); - assert(cornerSize >= 2); - - double totalRadRotation = 0; - - TStroke *subStroke1 = 0; - TStroke *subStroke2 = 0; - - stroke1Centroid = stroke1->getCentroid(); - stroke2Centroid = stroke2->getCentroid(); +void TInbetween::Imp::computeTransformation() { + const UINT samplingPointNumber = 10; + const UINT bboxSamplingWeight = samplingPointNumber / 2; + + StrokeTransform transform; + double cs, sn, totalLen1, totalLen2, constK, constQ, constB, constD, constA; + UINT cpCount1, cpCount2; + TPointD stroke1Centroid, stroke2Centroid, stroke1Begin, stroke2Begin, + stroke1End, stroke2End, versor1, versor2; + std::vector samplingPoint1(samplingPointNumber), + samplingPoint2(samplingPointNumber); + TStroke *stroke1, *stroke2; + std::vector ratioSampling, weigths, subStrokeXScaling, + subStrokeYScaling; + + UINT strokeCount1 = m_firstImage->getStrokeCount(); + UINT strokeCount2 = m_lastImage->getStrokeCount(); + if (strokeCount1 > strokeCount2) strokeCount1 = strokeCount2; + + m_transformation.clear(); + m_transformation.reserve(strokeCount1); + + const int maxSubSetNum = (strokeCount1) ? 1000 / strokeCount1 : 1; + + UINT j, p; + + for (UINT i = 0; i < strokeCount1; i++) { + stroke1 = m_firstImage->getStroke(i); + stroke2 = m_lastImage->getStroke(i); + + // check if the strokes are equal + cpCount1 = stroke1->getControlPointCount(); + cpCount2 = stroke2->getControlPointCount(); + + transform.m_firstStrokeCornerIndexes.clear(); + transform.m_secondStrokeCornerIndexes.clear(); + transform.m_translate = TPointD(); + transform.m_rotationAndScaleCenter = TPointD(); + transform.m_scaleX = 0; + transform.m_scaleY = 0; + transform.m_rotation = 0; + + bool isEqual = true; + + if (cpCount1 == cpCount2) { + for (j = 0; j < cpCount1 && isEqual; j++) { + isEqual = (stroke1->getControlPoint(j) == stroke2->getControlPoint(j)); + } + } else + isEqual = false; + + if (isEqual) { + transform.m_type = StrokeTransform::EQUAL; + } else { + totalLen1 = stroke1->getLength(); + totalLen2 = stroke2->getLength(); + + if (totalLen1 == 0 || totalLen2 == 0) { + if (totalLen1 == 0 && totalLen2 == 0) { + transform.m_type = StrokeTransform::POINT; + } else { + transform.m_inverse = TAffine(); + transform.m_firstStrokeCornerIndexes.resize(2); + transform.m_firstStrokeCornerIndexes[0] = 0; + transform.m_firstStrokeCornerIndexes[1] = stroke1->getChunkCount(); + transform.m_secondStrokeCornerIndexes.resize(2); + transform.m_secondStrokeCornerIndexes[0] = 0; + transform.m_secondStrokeCornerIndexes[1] = stroke2->getChunkCount(); + } + } else { + const double startMinAngle = 30.0; + std::vector> angles1, angles2; + + transform.m_type = StrokeTransform::GENERAL; + + double minAngle, maxAngle; + int minAngle1, maxAngle1, minAngle2, maxAngle2; + + angles1.clear(); + angles2.clear(); + + // TDebugMessage::getStream()<::max)(); + + if (angles1.size() != angles2.size()) { + bestValue = (std::numeric_limits::max)(); + + //-------------------------------------------------------------------------- + + if (isTooComplex(angles1.size(), angles2.size(), maxSubSetNum)) { + // debugStream <<"is too complex" << endl; + int firstAngle = + (int)((angles1.size() < angles2.size()) ? minAngle2 + : minAngle1); + int lastAngle = + (int)((angles1.size() < angles2.size()) ? maxAngle1 + : maxAngle2); + int bestAngle = (int)startMinAngle; + + if ((int)(angles1.size() + angles2.size()) < + lastAngle - firstAngle + 1) { + double tempAngle; + std::vector sortedAngles1, sortedAngles2; + sortedAngles1.reserve(angles1.size()); + sortedAngles2.reserve(angles2.size()); + for (j = 0; j < angles1.size(); j++) { + tempAngle = angles1[j].second; + if (tempAngle >= firstAngle && tempAngle <= lastAngle) + sortedAngles1.push_back(tempAngle); + } + for (j = 0; j < angles2.size(); j++) { + tempAngle = angles2[j].second; + if (tempAngle >= firstAngle && tempAngle <= lastAngle) + sortedAngles2.push_back(tempAngle); + } + std::vector sortedAngles(sortedAngles1.size() + + sortedAngles2.size()); + + std::sort(sortedAngles1.begin(), sortedAngles1.end()); + std::sort(sortedAngles2.begin(), sortedAngles2.end()); + std::merge(sortedAngles1.begin(), sortedAngles1.end(), + sortedAngles2.begin(), sortedAngles2.end(), + sortedAngles.begin()); + + for (j = 0; j < sortedAngles.size(); j++) { + int numAng1 = angleNumber(angles1, sortedAngles[j]); + int numAng2 = angleNumber(angles2, sortedAngles[j]); + double val = (numAng1 == numAng2) + ? 0 + : fabs((float)(numAng1 - numAng2)) / + (numAng1 + numAng2); + if (val < bestValue) { + bestValue = val; + bestAngle = (int)(sortedAngles[j]); + if (bestValue == 0 || + !isTooComplex(numAng1, numAng2, maxSubSetNum)) + break; + } + } + + } else //----------------------------------------------------- + { + for (int angle = firstAngle; angle <= lastAngle; angle++) { + int numAng1 = angleNumber(angles1, angle); + int numAng2 = angleNumber(angles2, angle); + double val = (numAng1 == numAng2) + ? 0 + : fabs((float)(numAng1 - numAng2)) / + (numAng1 + numAng2); + if (val < bestValue) { + bestValue = val; + bestAngle = angle; + if (bestValue == 0 || + !isTooComplex(numAng1, numAng2, maxSubSetNum)) + break; + } + } + } + + eraseSmallAngles(angles1, bestAngle); + eraseSmallAngles(angles2, bestAngle); + + /* +debugStream <<"bestAngle: "<< bestAngle << endl; +debugStream <<"num angoli 1: "<< angles1.size() << endl; +debugStream <<"num angoli 2: "<< angles2.size() << endl; +*/ + } + //-------------------------------------------------------------------------- + + bestValue = (std::numeric_limits::max)(); + + if (angles1.size() == angles2.size()) { + transform.m_firstStrokeCornerIndexes.push_back(0); + for (j = 0; j < angles1.size(); j++) + transform.m_firstStrokeCornerIndexes.push_back(angles1[j].first); + transform.m_firstStrokeCornerIndexes.push_back( + stroke1->getChunkCount()); + + transform.m_secondStrokeCornerIndexes.push_back(0); + for (j = 0; j < angles2.size(); j++) + transform.m_secondStrokeCornerIndexes.push_back(angles2[j].first); + transform.m_secondStrokeCornerIndexes.push_back( + stroke2->getChunkCount()); + } else { + if (isTooComplex(angles1.size(), angles2.size(), maxSubSetNum)) { + if (angles1.size() > angles2.size()) { + transform.m_firstStrokeCornerIndexes.resize(angles2.size()); + trivialSolution(stroke1, stroke2, angles1, angles2, + transform.m_firstStrokeCornerIndexes); + transform.m_firstStrokeCornerIndexes.insert( + transform.m_firstStrokeCornerIndexes.begin(), 0); + transform.m_firstStrokeCornerIndexes.push_back( + stroke1->getChunkCount()); + + transform.m_secondStrokeCornerIndexes.push_back(0); + for (j = 0; j < angles2.size(); j++) + transform.m_secondStrokeCornerIndexes.push_back( + angles2[j].first); + transform.m_secondStrokeCornerIndexes.push_back( + stroke2->getChunkCount()); + } else { + transform.m_firstStrokeCornerIndexes.push_back(0); + for (j = 0; j < angles1.size(); j++) + transform.m_firstStrokeCornerIndexes.push_back( + angles1[j].first); + transform.m_firstStrokeCornerIndexes.push_back( + stroke1->getChunkCount()); + + transform.m_secondStrokeCornerIndexes.resize(angles1.size()); + trivialSolution(stroke2, stroke1, angles2, angles1, + transform.m_secondStrokeCornerIndexes); + transform.m_secondStrokeCornerIndexes.insert( + transform.m_secondStrokeCornerIndexes.begin(), 0); + transform.m_secondStrokeCornerIndexes.push_back( + stroke2->getChunkCount()); + } + } else { + if (angles1.size() > angles2.size()) { + transform.m_firstStrokeCornerIndexes.resize(angles2.size()); + findBestSolution(stroke1, stroke2, angles1, angles2, bestValue, + transform.m_firstStrokeCornerIndexes); + transform.m_firstStrokeCornerIndexes.insert( + transform.m_firstStrokeCornerIndexes.begin(), 0); + transform.m_firstStrokeCornerIndexes.push_back( + stroke1->getChunkCount()); + + transform.m_secondStrokeCornerIndexes.push_back(0); + for (j = 0; j < angles2.size(); j++) + transform.m_secondStrokeCornerIndexes.push_back( + angles2[j].first); + transform.m_secondStrokeCornerIndexes.push_back( + stroke2->getChunkCount()); + } else { + transform.m_firstStrokeCornerIndexes.push_back(0); + for (j = 0; j < angles1.size(); j++) + transform.m_firstStrokeCornerIndexes.push_back( + angles1[j].first); + transform.m_firstStrokeCornerIndexes.push_back( + stroke1->getChunkCount()); + + transform.m_secondStrokeCornerIndexes.resize(angles1.size()); + findBestSolution(stroke2, stroke1, angles2, angles1, bestValue, + transform.m_secondStrokeCornerIndexes); + transform.m_secondStrokeCornerIndexes.insert( + transform.m_secondStrokeCornerIndexes.begin(), 0); + transform.m_secondStrokeCornerIndexes.push_back( + stroke2->getChunkCount()); + } + } + } + } else { + transform.m_firstStrokeCornerIndexes.push_back(0); + for (j = 0; j < angles1.size(); j++) + transform.m_firstStrokeCornerIndexes.push_back(angles1[j].first); + transform.m_firstStrokeCornerIndexes.push_back( + stroke1->getChunkCount()); + + transform.m_secondStrokeCornerIndexes.push_back(0); + for (j = 0; j < angles2.size(); j++) + transform.m_secondStrokeCornerIndexes.push_back(angles2[j].first); + transform.m_secondStrokeCornerIndexes.push_back( + stroke2->getChunkCount()); + } + + UINT cornerSize = transform.m_firstStrokeCornerIndexes.size(); + assert(cornerSize == transform.m_secondStrokeCornerIndexes.size()); + assert(cornerSize >= 2); + + double totalRadRotation = 0; + + TStroke *subStroke1 = 0; + TStroke *subStroke2 = 0; + + stroke1Centroid = stroke1->getCentroid(); + stroke2Centroid = stroke2->getCentroid(); #ifdef _DEBUG - assert(transform.m_firstStrokeCornerIndexes[0] == 0); - assert(transform.m_secondStrokeCornerIndexes[0] == 0); - assert(transform.m_firstStrokeCornerIndexes[cornerSize - 1] == stroke1->getChunkCount()); - assert(transform.m_secondStrokeCornerIndexes[cornerSize - 1] == stroke2->getChunkCount()); - for (j = 0; j < cornerSize - 1; j++) { - assert(transform.m_firstStrokeCornerIndexes[j] < transform.m_firstStrokeCornerIndexes[j + 1]); - assert(transform.m_secondStrokeCornerIndexes[j] < transform.m_secondStrokeCornerIndexes[j + 1]); - - assert(transform.m_firstStrokeCornerIndexes[j] < stroke1->getChunkCount()); - assert(transform.m_secondStrokeCornerIndexes[j] < stroke2->getChunkCount()); - } + assert(transform.m_firstStrokeCornerIndexes[0] == 0); + assert(transform.m_secondStrokeCornerIndexes[0] == 0); + assert(transform.m_firstStrokeCornerIndexes[cornerSize - 1] == + stroke1->getChunkCount()); + assert(transform.m_secondStrokeCornerIndexes[cornerSize - 1] == + stroke2->getChunkCount()); + for (j = 0; j < cornerSize - 1; j++) { + assert(transform.m_firstStrokeCornerIndexes[j] < + transform.m_firstStrokeCornerIndexes[j + 1]); + assert(transform.m_secondStrokeCornerIndexes[j] < + transform.m_secondStrokeCornerIndexes[j + 1]); + + assert(transform.m_firstStrokeCornerIndexes[j] < + stroke1->getChunkCount()); + assert(transform.m_secondStrokeCornerIndexes[j] < + stroke2->getChunkCount()); + } #endif - for (j = 0; j < cornerSize - 1; j++) { - ///////////////////////////////////////// sampling - - subStroke1 = extract(stroke1, transform.m_firstStrokeCornerIndexes[j], transform.m_firstStrokeCornerIndexes[j + 1] - 1); - sample(subStroke1, samplingPointNumber, samplingPoint1); - subStroke2 = extract(stroke2, transform.m_secondStrokeCornerIndexes[j], transform.m_secondStrokeCornerIndexes[j + 1] - 1); - sample(subStroke2, samplingPointNumber, samplingPoint2); - - ///////////////////////////////////////// compute Rotation - - ratioSampling.clear(); - ratioSampling.reserve(samplingPointNumber); - weigths.clear(); - weigths.reserve(samplingPointNumber); - - TPointD pOld, pNew; - // double totalW=0; - - for (p = 0; p < samplingPointNumber; p++) { - pOld = samplingPoint1[p]; - pNew = samplingPoint2[p]; - if (pOld == stroke1Centroid) - continue; - if (pNew == stroke2Centroid) - continue; - versor1 = normalize(pOld - stroke1Centroid); - versor2 = normalize(pNew - stroke2Centroid); - weigths.push_back(tdistance(pOld, stroke1Centroid) + tdistance(pNew, stroke2Centroid)); - cs = versor1 * versor2; - sn = cross(versor1, versor2); - double v = atan2(sn, cs); - ratioSampling.push_back(v); - } - delete subStroke1; - delete subStroke2; - subStroke1 = 0; - subStroke2 = 0; - - double radRotation = weightedAverage(ratioSampling, weigths); - - totalRadRotation += radRotation; - } - totalRadRotation /= (cornerSize - 1); - transform.m_rotation = TConsts::invOf_pi_180 * totalRadRotation; - - if (isAlmostZero(transform.m_rotation, 2)) { - transform.m_rotation = 0.0; - totalRadRotation = 0.0; - } + for (j = 0; j < cornerSize - 1; j++) { + ///////////////////////////////////////// sampling + + subStroke1 = extract(stroke1, transform.m_firstStrokeCornerIndexes[j], + transform.m_firstStrokeCornerIndexes[j + 1] - 1); + sample(subStroke1, samplingPointNumber, samplingPoint1); + subStroke2 = + extract(stroke2, transform.m_secondStrokeCornerIndexes[j], + transform.m_secondStrokeCornerIndexes[j + 1] - 1); + sample(subStroke2, samplingPointNumber, samplingPoint2); + + ///////////////////////////////////////// compute Rotation + + ratioSampling.clear(); + ratioSampling.reserve(samplingPointNumber); + weigths.clear(); + weigths.reserve(samplingPointNumber); + + TPointD pOld, pNew; + // double totalW=0; + + for (p = 0; p < samplingPointNumber; p++) { + pOld = samplingPoint1[p]; + pNew = samplingPoint2[p]; + if (pOld == stroke1Centroid) continue; + if (pNew == stroke2Centroid) continue; + versor1 = normalize(pOld - stroke1Centroid); + versor2 = normalize(pNew - stroke2Centroid); + weigths.push_back(tdistance(pOld, stroke1Centroid) + + tdistance(pNew, stroke2Centroid)); + cs = versor1 * versor2; + sn = cross(versor1, versor2); + double v = atan2(sn, cs); + ratioSampling.push_back(v); + } + delete subStroke1; + delete subStroke2; + subStroke1 = 0; + subStroke2 = 0; + + double radRotation = weightedAverage(ratioSampling, weigths); + + totalRadRotation += radRotation; + } + totalRadRotation /= (cornerSize - 1); + transform.m_rotation = totalRadRotation * M_180_PI; + + if (isAlmostZero(transform.m_rotation, 2)) { + transform.m_rotation = 0.0; + totalRadRotation = 0.0; + } #ifdef _DEBUG // TDebugMessage::getStream()<<"rotation "<< transform.m_rotation; // TDebugMessage::flush(); #endif - ///////////////////////////////////////// compute Scale - - if (transform.m_rotation == 0.0) { - - subStrokeXScaling.clear(); - subStrokeXScaling.reserve(cornerSize - 1); - subStrokeYScaling.clear(); - subStrokeYScaling.reserve(cornerSize - 1); - - for (j = 0; j < cornerSize - 1; j++) { - ///////////////////////////////////////// sampling - - subStroke1 = extract(stroke1, transform.m_firstStrokeCornerIndexes[j], transform.m_firstStrokeCornerIndexes[j + 1] - 1); - sample(subStroke1, samplingPointNumber, samplingPoint1); - subStroke2 = extract(stroke2, transform.m_secondStrokeCornerIndexes[j], transform.m_secondStrokeCornerIndexes[j + 1] - 1); - sample(subStroke2, samplingPointNumber, samplingPoint2); - - ///////////////////////////////////////// compute X Scale - - ratioSampling.clear(); - ratioSampling.reserve(samplingPointNumber + bboxSamplingWeight); - double appX, appY; - - TPointD appPoint; - double bboxXMin, bboxYMin, bboxXMax, bboxYMax; - bboxXMin = bboxYMin = (std::numeric_limits::max)(); - bboxXMax = bboxYMax = -(std::numeric_limits::max)(); - int h; - - for (h = 0; h < subStroke1->getControlPointCount(); ++h) { - appPoint = subStroke1->getControlPoint(h); - if (appPoint.x < bboxXMin) - bboxXMin = appPoint.x; - if (appPoint.x > bboxXMax) - bboxXMax = appPoint.x; - if (appPoint.y < bboxYMin) - bboxYMin = appPoint.y; - if (appPoint.y > bboxYMax) - bboxYMax = appPoint.y; - } - - appX = bboxXMax - bboxXMin; - appY = bboxYMax - bboxYMin; - - if (appX) { - bboxXMin = (std::numeric_limits::max)(); - bboxXMax = -(std::numeric_limits::max)(); - for (h = 0; h < subStroke2->getControlPointCount(); ++h) { - appPoint = subStroke2->getControlPoint(h); - if (appPoint.x < bboxXMin) - bboxXMin = appPoint.x; - if (appPoint.x > bboxXMax) - bboxXMax = appPoint.x; - } - appX = (isAlmostZero(appX, 1e-01)) ? -1 : (bboxXMax - bboxXMin) / appX; - for (UINT tms = 0; tms < bboxSamplingWeight && appX >= 0; tms++) - ratioSampling.push_back(appX); - - for (p = 0; p < samplingPointNumber; p++) { - appX = fabs(samplingPoint1[p].x - stroke1Centroid.x); - if (appX) - ratioSampling.push_back(fabs(samplingPoint2[p].x - stroke2Centroid.x) / appX); - } - - if (!ratioSampling.empty()) { - subStrokeXScaling.push_back(average(ratioSampling)); - } - } - - ///////////////////////////////////////// compute Y Scale - - ratioSampling.clear(); - ratioSampling.reserve(samplingPointNumber + bboxSamplingWeight); - - if (appY) { - bboxYMin = (std::numeric_limits::max)(); - bboxYMax = -(std::numeric_limits::max)(); - for (h = 0; h < subStroke2->getControlPointCount(); ++h) { - appPoint = subStroke2->getControlPoint(h); - if (appPoint.y < bboxYMin) - bboxYMin = appPoint.y; - if (appPoint.y > bboxYMax) - bboxYMax = appPoint.y; - } - - appY = (isAlmostZero(appY, 1e-01)) ? -1 : (bboxYMax - bboxYMin) / appY; - for (UINT tms = 0; tms < bboxSamplingWeight && appY >= 0; tms++) - ratioSampling.push_back(appY); - - for (p = 0; p < samplingPointNumber; p++) { - appY = fabs(samplingPoint1[p].y - stroke1Centroid.y); - if (appY) - ratioSampling.push_back(fabs(samplingPoint2[p].y - stroke2Centroid.y) / appY); - } - - if (!ratioSampling.empty()) { - subStrokeYScaling.push_back(average(ratioSampling)); - } - } - - delete subStroke1; - delete subStroke2; - subStroke1 = 0; - subStroke2 = 0; - } - - if (subStrokeXScaling.empty()) { - transform.m_scaleX = 1.0; - } else { - transform.m_scaleX = average(subStrokeXScaling); - if (isAlmostZero(transform.m_scaleX - 1.0)) - transform.m_scaleX = 1.0; - } - - if (subStrokeYScaling.empty()) { - transform.m_scaleY = 1.0; - } else { - transform.m_scaleY = average(subStrokeYScaling); - if (isAlmostZero(transform.m_scaleY - 1.0)) - transform.m_scaleY = 1.0; - } - /* - #ifdef _DEBUG - - TDebugMessage::getStream()<<"x scale "<< transform.m_scaleX ; - TDebugMessage::flush(); - TDebugMessage::getStream()<<"y scale "<< transform.m_scaleY ; - TDebugMessage::flush(); - #endif + ///////////////////////////////////////// compute Scale + + if (transform.m_rotation == 0.0) { + subStrokeXScaling.clear(); + subStrokeXScaling.reserve(cornerSize - 1); + subStrokeYScaling.clear(); + subStrokeYScaling.reserve(cornerSize - 1); + + for (j = 0; j < cornerSize - 1; j++) { + ///////////////////////////////////////// sampling + + subStroke1 = + extract(stroke1, transform.m_firstStrokeCornerIndexes[j], + transform.m_firstStrokeCornerIndexes[j + 1] - 1); + sample(subStroke1, samplingPointNumber, samplingPoint1); + subStroke2 = + extract(stroke2, transform.m_secondStrokeCornerIndexes[j], + transform.m_secondStrokeCornerIndexes[j + 1] - 1); + sample(subStroke2, samplingPointNumber, samplingPoint2); + + ///////////////////////////////////////// compute X Scale + + ratioSampling.clear(); + ratioSampling.reserve(samplingPointNumber + bboxSamplingWeight); + double appX, appY; + + TPointD appPoint; + double bboxXMin, bboxYMin, bboxXMax, bboxYMax; + bboxXMin = bboxYMin = (std::numeric_limits::max)(); + bboxXMax = bboxYMax = -(std::numeric_limits::max)(); + int h; + + for (h = 0; h < subStroke1->getControlPointCount(); ++h) { + appPoint = subStroke1->getControlPoint(h); + if (appPoint.x < bboxXMin) bboxXMin = appPoint.x; + if (appPoint.x > bboxXMax) bboxXMax = appPoint.x; + if (appPoint.y < bboxYMin) bboxYMin = appPoint.y; + if (appPoint.y > bboxYMax) bboxYMax = appPoint.y; + } + + appX = bboxXMax - bboxXMin; + appY = bboxYMax - bboxYMin; + + if (appX) { + bboxXMin = (std::numeric_limits::max)(); + bboxXMax = -(std::numeric_limits::max)(); + for (h = 0; h < subStroke2->getControlPointCount(); ++h) { + appPoint = subStroke2->getControlPoint(h); + if (appPoint.x < bboxXMin) bboxXMin = appPoint.x; + if (appPoint.x > bboxXMax) bboxXMax = appPoint.x; + } + appX = (isAlmostZero(appX, 1e-01)) ? -1 + : (bboxXMax - bboxXMin) / appX; + for (UINT tms = 0; tms < bboxSamplingWeight && appX >= 0; tms++) + ratioSampling.push_back(appX); + + for (p = 0; p < samplingPointNumber; p++) { + appX = fabs(samplingPoint1[p].x - stroke1Centroid.x); + if (appX) + ratioSampling.push_back( + fabs(samplingPoint2[p].x - stroke2Centroid.x) / appX); + } + + if (!ratioSampling.empty()) { + subStrokeXScaling.push_back(average(ratioSampling)); + } + } + + ///////////////////////////////////////// compute Y Scale + + ratioSampling.clear(); + ratioSampling.reserve(samplingPointNumber + bboxSamplingWeight); + + if (appY) { + bboxYMin = (std::numeric_limits::max)(); + bboxYMax = -(std::numeric_limits::max)(); + for (h = 0; h < subStroke2->getControlPointCount(); ++h) { + appPoint = subStroke2->getControlPoint(h); + if (appPoint.y < bboxYMin) bboxYMin = appPoint.y; + if (appPoint.y > bboxYMax) bboxYMax = appPoint.y; + } + + appY = (isAlmostZero(appY, 1e-01)) ? -1 + : (bboxYMax - bboxYMin) / appY; + for (UINT tms = 0; tms < bboxSamplingWeight && appY >= 0; tms++) + ratioSampling.push_back(appY); + + for (p = 0; p < samplingPointNumber; p++) { + appY = fabs(samplingPoint1[p].y - stroke1Centroid.y); + if (appY) + ratioSampling.push_back( + fabs(samplingPoint2[p].y - stroke2Centroid.y) / appY); + } + + if (!ratioSampling.empty()) { + subStrokeYScaling.push_back(average(ratioSampling)); + } + } + + delete subStroke1; + delete subStroke2; + subStroke1 = 0; + subStroke2 = 0; + } + + if (subStrokeXScaling.empty()) { + transform.m_scaleX = 1.0; + } else { + transform.m_scaleX = average(subStrokeXScaling); + if (isAlmostZero(transform.m_scaleX - 1.0)) + transform.m_scaleX = 1.0; + } + + if (subStrokeYScaling.empty()) { + transform.m_scaleY = 1.0; + } else { + transform.m_scaleY = average(subStrokeYScaling); + if (isAlmostZero(transform.m_scaleY - 1.0)) + transform.m_scaleY = 1.0; + } + /* +#ifdef _DEBUG + +TDebugMessage::getStream()<<"x scale "<< transform.m_scaleX ; +TDebugMessage::flush(); +TDebugMessage::getStream()<<"y scale "<< transform.m_scaleY ; +TDebugMessage::flush(); +#endif */ - } else { - subStrokeXScaling.clear(); - subStrokeXScaling.reserve(cornerSize - 1); - - for (j = 0; j < cornerSize - 1; j++) { - ///////////////////////////////////////// sampling - - subStroke1 = extract(stroke1, transform.m_firstStrokeCornerIndexes[j], transform.m_firstStrokeCornerIndexes[j + 1] - 1); - sample(subStroke1, samplingPointNumber, samplingPoint1); - subStroke2 = extract(stroke2, transform.m_secondStrokeCornerIndexes[j], transform.m_secondStrokeCornerIndexes[j + 1] - 1); - sample(subStroke2, samplingPointNumber, samplingPoint2); - - ///////////////////////////////////////// compute Scale - - ratioSampling.clear(); - ratioSampling.reserve(samplingPointNumber + bboxSamplingWeight); - - TRectD bbox1 = subStroke1->getBBox(); - double app = tdistance2(bbox1.getP00(), bbox1.getP11()); - if (app) { - TRectD bbox2 = TRotation(transform.m_rotation).inv() * subStroke2->getBBox(); - app = sqrt(tdistance2(bbox2.getP00(), bbox2.getP11()) / app); - - for (UINT tms = 0; tms < bboxSamplingWeight; tms++) - ratioSampling.push_back(app); - - double app; - for (p = 0; p < samplingPointNumber; p++) { - app = tdistance(samplingPoint1[p], stroke1Centroid); - if (app) { - ratioSampling.push_back(tdistance(samplingPoint2[p], stroke2Centroid) / app); - } - } - } - if (!ratioSampling.empty()) { - subStrokeXScaling.push_back(average(ratioSampling)); - } - - delete subStroke1; - delete subStroke2; - subStroke1 = 0; - subStroke2 = 0; - } - - if (subStrokeXScaling.empty()) { - transform.m_scaleX = transform.m_scaleY = 1.0; - } else { - transform.m_scaleX = transform.m_scaleY = average(subStrokeXScaling); - if (isAlmostZero(transform.m_scaleX - 1.0, 0.00001)) - transform.m_scaleX = transform.m_scaleY = 1.0; - } - /* - #ifdef _DEBUG - - TDebugMessage::getStream()<<"scale "<< transform.m_scaleX ; - TDebugMessage::flush(); - #endif + } else { + subStrokeXScaling.clear(); + subStrokeXScaling.reserve(cornerSize - 1); + + for (j = 0; j < cornerSize - 1; j++) { + ///////////////////////////////////////// sampling + + subStroke1 = + extract(stroke1, transform.m_firstStrokeCornerIndexes[j], + transform.m_firstStrokeCornerIndexes[j + 1] - 1); + sample(subStroke1, samplingPointNumber, samplingPoint1); + subStroke2 = + extract(stroke2, transform.m_secondStrokeCornerIndexes[j], + transform.m_secondStrokeCornerIndexes[j + 1] - 1); + sample(subStroke2, samplingPointNumber, samplingPoint2); + + ///////////////////////////////////////// compute Scale + + ratioSampling.clear(); + ratioSampling.reserve(samplingPointNumber + bboxSamplingWeight); + + TRectD bbox1 = subStroke1->getBBox(); + double app = tdistance2(bbox1.getP00(), bbox1.getP11()); + if (app) { + TRectD bbox2 = + TRotation(transform.m_rotation).inv() * subStroke2->getBBox(); + app = sqrt(tdistance2(bbox2.getP00(), bbox2.getP11()) / app); + + for (UINT tms = 0; tms < bboxSamplingWeight; tms++) + ratioSampling.push_back(app); + + double app; + for (p = 0; p < samplingPointNumber; p++) { + app = tdistance(samplingPoint1[p], stroke1Centroid); + if (app) { + ratioSampling.push_back( + tdistance(samplingPoint2[p], stroke2Centroid) / app); + } + } + } + if (!ratioSampling.empty()) { + subStrokeXScaling.push_back(average(ratioSampling)); + } + + delete subStroke1; + delete subStroke2; + subStroke1 = 0; + subStroke2 = 0; + } + + if (subStrokeXScaling.empty()) { + transform.m_scaleX = transform.m_scaleY = 1.0; + } else { + transform.m_scaleX = transform.m_scaleY = + average(subStrokeXScaling); + if (isAlmostZero(transform.m_scaleX - 1.0, 0.00001)) + transform.m_scaleX = transform.m_scaleY = 1.0; + } + /* +#ifdef _DEBUG + +TDebugMessage::getStream()<<"scale "<< transform.m_scaleX ; +TDebugMessage::flush(); +#endif */ - } - - ///////////////////////////////////////// compute centre of Rotation and Scaling - - std::vector vpOld(cornerSize), vpNew(cornerSize); - TPointD pOld, pNew; - - for (j = 0; j < cornerSize - 1; j++) { - vpOld[j] = stroke1->getChunk(transform.m_firstStrokeCornerIndexes[j])->getP0(); - vpNew[j] = stroke2->getChunk(transform.m_secondStrokeCornerIndexes[j])->getP0(); - } - vpOld[j] = stroke1->getControlPoint(stroke1->getControlPointCount()); - vpNew[j] = stroke2->getControlPoint(stroke2->getControlPointCount()); - - if (transform.m_rotation == 0.0) { - if (transform.m_scaleX == 1.0 && transform.m_scaleY == 1.0) { - transform.m_translate = stroke2Centroid - stroke1Centroid; - transform.m_rotationAndScaleCenter = TPointD(); - } else { - if (transform.m_scaleX == 1.0) { - transform.m_rotationAndScaleCenter.x = 0; - transform.m_translate.x = 0; - for (j = 0; j < cornerSize; j++) { - transform.m_translate.x += vpNew[j].x - vpOld[j].x; - } - transform.m_translate.x = transform.m_translate.x / cornerSize; - } else { - transform.m_rotationAndScaleCenter.x = 0; - - for (j = 0; j < cornerSize; j++) { - pOld = vpOld[j]; - pNew = vpNew[j]; - transform.m_rotationAndScaleCenter.x += (transform.m_scaleX * pOld.x - pNew.x) / (transform.m_scaleX - 1.0); - } - transform.m_rotationAndScaleCenter.x = transform.m_rotationAndScaleCenter.x / cornerSize; - transform.m_translate.x = 0; - } - - if (transform.m_scaleY == 1.0) { - transform.m_rotationAndScaleCenter.y = 0; - transform.m_translate.y = 0; - for (j = 0; j < cornerSize; j++) { - transform.m_translate.y += vpNew[j].y - vpOld[j].y; - } - transform.m_translate.y = transform.m_translate.y / cornerSize; - } else { - transform.m_rotationAndScaleCenter.y = 0; - - for (j = 0; j < cornerSize; j++) { - pOld = vpOld[j]; - pNew = vpNew[j]; - transform.m_rotationAndScaleCenter.y += (transform.m_scaleY * pOld.y - pNew.y) / (transform.m_scaleY - 1.0); - } - transform.m_rotationAndScaleCenter.y = transform.m_rotationAndScaleCenter.y / cornerSize; - transform.m_translate.y = 0; - } - } - - } else { - assert(transform.m_scaleX == transform.m_scaleY); - - cs = transform.m_scaleX * cos(totalRadRotation); - sn = transform.m_scaleX * sin(totalRadRotation); - - // scelgo punti da usare come vincolo, per ottenere la translazione, dato un centro di rotazione - - // dato il punto pOld e pNew si calcola analiticamnete il punto di rotazione e scala - // che minimizza la traslazione aggiuntiva e la traslazione stessa - - for (j = 0; j < cornerSize; j++) { - pOld = vpOld[j]; - pNew = vpNew[j]; - constK = pNew.x - cs * pOld.x + sn * pOld.y; - constQ = pNew.y - sn * pOld.x - cs * pOld.y; - constB = 2 * (constK * (cs - 1.) + sn * constQ); - constD = 2 * (constQ * (cs - 1.) - sn * constK); - constA = transform.m_scaleX * transform.m_scaleX + 1 - 2 * cs; - assert(constA > 0); - constA = 1.0 / (2 * constA); - transform.m_rotationAndScaleCenter.x += -constB * constA; - transform.m_rotationAndScaleCenter.y += -constD * constA; - } - - transform.m_rotationAndScaleCenter = transform.m_rotationAndScaleCenter * (1.0 / (double)cornerSize); - - transform.m_translate.x = (cs - 1.0) * transform.m_rotationAndScaleCenter.x - sn * transform.m_rotationAndScaleCenter.y + constK; - - transform.m_translate.y = sn * transform.m_rotationAndScaleCenter.x + (cs - 1.0) * transform.m_rotationAndScaleCenter.y + constQ; - } - - ///////////////////////////////////////// - - transform.m_inverse = (TTranslation(transform.m_translate) * - TScale(transform.m_rotationAndScaleCenter, transform.m_scaleX, transform.m_scaleY) * - TRotation(transform.m_rotationAndScaleCenter, transform.m_rotation)) - .inv(); - - //debugStream.close(); - } // end if !isPoint - - } // end if !isEqual - - m_transformation.push_back(transform); - - } // end for each stroke + } + + ///////////////////////////////////////// compute centre of Rotation and + ///Scaling + + std::vector vpOld(cornerSize), vpNew(cornerSize); + TPointD pOld, pNew; + + for (j = 0; j < cornerSize - 1; j++) { + vpOld[j] = stroke1->getChunk(transform.m_firstStrokeCornerIndexes[j]) + ->getP0(); + vpNew[j] = stroke2->getChunk(transform.m_secondStrokeCornerIndexes[j]) + ->getP0(); + } + vpOld[j] = stroke1->getControlPoint(stroke1->getControlPointCount()); + vpNew[j] = stroke2->getControlPoint(stroke2->getControlPointCount()); + + if (transform.m_rotation == 0.0) { + if (transform.m_scaleX == 1.0 && transform.m_scaleY == 1.0) { + transform.m_translate = stroke2Centroid - stroke1Centroid; + transform.m_rotationAndScaleCenter = TPointD(); + } else { + if (transform.m_scaleX == 1.0) { + transform.m_rotationAndScaleCenter.x = 0; + transform.m_translate.x = 0; + for (j = 0; j < cornerSize; j++) { + transform.m_translate.x += vpNew[j].x - vpOld[j].x; + } + transform.m_translate.x = transform.m_translate.x / cornerSize; + } else { + transform.m_rotationAndScaleCenter.x = 0; + + for (j = 0; j < cornerSize; j++) { + pOld = vpOld[j]; + pNew = vpNew[j]; + transform.m_rotationAndScaleCenter.x += + (transform.m_scaleX * pOld.x - pNew.x) / + (transform.m_scaleX - 1.0); + } + transform.m_rotationAndScaleCenter.x = + transform.m_rotationAndScaleCenter.x / cornerSize; + transform.m_translate.x = 0; + } + + if (transform.m_scaleY == 1.0) { + transform.m_rotationAndScaleCenter.y = 0; + transform.m_translate.y = 0; + for (j = 0; j < cornerSize; j++) { + transform.m_translate.y += vpNew[j].y - vpOld[j].y; + } + transform.m_translate.y = transform.m_translate.y / cornerSize; + } else { + transform.m_rotationAndScaleCenter.y = 0; + + for (j = 0; j < cornerSize; j++) { + pOld = vpOld[j]; + pNew = vpNew[j]; + transform.m_rotationAndScaleCenter.y += + (transform.m_scaleY * pOld.y - pNew.y) / + (transform.m_scaleY - 1.0); + } + transform.m_rotationAndScaleCenter.y = + transform.m_rotationAndScaleCenter.y / cornerSize; + transform.m_translate.y = 0; + } + } + + } else { + assert(transform.m_scaleX == transform.m_scaleY); + + cs = transform.m_scaleX * cos(totalRadRotation); + sn = transform.m_scaleX * sin(totalRadRotation); + + // scelgo punti da usare come vincolo, per ottenere la translazione, + // dato un centro di rotazione + + // dato il punto pOld e pNew si calcola analiticamnete il punto di + // rotazione e scala + // che minimizza la traslazione aggiuntiva e la traslazione stessa + + for (j = 0; j < cornerSize; j++) { + pOld = vpOld[j]; + pNew = vpNew[j]; + constK = pNew.x - cs * pOld.x + sn * pOld.y; + constQ = pNew.y - sn * pOld.x - cs * pOld.y; + constB = 2 * (constK * (cs - 1.) + sn * constQ); + constD = 2 * (constQ * (cs - 1.) - sn * constK); + constA = transform.m_scaleX * transform.m_scaleX + 1 - 2 * cs; + assert(constA > 0); + constA = 1.0 / (2 * constA); + transform.m_rotationAndScaleCenter.x += -constB * constA; + transform.m_rotationAndScaleCenter.y += -constD * constA; + } + + transform.m_rotationAndScaleCenter = + transform.m_rotationAndScaleCenter * (1.0 / (double)cornerSize); + + transform.m_translate.x = + (cs - 1.0) * transform.m_rotationAndScaleCenter.x - + sn * transform.m_rotationAndScaleCenter.y + constK; + + transform.m_translate.y = + sn * transform.m_rotationAndScaleCenter.x + + (cs - 1.0) * transform.m_rotationAndScaleCenter.y + constQ; + } + + ///////////////////////////////////////// + + transform.m_inverse = (TTranslation(transform.m_translate) * + TScale(transform.m_rotationAndScaleCenter, + transform.m_scaleX, transform.m_scaleY) * + TRotation(transform.m_rotationAndScaleCenter, + transform.m_rotation)) + .inv(); + + // debugStream.close(); + } // end if !isPoint + + } // end if !isEqual + + m_transformation.push_back(transform); + + } // end for each stroke } //------------------------------------------------------------------- -TVectorImageP TInbetween::Imp::tween(double t) const -{ - const double step = 5.0; - const double interpolateError = 1.0; - - TVectorImageP vi = new TVectorImage; - - UINT strokeCount1 = m_firstImage->getStrokeCount(); - UINT strokeCount2 = m_lastImage->getStrokeCount(); - vi->setPalette(m_firstImage->getPalette()); - if (strokeCount1 > strokeCount2) - strokeCount1 = strokeCount2; - - assert(m_transformation.size() == strokeCount1); - - double totalLen1, totalLen2, len1, len2, step1, step2; - std::vector points; - TStroke *stroke1, *stroke2, *subStroke1, *subStroke2, *stroke; - - TAffine mt, invMatrix; - TThickPoint point2, finalPoint; - UINT i, j, cp, cpSize; - - for (i = 0; i < strokeCount1; i++) { - - stroke1 = m_firstImage->getStroke(i); - stroke2 = m_lastImage->getStroke(i); - - if (m_transformation[i].m_type == StrokeTransform::EQUAL) { - stroke = new TStroke(*stroke1); - } else { - points.clear(); - totalLen1 = stroke1->getLength(); - totalLen2 = stroke2->getLength(); - ; - - if (stroke1->getControlPointCount() == stroke2->getControlPointCount() && - stroke1->isSelfLoop() && stroke2->isSelfLoop()) { - for (int i = 0; i < stroke1->getControlPointCount(); i++) { - TThickPoint p0 = stroke1->getControlPoint(i); - TThickPoint p1 = stroke2->getControlPoint(i); - points.push_back(p0 * (1 - t) + p1 * t); - } - stroke = new TStroke(points); - } else if (m_transformation[i].m_type == StrokeTransform::POINT) { - TThickPoint pOld = stroke1->getThickPointAtLength(0.5 * totalLen1); - TThickPoint pNew = stroke2->getThickPointAtLength(0.5 * totalLen2); - points.push_back(pOld * (1 - t) + pNew * t); - points.push_back(points[0]); - points.push_back(points[0]); - stroke = new TStroke(points); - } else { - mt = (m_transformation[i].m_inverse.isIdentity()) - ? TAffine() - : TTranslation(m_transformation[i].m_translate * t) * - TScale(m_transformation[i].m_rotationAndScaleCenter, (1 - t) + t * m_transformation[i].m_scaleX, (1 - t) + t * m_transformation[i].m_scaleY) * - TRotation(m_transformation[i].m_rotationAndScaleCenter, m_transformation[i].m_rotation * t); - - UINT cornerSize = m_transformation[i].m_firstStrokeCornerIndexes.size(); - assert(cornerSize == m_transformation[i].m_secondStrokeCornerIndexes.size()); - if (cornerSize > m_transformation[i].m_secondStrokeCornerIndexes.size()) - cornerSize = m_transformation[i].m_secondStrokeCornerIndexes.size(); - - assert(cornerSize >= 2); - - std::vector controlPoints; - - //if not m_transformation[i].m_findCorners => detect corner return different size =>cornerSize==2 - // assert(!m_transformation[i].m_findCorners || cornerSize==2); - - for (j = 0; j < cornerSize - 1; j++) { - points.clear(); - subStroke1 = extract(stroke1, m_transformation[i].m_firstStrokeCornerIndexes[j], m_transformation[i].m_firstStrokeCornerIndexes[j + 1] - 1); - subStroke2 = extract(stroke2, m_transformation[i].m_secondStrokeCornerIndexes[j], m_transformation[i].m_secondStrokeCornerIndexes[j + 1] - 1); - - totalLen1 = subStroke1->getLength(); - totalLen2 = subStroke2->getLength(); - - if (totalLen1 > totalLen2) { - step1 = step; - step2 = (totalLen2 / totalLen1) * step; - } else { - step1 = (totalLen1 / totalLen2) * step; - step2 = step; - } - - len1 = 0; - len2 = 0; - - while (len1 <= totalLen1 && len2 <= totalLen2) { - point2 = subStroke2->getThickPointAtLength(len2); - point2 = TThickPoint(m_transformation[i].m_inverse * subStroke2->getThickPointAtLength(len2), point2.thick); - finalPoint = subStroke1->getThickPointAtLength(len1) * (1 - t) + t * point2; - - points.push_back(TThickPoint(mt * (finalPoint), finalPoint.thick)); - len1 += step1; - len2 += step2; - } - point2 = subStroke2->getThickPointAtLength(totalLen2); - point2 = TThickPoint(m_transformation[i].m_inverse * subStroke2->getThickPointAtLength(totalLen2), point2.thick); - finalPoint = subStroke1->getThickPointAtLength(totalLen1) * (1 - t) + t * point2; - - points.push_back(TThickPoint(mt * (finalPoint), finalPoint.thick)); - - stroke = TStroke::interpolate(points, interpolateError, false - /*m_transformation[i].m_findCorners*/); - - if (j == 0) - controlPoints.push_back(stroke->getControlPoint(0)); - else - controlPoints.back() = (controlPoints.back() + stroke->getControlPoint(0)) * 0.5; - - cpSize = stroke->getControlPointCount(); - for (cp = 1; cp < cpSize; cp++) { - controlPoints.push_back(stroke->getControlPoint(cp)); - } - - delete subStroke1; - delete subStroke2; - delete stroke; - subStroke1 = 0; - subStroke2 = 0; - stroke = 0; - } - - stroke = new TStroke(controlPoints); - } - } - - if (stroke1->isSelfLoop() && stroke2->isSelfLoop()) - stroke->setSelfLoop(); - - stroke->setStyle(stroke1->getStyle()); - stroke->outlineOptions() = stroke1->outlineOptions(); - VIStroke *vs = new VIStroke(stroke, m_firstImage->getVIStroke(i)->m_groupId); - vi->m_imp->m_strokes.push_back(vs); - - } //end for each stroke - - if (m_firstImage->isComputedRegionAlmostOnce()) - transferColor(vi); - - return vi; +TVectorImageP TInbetween::Imp::tween(double t) const { + const double step = 5.0; + const double interpolateError = 1.0; + + TVectorImageP vi = new TVectorImage; + + UINT strokeCount1 = m_firstImage->getStrokeCount(); + UINT strokeCount2 = m_lastImage->getStrokeCount(); + vi->setPalette(m_firstImage->getPalette()); + if (strokeCount1 > strokeCount2) strokeCount1 = strokeCount2; + + assert(m_transformation.size() == strokeCount1); + + double totalLen1, totalLen2, len1, len2, step1, step2; + std::vector points; + TStroke *stroke1, *stroke2, *subStroke1, *subStroke2, *stroke; + + TAffine mt, invMatrix; + TThickPoint point2, finalPoint; + UINT i, j, cp, cpSize; + + for (i = 0; i < strokeCount1; i++) { + stroke1 = m_firstImage->getStroke(i); + stroke2 = m_lastImage->getStroke(i); + + if (m_transformation[i].m_type == StrokeTransform::EQUAL) { + stroke = new TStroke(*stroke1); + } else { + points.clear(); + totalLen1 = stroke1->getLength(); + totalLen2 = stroke2->getLength(); + ; + + if (stroke1->getControlPointCount() == stroke2->getControlPointCount() && + stroke1->isSelfLoop() && stroke2->isSelfLoop()) { + for (int i = 0; i < stroke1->getControlPointCount(); i++) { + TThickPoint p0 = stroke1->getControlPoint(i); + TThickPoint p1 = stroke2->getControlPoint(i); + points.push_back(p0 * (1 - t) + p1 * t); + } + stroke = new TStroke(points); + } else if (m_transformation[i].m_type == StrokeTransform::POINT) { + TThickPoint pOld = stroke1->getThickPointAtLength(0.5 * totalLen1); + TThickPoint pNew = stroke2->getThickPointAtLength(0.5 * totalLen2); + points.push_back(pOld * (1 - t) + pNew * t); + points.push_back(points[0]); + points.push_back(points[0]); + stroke = new TStroke(points); + } else { + mt = (m_transformation[i].m_inverse.isIdentity()) + ? TAffine() + : TTranslation(m_transformation[i].m_translate * t) * + TScale(m_transformation[i].m_rotationAndScaleCenter, + (1 - t) + t * m_transformation[i].m_scaleX, + (1 - t) + t * m_transformation[i].m_scaleY) * + TRotation(m_transformation[i].m_rotationAndScaleCenter, + m_transformation[i].m_rotation * t); + + UINT cornerSize = m_transformation[i].m_firstStrokeCornerIndexes.size(); + assert(cornerSize == + m_transformation[i].m_secondStrokeCornerIndexes.size()); + if (cornerSize > m_transformation[i].m_secondStrokeCornerIndexes.size()) + cornerSize = m_transformation[i].m_secondStrokeCornerIndexes.size(); + + assert(cornerSize >= 2); + + std::vector controlPoints; + + // if not m_transformation[i].m_findCorners => detect corner return + // different size =>cornerSize==2 + // assert(!m_transformation[i].m_findCorners || cornerSize==2); + + for (j = 0; j < cornerSize - 1; j++) { + points.clear(); + subStroke1 = extract( + stroke1, m_transformation[i].m_firstStrokeCornerIndexes[j], + m_transformation[i].m_firstStrokeCornerIndexes[j + 1] - 1); + subStroke2 = extract( + stroke2, m_transformation[i].m_secondStrokeCornerIndexes[j], + m_transformation[i].m_secondStrokeCornerIndexes[j + 1] - 1); + + totalLen1 = subStroke1->getLength(); + totalLen2 = subStroke2->getLength(); + + if (totalLen1 > totalLen2) { + step1 = step; + step2 = (totalLen2 / totalLen1) * step; + } else { + step1 = (totalLen1 / totalLen2) * step; + step2 = step; + } + + len1 = 0; + len2 = 0; + + while (len1 <= totalLen1 && len2 <= totalLen2) { + point2 = subStroke2->getThickPointAtLength(len2); + point2 = TThickPoint(m_transformation[i].m_inverse * + subStroke2->getThickPointAtLength(len2), + point2.thick); + finalPoint = + subStroke1->getThickPointAtLength(len1) * (1 - t) + t * point2; + + points.push_back(TThickPoint(mt * (finalPoint), finalPoint.thick)); + len1 += step1; + len2 += step2; + } + point2 = subStroke2->getThickPointAtLength(totalLen2); + point2 = TThickPoint(m_transformation[i].m_inverse * + subStroke2->getThickPointAtLength(totalLen2), + point2.thick); + finalPoint = subStroke1->getThickPointAtLength(totalLen1) * (1 - t) + + t * point2; + + points.push_back(TThickPoint(mt * (finalPoint), finalPoint.thick)); + + stroke = TStroke::interpolate(points, interpolateError, false + /*m_transformation[i].m_findCorners*/); + + if (j == 0) + controlPoints.push_back(stroke->getControlPoint(0)); + else + controlPoints.back() = + (controlPoints.back() + stroke->getControlPoint(0)) * 0.5; + + cpSize = stroke->getControlPointCount(); + for (cp = 1; cp < cpSize; cp++) { + controlPoints.push_back(stroke->getControlPoint(cp)); + } + + delete subStroke1; + delete subStroke2; + delete stroke; + subStroke1 = 0; + subStroke2 = 0; + stroke = 0; + } + + stroke = new TStroke(controlPoints); + } + } + + if (stroke1->isSelfLoop() && stroke2->isSelfLoop()) stroke->setSelfLoop(); + + stroke->setStyle(stroke1->getStyle()); + stroke->outlineOptions() = stroke1->outlineOptions(); + VIStroke *vs = + new VIStroke(stroke, m_firstImage->getVIStroke(i)->m_groupId); + vi->m_imp->m_strokes.push_back(vs); + + } // end for each stroke + + if (m_firstImage->isComputedRegionAlmostOnce()) transferColor(vi); + + return vi; } //------------------------------------------------------------------- -void TInbetween::Imp::transferColor(const TVectorImageP &destination) const -{ - const TVectorImageP &original = m_firstImage; - destination->setPalette(original->getPalette()); +void TInbetween::Imp::transferColor(const TVectorImageP &destination) const { + const TVectorImageP &original = m_firstImage; + destination->setPalette(original->getPalette()); - destination->findRegions(); + destination->findRegions(); - if (destination->getRegionCount()) { - UINT strokeCount1 = original->getStrokeCount(); - UINT strokeCount2 = destination->getStrokeCount(); - if (strokeCount1 > strokeCount2) - strokeCount1 = strokeCount2; + if (destination->getRegionCount()) { + UINT strokeCount1 = original->getStrokeCount(); + UINT strokeCount2 = destination->getStrokeCount(); + if (strokeCount1 > strokeCount2) strokeCount1 = strokeCount2; - for (UINT i = 0; i < strokeCount1; i++) { - TVectorImage::transferStrokeColors(original, i, destination, i); - } - } + for (UINT i = 0; i < strokeCount1; i++) { + TVectorImage::transferStrokeColors(original, i, destination, i); + } + } } //------------------------------------------------------------------- -TVectorImageP TInbetween::tween(double t) const -{ - return m_imp->tween(t); -} +TVectorImageP TInbetween::tween(double t) const { return m_imp->tween(t); } //------------------------------------------------------------------- diff --git a/toonz/sources/common/tvrender/tofflinegl.cpp b/toonz/sources/common/tvrender/tofflinegl.cpp index c1df1fa..a5354c5 100644 --- a/toonz/sources/common/tvrender/tofflinegl.cpp +++ b/toonz/sources/common/tvrender/tofflinegl.cpp @@ -28,17 +28,17 @@ #include "tofflinegl.h" #ifndef checkErrorsByGL -#define checkErrorsByGL \ - { \ - GLenum err = glGetError(); \ - assert(err != GL_INVALID_ENUM); \ - assert(err != GL_INVALID_VALUE); \ - assert(err != GL_INVALID_OPERATION); \ - assert(err != GL_STACK_OVERFLOW); \ - assert(err != GL_STACK_UNDERFLOW); \ - assert(err != GL_OUT_OF_MEMORY); \ - assert(err == GL_NO_ERROR); \ - } +#define checkErrorsByGL \ + { \ + GLenum err = glGetError(); \ + assert(err != GL_INVALID_ENUM); \ + assert(err != GL_INVALID_VALUE); \ + assert(err != GL_INVALID_OPERATION); \ + assert(err != GL_STACK_OVERFLOW); \ + assert(err != GL_STACK_UNDERFLOW); \ + assert(err != GL_OUT_OF_MEMORY); \ + assert(err == GL_NO_ERROR); \ + } #endif #undef checkErrorsByGL @@ -48,11 +48,9 @@ using namespace std; TGLContextManager *currentContextManager = 0; -void TOfflineGL::setContextManager(TGLContextManager *contextManager) -{ - currentContextManager = contextManager; - if (contextManager) - contextManager->store(); +void TOfflineGL::setContextManager(TGLContextManager *contextManager) { + currentContextManager = contextManager; + if (contextManager) contextManager->store(); } //============================================================================= @@ -61,457 +59,435 @@ void TOfflineGL::setContextManager(TGLContextManager *contextManager) #ifdef _WIN32 -namespace -{ -//We found out that our implementation of win32 opengl contexts can be someway -//not thread-safe. Deadlocks and errors could happen for wgl* and GDI functions -//on particular configurations (notably, Windows 7). So we mutex them as -//a temporary workaround. +namespace { +// We found out that our implementation of win32 opengl contexts can be someway +// not thread-safe. Deadlocks and errors could happen for wgl* and GDI functions +// on particular configurations (notably, Windows 7). So we mutex them as +// a temporary workaround. static QMutex win32ImpMutex; } //------------------------------- -class WIN32Implementation : public TOfflineGL::Imp -{ +class WIN32Implementation : public TOfflineGL::Imp { public: - HDC m_offDC; - HGDIOBJ m_oldobj; - HGLRC m_hglRC; - HBITMAP m_offDIB; - void *m_offData; + HDC m_offDC; + HGDIOBJ m_oldobj; + HGLRC m_hglRC; + HBITMAP m_offDIB; + void *m_offData; - //----------------------------------------------------------------------------- + //----------------------------------------------------------------------------- - WIN32Implementation(TDimension rasterSize, std::shared_ptr shared) - : TOfflineGL::Imp(rasterSize.lx, rasterSize.ly) - { - m_offData = 0; - createContext(rasterSize, std::move(shared)); //makeCurrent is called at the end of this + WIN32Implementation(TDimension rasterSize, + std::shared_ptr shared) + : TOfflineGL::Imp(rasterSize.lx, rasterSize.ly) { + m_offData = 0; + createContext( + rasterSize, + std::move(shared)); // makeCurrent is called at the end of this - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); - doneCurrent(); //doneCurrent must therefore be called here - } - - //----------------------------------------------------------------------------- - - ~WIN32Implementation() - { - QMutexLocker locker(&win32ImpMutex); - - BOOL ret = wglMakeCurrent(m_offDC, NULL); - assert(ret == TRUE); - wglDeleteContext(m_hglRC); - SelectObject(m_offDC, m_oldobj); - DeleteObject(m_offDC); - - // si potrebbe passare un parametro che evita di distruggere la bitmap. - // In tal caso il raster dovrebbe diventare owner del buffer, ma attualmente - // questo non e' settabile in TRaster: quando gli si passa da fuori un buffer, - // automaticamente bufferOwner viene settato a false e non e' modificabile! - DeleteObject(m_offDIB); - } - - //----------------------------------------------------------------------------- - - void makeCurrent() - { - QMutexLocker locker(&win32ImpMutex); - - int ret = wglMakeCurrent(m_offDC, m_hglRC); - assert(ret == TRUE); - } - - //----------------------------------------------------------------------------- - - void doneCurrent() - { - QMutexLocker locker(&win32ImpMutex); - - glFlush(); - glFinish(); - assert(glGetError() == 0); - wglMakeCurrent(NULL, NULL); - } - - //----------------------------------------------------------------------------- + doneCurrent(); // doneCurrent must therefore be called here + } + + //----------------------------------------------------------------------------- + + ~WIN32Implementation() { + QMutexLocker locker(&win32ImpMutex); + + BOOL ret = wglMakeCurrent(m_offDC, NULL); + assert(ret == TRUE); + wglDeleteContext(m_hglRC); + SelectObject(m_offDC, m_oldobj); + DeleteObject(m_offDC); + + // si potrebbe passare un parametro che evita di distruggere la bitmap. + // In tal caso il raster dovrebbe diventare owner del buffer, ma attualmente + // questo non e' settabile in TRaster: quando gli si passa da fuori un + // buffer, + // automaticamente bufferOwner viene settato a false e non e' modificabile! + DeleteObject(m_offDIB); + } + + //----------------------------------------------------------------------------- + + void makeCurrent() { + QMutexLocker locker(&win32ImpMutex); + + int ret = wglMakeCurrent(m_offDC, m_hglRC); + assert(ret == TRUE); + } + + //----------------------------------------------------------------------------- + + void doneCurrent() { + QMutexLocker locker(&win32ImpMutex); + + glFlush(); + glFinish(); + assert(glGetError() == 0); + wglMakeCurrent(NULL, NULL); + } + + //----------------------------------------------------------------------------- + + void initBITMAPINFO(BITMAPINFO &info, const TDimension rasterSize) { + memset(&info, 0, sizeof(BITMAPINFOHEADER)); + + info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + info.bmiHeader.biWidth = rasterSize.lx; + info.bmiHeader.biHeight = rasterSize.ly; + info.bmiHeader.biPlanes = 1; + info.bmiHeader.biBitCount = 32; + info.bmiHeader.biCompression = BI_RGB; + info.bmiHeader.biSizeImage = 0; + info.bmiHeader.biXPelsPerMeter = 1000; + info.bmiHeader.biYPelsPerMeter = 1000; + info.bmiHeader.biClrUsed = 0; + info.bmiHeader.biClrImportant = 0; + } + + //----------------------------------------------------------------------------- + + void createContext(TDimension rasterSize, + std::shared_ptr shared) { + QMutexLocker locker(&win32ImpMutex); + + BITMAPINFO info; + + initBITMAPINFO(info, rasterSize); + + // open an offscreen device + m_offDC = CreateCompatibleDC(NULL); + + // and a bitmap image + m_offDIB = + CreateDIBSection(m_offDC, &info, DIB_RGB_COLORS, &m_offData, NULL, 0); + + assert(m_offDIB); + assert(m_offData); + + if (!m_offDIB || !m_offData) + throw TException("cannot create OpenGL context. Check system resources!"); + + int dataSize = + rasterSize.lx * rasterSize.ly * 4; // number of byte of raster + + memset(m_offData, 0, dataSize); + + m_oldobj = SelectObject(m_offDC, m_offDIB); // select BIB to write + + static PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd + 1, // version number + 0 | (false ? (PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER) + : (PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI)) | + PFD_SUPPORT_OPENGL, // support OpenGL + PFD_TYPE_RGBA, // RGBA type + 32, // 32-bit color depth + 0, + 0, 0, 0, 0, 0, // color bits ignored + 8, // no alpha buffer /*===*/ + 0, // shift bit ignored + 0, // no accumulation buffer + 0, 0, 0, 0, // accum bits ignored + 32, // 32-bit z-buffer + 32, // max stencil buffer + 0, // no auxiliary buffer + PFD_MAIN_PLANE, // main layer + 0, // reserved + 0, 0, 0 // layer masks ignored + }; + + // get the best available match of pixel format for the device context + int iPixelFormat = ChoosePixelFormat(m_offDC, &pfd); + assert(iPixelFormat != 0); + + // make that the pixel format of the device context + int ret = SetPixelFormat(m_offDC, iPixelFormat, &pfd); + assert(ret == TRUE); + + // make a valid context for OpenGL rendering - void initBITMAPINFO(BITMAPINFO &info, const TDimension rasterSize) - { - memset(&info, 0, sizeof(BITMAPINFOHEADER)); + m_hglRC = wglCreateContext(m_offDC); + assert(m_hglRC); + + if (!m_hglRC) + throw TException("cannot create OpenGL context. Check system resources!"); + + if (shared) { + // Share shared's display lists + const WIN32Implementation *sharedImp = + dynamic_cast(shared.get()); + assert(sharedImp); + + bool ok = wglShareLists(sharedImp->m_hglRC, m_hglRC); + assert(ok); + } - info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - info.bmiHeader.biWidth = rasterSize.lx; - info.bmiHeader.biHeight = rasterSize.ly; - info.bmiHeader.biPlanes = 1; - info.bmiHeader.biBitCount = 32; - info.bmiHeader.biCompression = BI_RGB; - info.bmiHeader.biSizeImage = 0; - info.bmiHeader.biXPelsPerMeter = 1000; - info.bmiHeader.biYPelsPerMeter = 1000; - info.bmiHeader.biClrUsed = 0; - info.bmiHeader.biClrImportant = 0; - } + ret = wglMakeCurrent(m_offDC, m_hglRC); + assert(ret == TRUE); + } - //----------------------------------------------------------------------------- + //----------------------------------------------------------------------------- - void createContext(TDimension rasterSize, std::shared_ptr shared) - { - QMutexLocker locker(&win32ImpMutex); + void swapRedBlueChannels( + void *buffer, + int bufferSize) // Flips The Red And Blue Bytes (WidthxHeight) + { + void *b = buffer; // Pointer To The Buffer - BITMAPINFO info; +#ifdef x64 + int size = bufferSize; + UCHAR *pix = (UCHAR *)b; + while (size > 0) { + UCHAR r = *pix; + UCHAR b = *(pix + 2); + *pix = b; + *(pix + 2) = r; + pix += 4; + size--; + } +/*unsigned long ebx = (unsigned long)b; + while(size>0) + { + unsigned char al =__readgsbyte(ebx); + unsigned char ah =__readgsbyte(ebx+2); + __writegsbyte(ebx+2,al); + __writegsbyte(ebx,ah); + ebx+=4; + size--; + }*/ +#else + __asm // Assembler Code To Follow + { + mov ecx, bufferSize // Counter Set To Dimensions Of Our Memory Block + mov ebx, b // Points ebx To Our Data (b) + label: // Label Used For Looping + mov al,[ebx+0] // Loads Value At ebx Into al + mov ah,[ebx+2] // Loads Value At ebx+2 Into ah + mov [ebx+2],al // Stores Value In al At ebx+2 + mov [ebx+0],ah // Stores Value In ah At ebx + + add ebx,4 // Moves Through The Data By 4 Bytes + dec ecx // Decreases Our Loop Counter + jnz label // If Not Zero Jump Back To Label + } +#endif + } - initBITMAPINFO(info, rasterSize); + //----------------------------------------------------------------------------- - // open an offscreen device - m_offDC = CreateCompatibleDC(NULL); + void getRaster(TRaster32P raster) { + makeCurrent(); + glFlush(); - // and a bitmap image - m_offDIB = CreateDIBSection(m_offDC, &info, DIB_RGB_COLORS, &m_offData, NULL, 0); + int lx = raster->getLx(); + int ly = raster->getLy(); - assert(m_offDIB); - assert(m_offData); + raster->lock(); + glReadPixels(0, 0, lx, ly, GL_RGBA /*GL_BGRA_EXT*/, GL_UNSIGNED_BYTE, + raster->getRawData()); - if (!m_offDIB || !m_offData) - throw TException("cannot create OpenGL context. Check system resources!"); + swapRedBlueChannels(raster->getRawData(), lx * ly); + raster->unlock(); + } +}; - int dataSize = rasterSize.lx * rasterSize.ly * 4; // number of byte of raster +// default imp generator +std::shared_ptr defaultOfflineGLGenerator( + const TDimension &dim, std::shared_ptr shared) { + return std::make_shared(dim, shared); +} - memset(m_offData, 0, dataSize); +//============================================================================= +// XImplementation : implementazione offlineGL Server X (MACOSX & LINUX) +//----------------------------------------------------------------------------- - m_oldobj = SelectObject(m_offDC, m_offDIB); // select BIB to write +#elif defined(LINUX) - static PIXELFORMATDESCRIPTOR pfd = - { - sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd - 1, // version number - 0 | (false ? (PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER) : (PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI)) | PFD_SUPPORT_OPENGL, // support OpenGL - PFD_TYPE_RGBA, // RGBA type - 32, // 32-bit color depth - 0, 0, 0, 0, 0, 0, // color bits ignored - 8, // no alpha buffer /*===*/ - 0, // shift bit ignored - 0, // no accumulation buffer - 0, 0, 0, 0, // accum bits ignored - 32, // 32-bit z-buffer - 32, // max stencil buffer - 0, // no auxiliary buffer - PFD_MAIN_PLANE, // main layer - 0, // reserved - 0, 0, 0 // layer masks ignored - }; - - // get the best available match of pixel format for the device context - int iPixelFormat = ChoosePixelFormat(m_offDC, &pfd); - assert(iPixelFormat != 0); +class XImplementation : public TOfflineGL::Imp { +public: + Display *m_dpy; + GLXContext m_context; + GLXPixmap m_pixmap; + Pixmap m_xpixmap; + + //----------------------------------------------------------------------------- + + XImplementation(TDimension rasterSize) { + createContext(rasterSize); + + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); + } + + //----------------------------------------------------------------------------- + + ~XImplementation() { + glXDestroyContext(m_dpy, m_context); + m_context = 0; + safeGlXMakeCurrent(true); + XCloseDisplay(m_dpy); + } + + //----------------------------------------------------------------------------- + + bool safeGlXMakeCurrent(bool isDtor = false) { + static std::map m_glxContext; + static TThread::Mutex mutex; + + QMutexLocker sl(&mutex); + pthread_t self = pthread_self(); + std::map::iterator it = m_glxContext.find(self); + if (((it != m_glxContext.end()) && (it->second != m_context)) || + (it == m_glxContext.end())) { + // cout << "calling GLXMakeCurrent " << self << " " << m_context << + //endl; + Bool ret; + if (!isDtor) ret = glXMakeCurrent(m_dpy, m_pixmap, m_context); + m_glxContext[self] = m_context; + return ret; + } + // cout << "don't call GLXMakeCurrent " << self << " " << m_context << endl; + return true; + } - // make that the pixel format of the device context - int ret = SetPixelFormat(m_offDC, iPixelFormat, &pfd); - assert(ret == TRUE); + //----------------------------------------------------------------------------- - // make a valid context for OpenGL rendering + void makeCurrent() { + XScopedLock xsl; - m_hglRC = wglCreateContext(m_offDC); - assert(m_hglRC); + // Bool ret = glXMakeCurrent(m_dpy,m_pixmap,m_context); - if (!m_hglRC) - throw TException("cannot create OpenGL context. Check system resources!"); + Bool ret = safeGlXMakeCurrent(); + assert(ret == True); + } - if (shared) { - // Share shared's display lists - const WIN32Implementation *sharedImp = dynamic_cast(shared.get()); - assert(sharedImp); + //----------------------------------------------------------------------------- - bool ok = wglShareLists(sharedImp->m_hglRC, m_hglRC); - assert(ok); - } + // DA IMPLEMENTARE !!! - ret = wglMakeCurrent(m_offDC, m_hglRC); - assert(ret == TRUE); - } + void doneCurrent() {} - //----------------------------------------------------------------------------- + //----------------------------------------------------------------------------- - void swapRedBlueChannels(void *buffer, int bufferSize) // Flips The Red And Blue Bytes (WidthxHeight) - { - void *b = buffer; // Pointer To The Buffer + void createContext(TDimension rasterSize) { + m_dpy = XOpenDisplay(NULL); + Window win = DefaultRootWindow(m_dpy); + int attribList[] = {GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + // GLX_ALPHA_SIZE, 1, + GLX_STENCIL_SIZE, 8, -#ifdef x64 - int size = bufferSize; - UCHAR *pix = (UCHAR *)b; - while (size > 0) { - UCHAR r = *pix; - UCHAR b = *(pix + 2); - *pix = b; - *(pix + 2) = r; - pix += 4; - size--; - } -/*unsigned long ebx = (unsigned long)b; - while(size>0) - { - unsigned char al =__readgsbyte(ebx); - unsigned char ah =__readgsbyte(ebx+2); - __writegsbyte(ebx+2,al); - __writegsbyte(ebx,ah); - ebx+=4; - size--; - }*/ -#else - __asm // Assembler Code To Follow - { - mov ecx, bufferSize // Counter Set To Dimensions Of Our Memory Block - mov ebx, b // Points ebx To Our Data (b) - label: // Label Used For Looping - mov al,[ebx+0] // Loads Value At ebx Into al - mov ah,[ebx+2] // Loads Value At ebx+2 Into ah - mov [ebx+2],al // Stores Value In al At ebx+2 - mov [ebx+0],ah // Stores Value In ah At ebx - - add ebx,4 // Moves Through The Data By 4 Bytes - dec ecx // Decreases Our Loop Counter - jnz label // If Not Zero Jump Back To Label - } -#endif - } + // GLX_DEPTH_SIZE, 24, - //----------------------------------------------------------------------------- + None}; - void getRaster(TRaster32P raster) - { - makeCurrent(); - glFlush(); + int dbAttrib[] = {GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, + 1, GLX_BLUE_SIZE, 1, GLX_STENCIL_SIZE, + 8, GLX_DOUBLEBUFFER, None}; - int lx = raster->getLx(); - int ly = raster->getLy(); + int w = rasterSize.lx; + int h = rasterSize.ly; - raster->lock(); - glReadPixels(0, 0, lx, ly, - GL_RGBA /*GL_BGRA_EXT*/, GL_UNSIGNED_BYTE, - raster->getRawData()); + XVisualInfo *vis = glXChooseVisual(m_dpy, DefaultScreen(m_dpy), attribList); + if (!vis) { + std::cout << "unable to create sb visual" << std::endl; + vis = glXChooseVisual(m_dpy, DefaultScreen(m_dpy), dbAttrib); + assert(vis && "unable to create db visual"); + } - swapRedBlueChannels(raster->getRawData(), lx * ly); - raster->unlock(); - } -}; + m_context = glXCreateContext(m_dpy, vis, 0, False); + // std::cout << "Direct rendering: " << (glXIsDirect(m_dpy, m_context) ? + // "Yes" : "No" )<< std::endl; -// default imp generator -std::shared_ptr defaultOfflineGLGenerator(const TDimension &dim, std::shared_ptr shared) -{ - return std::make_shared(dim, shared); -} + if (!m_context) assert("not m_context" && false); + TRaster32P raster(w, h); -//============================================================================= -// XImplementation : implementazione offlineGL Server X (MACOSX & LINUX) -//----------------------------------------------------------------------------- + m_xpixmap = XCreatePixmap(m_dpy, win, w, h, vis->depth); -#elif defined(LINUX) + assert(m_xpixmap && "not m_xpixmap"); -class XImplementation : public TOfflineGL::Imp -{ -public: - Display *m_dpy; - GLXContext m_context; - GLXPixmap m_pixmap; - Pixmap m_xpixmap; - - //----------------------------------------------------------------------------- - - XImplementation(TDimension rasterSize) - { - createContext(rasterSize); - - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT); - } - - //----------------------------------------------------------------------------- - - ~XImplementation() - { - glXDestroyContext(m_dpy, m_context); - m_context = 0; - safeGlXMakeCurrent(true); - XCloseDisplay(m_dpy); - } - - //----------------------------------------------------------------------------- - - bool safeGlXMakeCurrent(bool isDtor = false) - { - static std::map m_glxContext; - static TThread::Mutex mutex; - - QMutexLocker sl(&mutex); - pthread_t self = pthread_self(); - std::map::iterator it = m_glxContext.find(self); - if (((it != m_glxContext.end()) && (it->second != m_context)) || (it == m_glxContext.end())) { - // cout << "calling GLXMakeCurrent " << self << " " << m_context << endl; - Bool ret; - if (!isDtor) - ret = glXMakeCurrent(m_dpy, m_pixmap, m_context); - m_glxContext[self] = m_context; - return ret; - } - // cout << "don't call GLXMakeCurrent " << self << " " << m_context << endl; - return true; - } - - //----------------------------------------------------------------------------- - - void makeCurrent() - { - XScopedLock xsl; - - //Bool ret = glXMakeCurrent(m_dpy,m_pixmap,m_context); - - Bool ret = safeGlXMakeCurrent(); - assert(ret == True); - } - - //----------------------------------------------------------------------------- - - // DA IMPLEMENTARE !!! - - void doneCurrent() - { - } - - //----------------------------------------------------------------------------- - - void createContext(TDimension rasterSize) - { - m_dpy = XOpenDisplay(NULL); - Window win = DefaultRootWindow(m_dpy); - int attribList[] = { - GLX_RGBA, - GLX_RED_SIZE, 1, - GLX_GREEN_SIZE, 1, - GLX_BLUE_SIZE, 1, - // GLX_ALPHA_SIZE, 1, - GLX_STENCIL_SIZE, 8, - - // GLX_DEPTH_SIZE, 24, - - None}; - - int dbAttrib[] = {GLX_RGBA, - GLX_RED_SIZE, 1, - GLX_GREEN_SIZE, 1, - GLX_BLUE_SIZE, 1, - GLX_STENCIL_SIZE, 8, - GLX_DOUBLEBUFFER, - None}; - - int w = rasterSize.lx; - int h = rasterSize.ly; - - XVisualInfo *vis = glXChooseVisual(m_dpy, DefaultScreen(m_dpy), attribList); - if (!vis) { - std::cout << "unable to create sb visual" << std::endl; - vis = glXChooseVisual(m_dpy, DefaultScreen(m_dpy), dbAttrib); - assert(vis && "unable to create db visual"); - } - - m_context = glXCreateContext(m_dpy, vis, 0, False); - // std::cout << "Direct rendering: " << (glXIsDirect(m_dpy, m_context) ? "Yes" : "No" )<< std::endl; - - if (!m_context) - assert("not m_context" && false); - TRaster32P raster(w, h); - - m_xpixmap = XCreatePixmap(m_dpy, win, w, h, vis->depth); - - assert(m_xpixmap && "not m_xpixmap"); - - m_pixmap = glXCreateGLXPixmap(m_dpy, vis, m_xpixmap); - if (!m_pixmap) - assert("not m_pixmap" && m_pixmap); - /* - Bool ret = glXMakeCurrent(m_dpy, - m_pixmap, - m_context); + m_pixmap = glXCreateGLXPixmap(m_dpy, vis, m_xpixmap); + if (!m_pixmap) assert("not m_pixmap" && m_pixmap); + /* +Bool ret = glXMakeCurrent(m_dpy, + m_pixmap, + m_context); */ - Bool ret = safeGlXMakeCurrent(); - assert(ret); + Bool ret = safeGlXMakeCurrent(); + assert(ret); - m_raster = raster; - } + m_raster = raster; + } //----------------------------------------------------------------------------- #if defined(MACOSX) #if defined(powerpc) - void rightRotateBits(UCHAR *buf, int bufferSize) - { - UINT *buffer = (UINT *)buf; - UINT app; - for (int i = 0; i < bufferSize; i++, buffer++) { - app = *buffer; - *buffer = app >> 8 | app << 24; - } - } + void rightRotateBits(UCHAR *buf, int bufferSize) { + UINT *buffer = (UINT *)buf; + UINT app; + for (int i = 0; i < bufferSize; i++, buffer++) { + app = *buffer; + *buffer = app >> 8 | app << 24; + } + } #else - void rightRotateBits(UCHAR *buf, int bufferSize) - { - UINT *buffer = (UINT *)buf; - UINT app; - for (int i = 0; i < bufferSize; i++, buffer++) { - app = *buffer; - *buffer = (app >> 16 & 0x000000ff) | (app << 16 & 0x00ff0000) | (app & 0xff00ff00); - } - } + void rightRotateBits(UCHAR *buf, int bufferSize) { + UINT *buffer = (UINT *)buf; + UINT app; + for (int i = 0; i < bufferSize; i++, buffer++) { + app = *buffer; + *buffer = (app >> 16 & 0x000000ff) | (app << 16 & 0x00ff0000) | + (app & 0xff00ff00); + } + } #endif #endif - //----------------------------------------------------------------------------- + //----------------------------------------------------------------------------- - const TRaster32P &getRaster() - { - makeCurrent(); - glFlush(); + const TRaster32P &getRaster() { + makeCurrent(); + glFlush(); - int lx = m_raster->getLx(); - int ly = m_raster->getLy(); - m_raster->lock(); - glReadPixels(0, 0, lx, ly, - GL_RGBA /*GL_BGRA_EXT*/, GL_UNSIGNED_BYTE, - m_raster->getRawData()); + int lx = m_raster->getLx(); + int ly = m_raster->getLy(); + m_raster->lock(); + glReadPixels(0, 0, lx, ly, GL_RGBA /*GL_BGRA_EXT*/, GL_UNSIGNED_BYTE, + m_raster->getRawData()); #if defined(MACOSX) - rightRotateBits(m_raster->getRawData(), lx * ly); + rightRotateBits(m_raster->getRawData(), lx * ly); #warning "to do" #endif - m_raster->unlock(); - return m_raster; - } + m_raster->unlock(); + return m_raster; + } - //----------------------------------------------------------------------------- + //----------------------------------------------------------------------------- - int getLx() const - { - return m_raster->getLx(); - } + int getLx() const { return m_raster->getLx(); } - //----------------------------------------------------------------------------- + //----------------------------------------------------------------------------- - int getLy() const - { - return m_raster->getLy(); - } + int getLy() const { return m_raster->getLy(); } }; -std::shared_ptr defaultOfflineGLGenerator(const TDimension &dim, std::shared_ptr shared) -{ - return std::make_shared(dim); +std::shared_ptr defaultOfflineGLGenerator( + const TDimension &dim, std::shared_ptr shared) { + return std::make_shared(dim); } #elif MACOSX -std::shared_ptr defaultOfflineGLGenerator(const TDimension &dim, std::shared_ptr shared) -{ - return std::make_shared(dim, shared); +std::shared_ptr defaultOfflineGLGenerator( + const TDimension &dim, std::shared_ptr shared) { + return std::make_shared(dim, shared); } #endif @@ -521,425 +497,392 @@ std::shared_ptr defaultOfflineGLGenerator(const TDimension &dim //----------------------------------------------------------------------------- // current imp generator -namespace -{ +namespace { TOfflineGL::ImpGenerator *currentImpGenerator = defaultOfflineGLGenerator; -} // namespace +} // namespace //============================================================================= // TOfflineGL //----------------------------------------------------------------------------- -//namespace { +// namespace { -class MessageCreateContext : public TThread::Message -{ - friend class TOfflineGL; +class MessageCreateContext : public TThread::Message { + friend class TOfflineGL; - TOfflineGL *m_ogl; - TDimension m_size; - std::shared_ptr m_shared; + TOfflineGL *m_ogl; + TDimension m_size; + std::shared_ptr m_shared; public: - MessageCreateContext(TOfflineGL *ogl, const TDimension &size, std::shared_ptr shared) - : m_ogl(ogl), m_size(size), m_shared(std::move(shared)) {} - - void onDeliver() - { - m_ogl->m_imp = currentImpGenerator(m_size, m_shared); - } - - TThread::Message *clone() const - { - return new MessageCreateContext(*this); - } + MessageCreateContext(TOfflineGL *ogl, const TDimension &size, + std::shared_ptr shared) + : m_ogl(ogl), m_size(size), m_shared(std::move(shared)) {} + + void onDeliver() { m_ogl->m_imp = currentImpGenerator(m_size, m_shared); } + + TThread::Message *clone() const { return new MessageCreateContext(*this); } }; //} // namespace //-------------------------------------------------- -TOfflineGL::TOfflineGL(TDimension dim, const TOfflineGL *shared) -{ +TOfflineGL::TOfflineGL(TDimension dim, const TOfflineGL *shared) { #if defined(LINUX) - XScopedLock xsl; + XScopedLock xsl; #endif - std::shared_ptr sharedImp = shared ? shared->m_imp : 0; + std::shared_ptr sharedImp = shared ? shared->m_imp : 0; - /* - 元のコードは(別スレッドから呼び出すための) offline renderer を作って main thread に dispatch するという訳のわからないことをしていたが Q*GLContext は thread context を超えられないので直接生成してこのコンテキストで閉じる. - 別スレッドには dispatch しない. - */ - m_imp = currentImpGenerator(dim, std::move(sharedImp)); + /* + 元のコードは(別スレッドから呼び出すための) offline renderer を作って main + thread に dispatch するという訳のわからないことをしていたが Q*GLContext は + thread context を超えられないので直接生成してこのコンテキストで閉じる. + 別スレッドには dispatch しない. +*/ + m_imp = currentImpGenerator(dim, std::move(sharedImp)); - initMatrix(); + initMatrix(); } //----------------------------------------------------------------------------- -TOfflineGL::TOfflineGL(const TRaster32P &raster, const TOfflineGL *shared) -{ +TOfflineGL::TOfflineGL(const TRaster32P &raster, const TOfflineGL *shared) { #if defined(LINUX) - XScopedLock xsl; + XScopedLock xsl; #endif - m_imp = currentImpGenerator(raster->getSize(), shared->m_imp); + m_imp = currentImpGenerator(raster->getSize(), shared->m_imp); - initMatrix(); + initMatrix(); - glRasterPos2d(0, 0); - raster->lock(); - glDrawPixels(raster->getLx(), raster->getLy(), GL_BGRA_EXT, GL_UNSIGNED_BYTE, raster->getRawData()); - raster->unlock(); + glRasterPos2d(0, 0); + raster->lock(); + glDrawPixels(raster->getLx(), raster->getLy(), GL_BGRA_EXT, GL_UNSIGNED_BYTE, + raster->getRawData()); + raster->unlock(); } //----------------------------------------------------------------------------- -TOfflineGL::~TOfflineGL() -{ -} +TOfflineGL::~TOfflineGL() {} //----------------------------------------------------------------------------- -TOfflineGL::ImpGenerator *TOfflineGL::defineImpGenerator(TOfflineGL::ImpGenerator *impGenerator) -{ - TOfflineGL::ImpGenerator *ret = currentImpGenerator; - currentImpGenerator = impGenerator; - return ret; +TOfflineGL::ImpGenerator *TOfflineGL::defineImpGenerator( + TOfflineGL::ImpGenerator *impGenerator) { + TOfflineGL::ImpGenerator *ret = currentImpGenerator; + currentImpGenerator = impGenerator; + return ret; } //----------------------------------------------------------------------------- -void TOfflineGL::makeCurrent() -{ - if (currentContextManager) - currentContextManager->store(); - // Tutto il codice è stato spostato dentro Imp - m_imp->makeCurrent(); - assert(glGetError() == GL_NO_ERROR); +void TOfflineGL::makeCurrent() { + if (currentContextManager) currentContextManager->store(); + // Tutto il codice è stato spostato dentro Imp + m_imp->makeCurrent(); + assert(glGetError() == GL_NO_ERROR); } //----------------------------------------------------------------------------- -void TOfflineGL::doneCurrent() -{ - m_imp->doneCurrent(); - if (currentContextManager) { - currentContextManager->restore(); - } +void TOfflineGL::doneCurrent() { + m_imp->doneCurrent(); + if (currentContextManager) { + currentContextManager->restore(); + } } //----------------------------------------------------------------------------- -void TOfflineGL::initMatrix() -{ - m_imp->makeCurrent(); +void TOfflineGL::initMatrix() { + m_imp->makeCurrent(); - // cfr. help: OpenGL/Programming tip/OpenGL Correctness Tips - glViewport(0, 0, m_imp->getLx(), m_imp->getLy()); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluOrtho2D(0, m_imp->getLx(), 0, m_imp->getLy()); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - //glTranslatef(0.375, 0.375, 0.0); //WRONG + // cfr. help: OpenGL/Programming tip/OpenGL Correctness Tips + glViewport(0, 0, m_imp->getLx(), m_imp->getLy()); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluOrtho2D(0, m_imp->getLx(), 0, m_imp->getLy()); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + // glTranslatef(0.375, 0.375, 0.0); //WRONG - /* (From Daniele) + /* (From Daniele) Quoting from the aforementioned source: -"An optimum compromise that allows all primitives to be specified at integer -positions, while still ensuring predictable rasterization, is to translate x -and y by 0.375, as shown in the following code sample. Such a translation -keeps polygon and pixel image edges safely away from the centers of pixels, +"An optimum compromise that allows all primitives to be specified at integer +positions, while still ensuring predictable rasterization, is to translate x +and y by 0.375, as shown in the following code sample. Such a translation +keeps polygon and pixel image edges safely away from the centers of pixels, while moving line vertices close enough to the pixel centers" - NOTE: This is not an acceptable excuse in our case - as we're NOT USING - INTEGER COORDINATES ONLY. OpenGL has all the rights to render pixels - at integer coordinates across the neighbouring 4 pixels - and their - (0.5, 0.5) translations at the EXACT screen pixel. - */ +NOTE: This is not an acceptable excuse in our case - as we're NOT USING + INTEGER COORDINATES ONLY. OpenGL has all the rights to render pixels + at integer coordinates across the neighbouring 4 pixels - and their + (0.5, 0.5) translations at the EXACT screen pixel. +*/ } //----------------------------------------------------------------------------- -void TOfflineGL::clear(TPixel32 color) -{ - const double maxValue = 255.0; - makeCurrent(); - glClearColor( - (double)color.r / maxValue, - (double)color.g / maxValue, - (double)color.b / maxValue, - (double)color.m / maxValue); - glClear(GL_COLOR_BUFFER_BIT); +void TOfflineGL::clear(TPixel32 color) { + const double maxValue = 255.0; + makeCurrent(); + glClearColor((double)color.r / maxValue, (double)color.g / maxValue, + (double)color.b / maxValue, (double)color.m / maxValue); + glClear(GL_COLOR_BUFFER_BIT); } //----------------------------------------------------------------------------- -void TOfflineGL::draw(TVectorImageP image, const TVectorRenderData &rd, bool doInitMatrix) -{ - checkErrorsByGL; - makeCurrent(); - checkErrorsByGL; - - if (doInitMatrix) { - initMatrix(); - checkErrorsByGL; - } - - if (image) { - checkErrorsByGL; - tglDraw(rd, image.getPointer()); - checkErrorsByGL; - } - - checkErrorsByGL; - glFlush(); - checkErrorsByGL; +void TOfflineGL::draw(TVectorImageP image, const TVectorRenderData &rd, + bool doInitMatrix) { + checkErrorsByGL; + makeCurrent(); + checkErrorsByGL; + + if (doInitMatrix) { + initMatrix(); + checkErrorsByGL; + } + + if (image) { + checkErrorsByGL; + tglDraw(rd, image.getPointer()); + checkErrorsByGL; + } + + checkErrorsByGL; + glFlush(); + checkErrorsByGL; } //----------------------------------------------------------------------------- -void TOfflineGL::draw(TRasterImageP ri, const TAffine &aff, bool doInitMatrix) -{ - makeCurrent(); - - if (doInitMatrix) - initMatrix(); - - TRaster32P ras32 = ri->getRaster(); - if (!ras32) - return; - - int lx = ras32->getLx(); - int ly = ras32->getLy(); - // lx e ly devono essere potenze di due - assert((lx & (lx - 1)) == 0); - assert((ly & (ly - 1)) == 0); - - glPushMatrix(); - tglMultMatrix(aff); - - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - - glTexEnvf(GL_TEXTURE_ENV, - GL_TEXTURE_ENV_MODE, - GL_DECAL); - - glEnable(GL_TEXTURE_2D); - - /* - TNZ_MACHINE_CHANNEL_ORDER_BGRM - TNZ_MACHINE_CHANNEL_ORDER_MBGR - TNZ_MACHINE_CHANNEL_ORDER_RGBM - TNZ_MACHINE_CHANNEL_ORDER_MRGB - */ - - GLenum fmt = TGL_FMT; - /* - #ifdef TNZ_MACHINE_CHANNEL_ORDER_BGRM - GL_BGRA_EXT; - #elif TNZ_MACHINE_CHANNEL_ORDER_MBGR - GL_ABGR_EXT; - #elif TNZ_MACHINE_CHANNEL_ORDER_RGBM - GL_RGBA; - #elif TNZ_MACHINE_CHANNEL_ORDER_MRGB - #warning "to do" - GL_ABGR_EXT; - #else - Error PLATFORM NOT SUPPORTED - #endif +void TOfflineGL::draw(TRasterImageP ri, const TAffine &aff, bool doInitMatrix) { + makeCurrent(); + + if (doInitMatrix) initMatrix(); + + TRaster32P ras32 = ri->getRaster(); + if (!ras32) return; + + int lx = ras32->getLx(); + int ly = ras32->getLy(); + // lx e ly devono essere potenze di due + assert((lx & (lx - 1)) == 0); + assert((ly & (ly - 1)) == 0); + + glPushMatrix(); + tglMultMatrix(aff); + + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); + + glEnable(GL_TEXTURE_2D); + + /* +TNZ_MACHINE_CHANNEL_ORDER_BGRM +TNZ_MACHINE_CHANNEL_ORDER_MBGR +TNZ_MACHINE_CHANNEL_ORDER_RGBM +TNZ_MACHINE_CHANNEL_ORDER_MRGB +*/ + + GLenum fmt = TGL_FMT; + /* +#ifdef TNZ_MACHINE_CHANNEL_ORDER_BGRM +GL_BGRA_EXT; +#elif TNZ_MACHINE_CHANNEL_ORDER_MBGR +GL_ABGR_EXT; +#elif TNZ_MACHINE_CHANNEL_ORDER_RGBM +GL_RGBA; +#elif TNZ_MACHINE_CHANNEL_ORDER_MRGB +#warning "to do" +GL_ABGR_EXT; +#else +Error PLATFORM NOT SUPPORTED +#endif */ - // Generate a texture id and bind it. - GLuint texId; - glGenTextures(1, &texId); - - glBindTexture(GL_TEXTURE_2D, texId); - - glPixelStorei(GL_UNPACK_ROW_LENGTH, - ras32->getWrap() != ras32->getLx() ? ras32->getWrap() : 0); - - ras32->lock(); - - glTexImage2D( - GL_TEXTURE_2D, // target (is a 2D texture) - 0, // is one level only - GL_RGB, // number of component of a pixel - lx, // size width - ly, // height - 0, // size of a border - fmt, - GL_UNSIGNED_BYTE, // - ras32->getRawData()); - - ras32->unlock(); - - double halfWidth = 0.5 * lx; - double halfHeight = 0.5 * ly; - - double dpix = 1, dpiy = 1; - ri->getDpi(dpix, dpiy); - - if (dpix != 0 && dpiy != 0) { - double unit = 100; - halfWidth *= unit / dpix; - halfHeight *= unit / dpiy; - } - - glBegin(GL_QUAD_STRIP); - glTexCoord2d(0, 0); - glVertex2d(-halfWidth, -halfHeight); - glTexCoord2d(1, 0); - glVertex2d(halfWidth, -halfHeight); - glTexCoord2d(0, 1); - glVertex2d(-halfWidth, halfHeight); - glTexCoord2d(1, 1); - glVertex2d(halfWidth, halfHeight); - glEnd(); - glDisable(GL_TEXTURE_2D); - - glPopMatrix(); - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - - // Delete texture - glDeleteTextures(1, &texId); - - glFlush(); + // Generate a texture id and bind it. + GLuint texId; + glGenTextures(1, &texId); + + glBindTexture(GL_TEXTURE_2D, texId); + + glPixelStorei(GL_UNPACK_ROW_LENGTH, + ras32->getWrap() != ras32->getLx() ? ras32->getWrap() : 0); + + ras32->lock(); + + glTexImage2D(GL_TEXTURE_2D, // target (is a 2D texture) + 0, // is one level only + GL_RGB, // number of component of a pixel + lx, // size width + ly, // height + 0, // size of a border + fmt, + GL_UNSIGNED_BYTE, // + ras32->getRawData()); + + ras32->unlock(); + + double halfWidth = 0.5 * lx; + double halfHeight = 0.5 * ly; + + double dpix = 1, dpiy = 1; + ri->getDpi(dpix, dpiy); + + if (dpix != 0 && dpiy != 0) { + double unit = 100; + halfWidth *= unit / dpix; + halfHeight *= unit / dpiy; + } + + glBegin(GL_QUAD_STRIP); + glTexCoord2d(0, 0); + glVertex2d(-halfWidth, -halfHeight); + glTexCoord2d(1, 0); + glVertex2d(halfWidth, -halfHeight); + glTexCoord2d(0, 1); + glVertex2d(-halfWidth, halfHeight); + glTexCoord2d(1, 1); + glVertex2d(halfWidth, halfHeight); + glEnd(); + glDisable(GL_TEXTURE_2D); + + glPopMatrix(); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + + // Delete texture + glDeleteTextures(1, &texId); + + glFlush(); } //----------------------------------------------------------------------------- -void TOfflineGL::flush() -{ - makeCurrent(); - glFlush(); +void TOfflineGL::flush() { + makeCurrent(); + glFlush(); } //----------------------------------------------------------------------------- -void TOfflineGL::getRaster(TRaster32P raster) -{ - assert(raster->getLx() <= getLx() && raster->getLy() <= getLy()); - if (raster->getWrap() == raster->getLx()) { - m_imp->getRaster(raster); - } else { - //There are 2 possible solutions: use glReadPixels multiple times for each row of input raster, - //OR allocate a new contiguous buffer, use glReadPixels once, and then memcpy each row. - //It actually seems that the *latter* is actually the fastest solution, although it requires - //allocating a temporary buffer of the same size of the requested raster... - //I also could not actually manage to make the former work - the code seemed right but results were weird... - TRaster32P ras32(raster->getSize()); - m_imp->getRaster(ras32); - TRop::copy(raster, ras32); - } +void TOfflineGL::getRaster(TRaster32P raster) { + assert(raster->getLx() <= getLx() && raster->getLy() <= getLy()); + if (raster->getWrap() == raster->getLx()) { + m_imp->getRaster(raster); + } else { + // There are 2 possible solutions: use glReadPixels multiple times for each + // row of input raster, + // OR allocate a new contiguous buffer, use glReadPixels once, and then + // memcpy each row. + // It actually seems that the *latter* is actually the fastest solution, + // although it requires + // allocating a temporary buffer of the same size of the requested raster... + // I also could not actually manage to make the former work - the code + // seemed right but results were weird... + TRaster32P ras32(raster->getSize()); + m_imp->getRaster(ras32); + TRop::copy(raster, ras32); + } } //----------------------------------------------------------------------------- -void TOfflineGL::getRaster(TRasterP raster) -{ - assert(raster->getLx() <= getLx() && raster->getLy() <= getLy()); - TRaster32P ras32 = raster; - if (ras32 && (raster->getWrap() == raster->getLx())) { - m_imp->getRaster(ras32); - } else { - ras32 = TRaster32P(raster->getSize()); - m_imp->getRaster(ras32); - TRop::copy(raster, ras32); - } +void TOfflineGL::getRaster(TRasterP raster) { + assert(raster->getLx() <= getLx() && raster->getLy() <= getLy()); + TRaster32P ras32 = raster; + if (ras32 && (raster->getWrap() == raster->getLx())) { + m_imp->getRaster(ras32); + } else { + ras32 = TRaster32P(raster->getSize()); + m_imp->getRaster(ras32); + TRop::copy(raster, ras32); + } } //----------------------------------------------------------------------------- -TRaster32P TOfflineGL::getRaster() -{ - TRaster32P raster(getLx(), getLy()); - m_imp->getRaster(raster); - return raster; +TRaster32P TOfflineGL::getRaster() { + TRaster32P raster(getLx(), getLy()); + m_imp->getRaster(raster); + return raster; } //----------------------------------------------------------------------------- -int TOfflineGL::getLx() const -{ - return m_imp->getLx(); -} +int TOfflineGL::getLx() const { return m_imp->getLx(); } //----------------------------------------------------------------------------- -int TOfflineGL::getLy() const -{ - return m_imp->getLy(); -} +int TOfflineGL::getLy() const { return m_imp->getLy(); } //----------------------------------------------------------------------------- //============================================================================= -namespace -{ +namespace { -struct DimensionLess : public std::binary_function { - bool operator()(const TDimension &d1, const TDimension &d2) const - { - return d1.lx < d2.lx || (d1.lx == d2.lx && d1.ly < d2.ly); - } +struct DimensionLess + : public std::binary_function { + bool operator()(const TDimension &d1, const TDimension &d2) const { + return d1.lx < d2.lx || (d1.lx == d2.lx && d1.ly < d2.ly); + } }; //----------------------------------------------------------------------------- -class OglStock -{ // singleton +class OglStock { // singleton - typedef std::map ContextMap; - ContextMap m_table; + typedef std::map ContextMap; + ContextMap m_table; - OglStock() {} + OglStock() {} public: - ~OglStock() - { - /* // PER ADESSO, LASCIAMO IL MEMORY LEAK DATO CHE ALTRIMENTI VA IN CRASH - ContextMap::iterator it = m_table.begin(); - for(; it!=m_table.end(); ++it) - { - delete it->second; + ~OglStock() { + /* // PER ADESSO, LASCIAMO IL MEMORY LEAK DATO CHE ALTRIMENTI VA IN CRASH +ContextMap::iterator it = m_table.begin(); +for(; it!=m_table.end(); ++it) +{ +delete it->second; +} +*/ + } + + TOfflineGL *get(const TDimension &d) { + ContextMap::iterator it = m_table.find(d); + if (it == m_table.end()) { + TOfflineGL *glContext; + glContext = new TOfflineGL(d); + pair result = + m_table.insert(ContextMap::value_type(d, glContext)); + assert(result.second); + assert(m_table.size() < 15); + return glContext; } - */ - } - - TOfflineGL *get(const TDimension &d) - { - ContextMap::iterator it = m_table.find(d); - if (it == m_table.end()) { - TOfflineGL *glContext; - glContext = new TOfflineGL(d); - pair result = m_table.insert(ContextMap::value_type(d, glContext)); - assert(result.second); - assert(m_table.size() < 15); - return glContext; - } - return it->second; - } - - static OglStock *instance() - { - static OglStock singleton; - return &singleton; - } + return it->second; + } + + static OglStock *instance() { + static OglStock singleton; + return &singleton; + } }; -} // namespace +} // namespace //----------------------------------------------------------------------------- -TOfflineGL *TOfflineGL::getStock(const TDimension dim) -{ - return OglStock::instance()->get(dim); +TOfflineGL *TOfflineGL::getStock(const TDimension dim) { + return OglStock::instance()->get(dim); } diff --git a/toonz/sources/common/tvrender/tpalette.cpp b/toonz/sources/common/tvrender/tpalette.cpp index a348de3..7984f70 100644 --- a/toonz/sources/common/tvrender/tpalette.cpp +++ b/toonz/sources/common/tvrender/tpalette.cpp @@ -26,12 +26,11 @@ DEFINE_CLASS_CODE(TPalette, 30) // Local namespace stuff //************************************************************************************* -namespace -{ +namespace { const int maxStyleIndex = 32765; -} // namespace +} // namespace //=================================================================== // @@ -40,143 +39,120 @@ const int maxStyleIndex = 32765; //------------------------------------------------------------------- TPalette::Page::Page(std::wstring name) - : m_name(name), m_index(-1), m_palette(0) -{ -} + : m_name(name), m_index(-1), m_palette(0) {} //------------------------------------------------------------------- -TColorStyle *TPalette::Page::getStyle(int index) const -{ - assert(m_palette); - if (0 <= index && index < getStyleCount()) - return m_palette->getStyle(m_styleIds[index]); - else - return 0; +TColorStyle *TPalette::Page::getStyle(int index) const { + assert(m_palette); + if (0 <= index && index < getStyleCount()) + return m_palette->getStyle(m_styleIds[index]); + else + return 0; } //------------------------------------------------------------------- -int TPalette::Page::getStyleId(int index) const -{ - assert(m_palette); - if (0 <= index && index < getStyleCount()) - return m_styleIds[index]; - else - return -1; +int TPalette::Page::getStyleId(int index) const { + assert(m_palette); + if (0 <= index && index < getStyleCount()) + return m_styleIds[index]; + else + return -1; } //------------------------------------------------------------------- -int TPalette::Page::addStyle(int styleId) -{ - assert(m_palette); - if (styleId < 0 || styleId >= m_palette->getStyleCount()) - return -1; - if (m_palette->m_styles[styleId].first != 0) - return -1; - m_palette->m_styles[styleId].first = this; - int indexInPage = int(m_styleIds.size()); - m_styleIds.push_back(styleId); - return indexInPage; +int TPalette::Page::addStyle(int styleId) { + assert(m_palette); + if (styleId < 0 || styleId >= m_palette->getStyleCount()) return -1; + if (m_palette->m_styles[styleId].first != 0) return -1; + m_palette->m_styles[styleId].first = this; + int indexInPage = int(m_styleIds.size()); + m_styleIds.push_back(styleId); + return indexInPage; } //------------------------------------------------------------------- -int TPalette::Page::addStyle(TColorStyle *style) -{ - assert(m_palette); - int stylesCount = int(m_palette->m_styles.size()); - int styleId; - for (styleId = 0; styleId < stylesCount; styleId++) - if (m_palette->m_styles[styleId].first == 0) - break; - if (styleId >= stylesCount - 1) - return addStyle(m_palette->addStyle(style)); - m_palette->setStyle(styleId, style); - return addStyle(styleId); +int TPalette::Page::addStyle(TColorStyle *style) { + assert(m_palette); + int stylesCount = int(m_palette->m_styles.size()); + int styleId; + for (styleId = 0; styleId < stylesCount; styleId++) + if (m_palette->m_styles[styleId].first == 0) break; + if (styleId >= stylesCount - 1) return addStyle(m_palette->addStyle(style)); + m_palette->setStyle(styleId, style); + return addStyle(styleId); } //------------------------------------------------------------------- -int TPalette::Page::addStyle(TPixel32 color) -{ - return addStyle(new TSolidColorStyle(color)); +int TPalette::Page::addStyle(TPixel32 color) { + return addStyle(new TSolidColorStyle(color)); } //------------------------------------------------------------------- -void TPalette::Page::insertStyle(int indexInPage, int styleId) -{ - assert(m_palette); - if (styleId < 0 || styleId >= m_palette->getStyleCount()) - return; - if (m_palette->m_styles[styleId].first != 0) - return; - m_palette->m_styles[styleId].first = this; - if (indexInPage < 0) - indexInPage = 0; - else if (indexInPage > getStyleCount()) - indexInPage = getStyleCount(); - m_styleIds.insert(m_styleIds.begin() + indexInPage, styleId); +void TPalette::Page::insertStyle(int indexInPage, int styleId) { + assert(m_palette); + if (styleId < 0 || styleId >= m_palette->getStyleCount()) return; + if (m_palette->m_styles[styleId].first != 0) return; + m_palette->m_styles[styleId].first = this; + if (indexInPage < 0) + indexInPage = 0; + else if (indexInPage > getStyleCount()) + indexInPage = getStyleCount(); + m_styleIds.insert(m_styleIds.begin() + indexInPage, styleId); } //------------------------------------------------------------------- -void TPalette::Page::insertStyle(int indexInPage, TColorStyle *style) -{ - assert(m_palette); - int styleId = m_palette->addStyle(style); - if (styleId >= 0) - insertStyle(indexInPage, styleId); +void TPalette::Page::insertStyle(int indexInPage, TColorStyle *style) { + assert(m_palette); + int styleId = m_palette->addStyle(style); + if (styleId >= 0) insertStyle(indexInPage, styleId); } //------------------------------------------------------------------- -void TPalette::Page::insertStyle(int indexInPage, TPixel32 color) -{ - assert(m_palette); - int styleId = m_palette->addStyle(color); - if (styleId >= 0) - insertStyle(indexInPage, styleId); +void TPalette::Page::insertStyle(int indexInPage, TPixel32 color) { + assert(m_palette); + int styleId = m_palette->addStyle(color); + if (styleId >= 0) insertStyle(indexInPage, styleId); } //------------------------------------------------------------------- -void TPalette::Page::removeStyle(int indexInPage) -{ - if (indexInPage < 0 || indexInPage >= getStyleCount()) - return; - assert(m_palette); - int styleId = getStyleId(indexInPage); - assert(0 <= styleId && styleId < m_palette->getStyleCount()); - assert(m_palette->m_styles[styleId].first == this); - m_palette->m_styles[styleId].first = 0; - m_styleIds.erase(m_styleIds.begin() + indexInPage); +void TPalette::Page::removeStyle(int indexInPage) { + if (indexInPage < 0 || indexInPage >= getStyleCount()) return; + assert(m_palette); + int styleId = getStyleId(indexInPage); + assert(0 <= styleId && styleId < m_palette->getStyleCount()); + assert(m_palette->m_styles[styleId].first == this); + m_palette->m_styles[styleId].first = 0; + m_styleIds.erase(m_styleIds.begin() + indexInPage); } //------------------------------------------------------------------- -int TPalette::Page::search(int styleId) const -{ - std::vector::const_iterator it = - std::find(m_styleIds.begin(), m_styleIds.end(), styleId); - if (it == m_styleIds.end()) - return -1; - else - return it - m_styleIds.begin(); +int TPalette::Page::search(int styleId) const { + std::vector::const_iterator it = + std::find(m_styleIds.begin(), m_styleIds.end(), styleId); + if (it == m_styleIds.end()) + return -1; + else + return it - m_styleIds.begin(); } //------------------------------------------------------------------- -int TPalette::Page::search(TColorStyle *style) const -{ - assert(style); - assert(m_palette); - for (int i = 0; i < getStyleCount(); i++) - if (m_palette->getStyle(m_styleIds[i]) == style) - return i; - return -1; +int TPalette::Page::search(TColorStyle *style) const { + assert(style); + assert(m_palette); + for (int i = 0; i < getStyleCount(); i++) + if (m_palette->getStyle(m_styleIds[i]) == style) return i; + return -1; } //=================================================================== @@ -186,273 +162,250 @@ int TPalette::Page::search(TColorStyle *style) const //------------------------------------------------------------------- TPalette::TPalette() - : m_version(0), m_isCleanupPalette(false), m_currentFrame(-1), m_dirtyFlag(false), m_mutex(QMutex::Recursive), m_isLocked(false), m_askOverwriteFlag(false) -{ - QString tempName(QObject::tr("colors")); - std::wstring pageName = tempName.toStdWString(); - Page *page = addPage(pageName); - page->addStyle(TPixel32(255, 255, 255, 0)); - page->addStyle(TPixel32(0, 0, 0, 255)); - getStyle(0)->setName(L"color_0"); - getStyle(1)->setName(L"color_1"); - - for (int i = 0; i < 10; i++) - m_shortcuts['0' + i] = i; + : m_version(0) + , m_isCleanupPalette(false) + , m_currentFrame(-1) + , m_dirtyFlag(false) + , m_mutex(QMutex::Recursive) + , m_isLocked(false) + , m_askOverwriteFlag(false) { + QString tempName(QObject::tr("colors")); + std::wstring pageName = tempName.toStdWString(); + Page *page = addPage(pageName); + page->addStyle(TPixel32(255, 255, 255, 0)); + page->addStyle(TPixel32(0, 0, 0, 255)); + getStyle(0)->setName(L"color_0"); + getStyle(1)->setName(L"color_1"); + + for (int i = 0; i < 10; i++) m_shortcuts['0' + i] = i; } //------------------------------------------------------------------- -TPalette::~TPalette() -{ - std::set table; - int i = 0; - for (i = 0; i < getStyleCount(); i++) { - assert(table.find(getStyle(i)) == table.end()); - table.insert(getStyle(i)); - } - clearPointerContainer(m_pages); +TPalette::~TPalette() { + std::set table; + int i = 0; + for (i = 0; i < getStyleCount(); i++) { + assert(table.find(getStyle(i)) == table.end()); + table.insert(getStyle(i)); + } + clearPointerContainer(m_pages); } //------------------------------------------------------------------- -TPalette *TPalette::clone() const -{ - TPalette *palette = new TPalette; - palette->assign(this); - return palette; +TPalette *TPalette::clone() const { + TPalette *palette = new TPalette; + palette->assign(this); + return palette; } //------------------------------------------------------------------- -TColorStyle *TPalette::getStyle(int index) const -{ - if (0 <= index && index < getStyleCount()) - return m_styles[index].second.getPointer(); - else { - static TSolidColorStyle *ss = new TSolidColorStyle(TPixel32::Red); - ss->addRef(); - return ss; - } +TColorStyle *TPalette::getStyle(int index) const { + if (0 <= index && index < getStyleCount()) + return m_styles[index].second.getPointer(); + else { + static TSolidColorStyle *ss = new TSolidColorStyle(TPixel32::Red); + ss->addRef(); + return ss; + } } //------------------------------------------------------------------- -int TPalette::getStyleInPagesCount() const -{ - int styleInPagesCount = 0; - for (int i = 0; i < getStyleCount(); i++) - if (m_styles[i].first != 0) - styleInPagesCount++; - return styleInPagesCount; +int TPalette::getStyleInPagesCount() const { + int styleInPagesCount = 0; + for (int i = 0; i < getStyleCount(); i++) + if (m_styles[i].first != 0) styleInPagesCount++; + return styleInPagesCount; } //------------------------------------------------------------------- -int TPalette::getFirstUnpagedStyle() const -{ - for (int i = 0; i < getStyleCount(); i++) - if (m_styles[i].first == 0) - return i; - return -1; +int TPalette::getFirstUnpagedStyle() const { + for (int i = 0; i < getStyleCount(); i++) + if (m_styles[i].first == 0) return i; + return -1; } //------------------------------------------------------------------- -/*! Adding style with new styleId. Even if there are deleted styles in the palette, the new style will be appended to the end of the list. +/*! Adding style with new styleId. Even if there are deleted styles in the + * palette, the new style will be appended to the end of the list. */ -int TPalette::addStyle(TColorStyle *style) -{ - //limit the number of cleanup style to 7 - if (isCleanupPalette() && getStyleInPagesCount() >= 8) - return -1; - - int styleId = int(m_styles.size()); - if (styleId < 4096) { - //checking if the style is overlapped - int i = 0; - for (i = 0; i < styleId; i++) - if (getStyle(i) == style) - break; - if (i == styleId) { - m_styles.push_back(std::make_pair((Page *)0, style)); - return styleId; - } - } - delete style; - return -1; +int TPalette::addStyle(TColorStyle *style) { + // limit the number of cleanup style to 7 + if (isCleanupPalette() && getStyleInPagesCount() >= 8) return -1; + + int styleId = int(m_styles.size()); + if (styleId < 4096) { + // checking if the style is overlapped + int i = 0; + for (i = 0; i < styleId; i++) + if (getStyle(i) == style) break; + if (i == styleId) { + m_styles.push_back(std::make_pair((Page *)0, style)); + return styleId; + } + } + delete style; + return -1; } //------------------------------------------------------------------- -int TPalette::addStyle(const TPixel32 &color) -{ - return addStyle(new TSolidColorStyle(color)); +int TPalette::addStyle(const TPixel32 &color) { + return addStyle(new TSolidColorStyle(color)); } //------------------------------------------------------------------- -void TPalette::setStyle(int styleId, TColorStyle *style) -{ - std::auto_ptr styleOwner(style); +void TPalette::setStyle(int styleId, TColorStyle *style) { + std::auto_ptr styleOwner(style); - int styleCount = getStyleCount(); + int styleCount = getStyleCount(); - if (0 <= styleId && styleId < styleCount) { - // Find out if the supplied style is already in the palette - // with a different style id. In that case, bail out as a noop. - for (int i = 0; i < styleCount; ++i) - if (style == getStyle(i)) - return; + if (0 <= styleId && styleId < styleCount) { + // Find out if the supplied style is already in the palette + // with a different style id. In that case, bail out as a noop. + for (int i = 0; i < styleCount; ++i) + if (style == getStyle(i)) return; - // Substitution can take place - if (typeid(*m_styles[styleId].second.getPointer()) != typeid(*style)) - m_styleAnimationTable.erase(styleId); + // Substitution can take place + if (typeid(*m_styles[styleId].second.getPointer()) != typeid(*style)) + m_styleAnimationTable.erase(styleId); - m_styles[styleId].second = styleOwner.release(); - } + m_styles[styleId].second = styleOwner.release(); + } } //------------------------------------------------------------------- -void TPalette::setStyle(int styleId, const TPixelRGBM32 &color) -{ - setStyle(styleId, new TSolidColorStyle(color)); +void TPalette::setStyle(int styleId, const TPixelRGBM32 &color) { + setStyle(styleId, new TSolidColorStyle(color)); } //------------------------------------------------------------------- -int TPalette::getPageCount() const -{ - return int(m_pages.size()); -} +int TPalette::getPageCount() const { return int(m_pages.size()); } //------------------------------------------------------------------- -TPalette::Page *TPalette::getPage(int pageIndex) -{ - if (0 <= pageIndex && pageIndex < getPageCount()) { - Page *page = m_pages[pageIndex]; - assert(page->getIndex() == pageIndex); - assert(page->m_palette == this); - return page; - } else - return 0; +TPalette::Page *TPalette::getPage(int pageIndex) { + if (0 <= pageIndex && pageIndex < getPageCount()) { + Page *page = m_pages[pageIndex]; + assert(page->getIndex() == pageIndex); + assert(page->m_palette == this); + return page; + } else + return 0; } //------------------------------------------------------------------- -const TPalette::Page *TPalette::getPage(int pageIndex) const -{ - if (0 <= pageIndex && pageIndex < getPageCount()) { - Page *page = m_pages[pageIndex]; - assert(page->getIndex() == pageIndex); - assert(page->m_palette == this); - return page; - } else - return 0; +const TPalette::Page *TPalette::getPage(int pageIndex) const { + if (0 <= pageIndex && pageIndex < getPageCount()) { + Page *page = m_pages[pageIndex]; + assert(page->getIndex() == pageIndex); + assert(page->m_palette == this); + return page; + } else + return 0; } //------------------------------------------------------------------- -TPalette::Page *TPalette::addPage(std::wstring name) -{ - Page *page = new Page(name); - page->m_index = getPageCount(); - page->m_palette = this; - m_pages.push_back(page); - return page; +TPalette::Page *TPalette::addPage(std::wstring name) { + Page *page = new Page(name); + page->m_index = getPageCount(); + page->m_palette = this; + m_pages.push_back(page); + return page; } //------------------------------------------------------------------- -void TPalette::erasePage(int index) -{ - Page *page = getPage(index); - if (!page) - return; - m_pages.erase(m_pages.begin() + index); - int i; - for (i = 0; i < getPageCount(); i++) - m_pages[i]->m_index = i; - for (i = 0; i < page->getStyleCount(); i++) - m_styles[page->getStyleId(i)].first = 0; - page->m_palette = 0; - delete page; +void TPalette::erasePage(int index) { + Page *page = getPage(index); + if (!page) return; + m_pages.erase(m_pages.begin() + index); + int i; + for (i = 0; i < getPageCount(); i++) m_pages[i]->m_index = i; + for (i = 0; i < page->getStyleCount(); i++) + m_styles[page->getStyleId(i)].first = 0; + page->m_palette = 0; + delete page; } //------------------------------------------------------------------- -void TPalette::movePage(Page *page, int dstPageIndex) -{ - assert(page); - assert(page->m_palette == this); - dstPageIndex = tcrop(dstPageIndex, 0, getPageCount() - 1); - if (dstPageIndex == page->getIndex()) - return; - m_pages.erase(m_pages.begin() + page->getIndex()); - m_pages.insert(m_pages.begin() + dstPageIndex, page); - for (int i = 0; i < getPageCount(); i++) - m_pages[i]->m_index = i; - assert(page->getIndex() == dstPageIndex); +void TPalette::movePage(Page *page, int dstPageIndex) { + assert(page); + assert(page->m_palette == this); + dstPageIndex = tcrop(dstPageIndex, 0, getPageCount() - 1); + if (dstPageIndex == page->getIndex()) return; + m_pages.erase(m_pages.begin() + page->getIndex()); + m_pages.insert(m_pages.begin() + dstPageIndex, page); + for (int i = 0; i < getPageCount(); i++) m_pages[i]->m_index = i; + assert(page->getIndex() == dstPageIndex); } //------------------------------------------------------------------- -TPalette::Page *TPalette::getStylePage(int styleId) const -{ - if (0 <= styleId && styleId < getStyleCount()) - return m_styles[styleId].first; - else - return 0; +TPalette::Page *TPalette::getStylePage(int styleId) const { + if (0 <= styleId && styleId < getStyleCount()) + return m_styles[styleId].first; + else + return 0; } //------------------------------------------------------------------- -int TPalette::getClosestStyle(const TPixel32 &color) const -{ - struct locals { - static inline int getDistance2(const TPixel32 &a, const TPixel32 &b) - { - return (a.r - b.r) * (a.r - b.r) + (a.g - b.g) * (a.g - b.g) + (a.b - b.b) * (a.b - b.b) + (a.m - b.m) * (a.m - b.m); - } - }; // locals - - if (color == TPixel32::Transparent) - return 0; - int bestIndex = -1; - int bestDistance = 255 * 255 * 4 + 1; - for (int i = 1; i < (int)m_styles.size(); i++) { - // if(i==FirstUserStyle+2) continue; - TSolidColorStyle *scs = dynamic_cast(m_styles[i].second.getPointer()); - if (scs) { - int d = locals::getDistance2(scs->getMainColor(), color); - if (d < bestDistance) { - bestIndex = i; - bestDistance = d; - } - } - } - return bestIndex; +int TPalette::getClosestStyle(const TPixel32 &color) const { + struct locals { + static inline int getDistance2(const TPixel32 &a, const TPixel32 &b) { + return (a.r - b.r) * (a.r - b.r) + (a.g - b.g) * (a.g - b.g) + + (a.b - b.b) * (a.b - b.b) + (a.m - b.m) * (a.m - b.m); + } + }; // locals + + if (color == TPixel32::Transparent) return 0; + int bestIndex = -1; + int bestDistance = 255 * 255 * 4 + 1; + for (int i = 1; i < (int)m_styles.size(); i++) { + // if(i==FirstUserStyle+2) continue; + TSolidColorStyle *scs = + dynamic_cast(m_styles[i].second.getPointer()); + if (scs) { + int d = locals::getDistance2(scs->getMainColor(), color); + if (d < bestDistance) { + bestIndex = i; + bestDistance = d; + } + } + } + return bestIndex; } //------------------------------------------------------------------- -bool TPalette::getFxRects(const TRect &rect, TRect &rectIn, TRect &rectOut) -{ - int i; - bool ret = false; - int borderIn, borderOut, fullBorderIn = 0, fullBorderOut = 0; - - for (i = 0; i < (int)m_styles.size(); i++) - if (m_styles[i].second->isRasterStyle()) { - m_styles[i].second->getRasterStyleFx()->getEnlargement(borderIn, borderOut); - fullBorderIn = std::max(fullBorderIn, borderIn); - fullBorderOut = std::max(fullBorderOut, borderOut); - ret = true; - } - - rectIn = rect.enlarge(fullBorderIn); - rectOut = rect.enlarge(fullBorderOut); - return ret; +bool TPalette::getFxRects(const TRect &rect, TRect &rectIn, TRect &rectOut) { + int i; + bool ret = false; + int borderIn, borderOut, fullBorderIn = 0, fullBorderOut = 0; + + for (i = 0; i < (int)m_styles.size(); i++) + if (m_styles[i].second->isRasterStyle()) { + m_styles[i].second->getRasterStyleFx()->getEnlargement(borderIn, + borderOut); + fullBorderIn = std::max(fullBorderIn, borderIn); + fullBorderOut = std::max(fullBorderOut, borderOut); + ret = true; + } + + rectIn = rect.enlarge(fullBorderIn); + rectOut = rect.enlarge(fullBorderOut); + return ret; } //=================================================================== @@ -461,728 +414,671 @@ bool TPalette::getFxRects(const TRect &rect, TRect &rectIn, TRect &rectOut) // //------------------------------------------------------------------- -namespace -{ +namespace { -class StyleWriter : public TOutputStreamInterface -{ - TOStream &m_os; - int m_index; +class StyleWriter : public TOutputStreamInterface { + TOStream &m_os; + int m_index; public: - static TFilePath m_rootDir; - StyleWriter(TOStream &os, int index) : m_os(os), m_index(index) - { - } - static void setRootDir(const TFilePath &fp) { m_rootDir = fp; } - - TOutputStreamInterface &operator<<(double x) - { - m_os << x; - return *this; - }; - TOutputStreamInterface &operator<<(int x) - { - m_os << x; - return *this; - }; - TOutputStreamInterface &operator<<(std::string x) - { - m_os << x; - return *this; - }; - TOutputStreamInterface &operator<<(UCHAR x) - { - m_os << (int)x; - return *this; - }; - TOutputStreamInterface &operator<<(USHORT x) - { - m_os << (int)x; - return *this; - }; - TOutputStreamInterface &operator<<(const TPixel32 &x) - { - m_os << x; - return *this; - }; - TOutputStreamInterface &operator<<(const TRaster32P &ras) - { - assert(m_rootDir != TFilePath()); - - std::string name = "texture_" + std::to_string(m_index); - m_os << name; - TFilePath filename = - ((m_rootDir + "textures") + name).withType("bmp"); - if (!TFileStatus(m_rootDir + "textures").doesExist()) { - try { - TSystem::mkDir(m_rootDir + "textures"); - } catch (...) { - } - } - - TImageWriter::save(filename, ras); - return *this; - }; + static TFilePath m_rootDir; + StyleWriter(TOStream &os, int index) : m_os(os), m_index(index) {} + static void setRootDir(const TFilePath &fp) { m_rootDir = fp; } + + TOutputStreamInterface &operator<<(double x) { + m_os << x; + return *this; + }; + TOutputStreamInterface &operator<<(int x) { + m_os << x; + return *this; + }; + TOutputStreamInterface &operator<<(std::string x) { + m_os << x; + return *this; + }; + TOutputStreamInterface &operator<<(UCHAR x) { + m_os << (int)x; + return *this; + }; + TOutputStreamInterface &operator<<(USHORT x) { + m_os << (int)x; + return *this; + }; + TOutputStreamInterface &operator<<(const TPixel32 &x) { + m_os << x; + return *this; + }; + TOutputStreamInterface &operator<<(const TRaster32P &ras) { + assert(m_rootDir != TFilePath()); + + std::string name = "texture_" + std::to_string(m_index); + m_os << name; + TFilePath filename = ((m_rootDir + "textures") + name).withType("bmp"); + if (!TFileStatus(m_rootDir + "textures").doesExist()) { + try { + TSystem::mkDir(m_rootDir + "textures"); + } catch (...) { + } + } + + TImageWriter::save(filename, ras); + return *this; + }; }; //------------------------------------------------------------------- -class StyleReader : public TInputStreamInterface -{ - TIStream &m_is; //!< Wrapped input stream. - VersionNumber m_version; //!< Palette version number (overrides m_is's one). +class StyleReader : public TInputStreamInterface { + TIStream &m_is; //!< Wrapped input stream. + VersionNumber m_version; //!< Palette version number (overrides m_is's one). public: - static TFilePath m_rootDir; + static TFilePath m_rootDir; public: - StyleReader(TIStream &is, const VersionNumber &version) - : m_is(is), m_version(version) {} - - static void setRootDir(const TFilePath &fp) { m_rootDir = fp; } - - virtual TInputStreamInterface &operator>>(double &x) - { - m_is >> x; - return *this; - } - virtual TInputStreamInterface &operator>>(int &x) - { - m_is >> x; - return *this; - } - virtual TInputStreamInterface &operator>>(std::string &x) - { - m_is >> x; - return *this; - } - virtual TInputStreamInterface &operator>>(UCHAR &x) - { - int v; - m_is >> v; - x = v; - return *this; - } - virtual TInputStreamInterface &operator>>(USHORT &x) - { - int v; - m_is >> v; - x = v; - return *this; - } - virtual TInputStreamInterface &operator>>(TRaster32P &x) - { - assert(m_rootDir != TFilePath()); - std::string name; - m_is >> name; - TFilePath filename = - ((m_rootDir + "textures") + name).withType("bmp"); - TRasterP ras; - if (TImageReader::load(filename, ras)) { - x = ras; - } - return *this; - } - virtual TInputStreamInterface &operator>>(TPixel32 &x) - { - m_is >> x; - return *this; - } - - /*! - \details Explicitly ovverrides the stream's version, returning m_version. - This is necessary since palettes have their \a own version number, - which is \a not the TIStream's file one. - */ - virtual VersionNumber versionNumber() const - { - return m_version; - } //!< Returns the palette's version number. + StyleReader(TIStream &is, const VersionNumber &version) + : m_is(is), m_version(version) {} + + static void setRootDir(const TFilePath &fp) { m_rootDir = fp; } + + virtual TInputStreamInterface &operator>>(double &x) { + m_is >> x; + return *this; + } + virtual TInputStreamInterface &operator>>(int &x) { + m_is >> x; + return *this; + } + virtual TInputStreamInterface &operator>>(std::string &x) { + m_is >> x; + return *this; + } + virtual TInputStreamInterface &operator>>(UCHAR &x) { + int v; + m_is >> v; + x = v; + return *this; + } + virtual TInputStreamInterface &operator>>(USHORT &x) { + int v; + m_is >> v; + x = v; + return *this; + } + virtual TInputStreamInterface &operator>>(TRaster32P &x) { + assert(m_rootDir != TFilePath()); + std::string name; + m_is >> name; + TFilePath filename = ((m_rootDir + "textures") + name).withType("bmp"); + TRasterP ras; + if (TImageReader::load(filename, ras)) { + x = ras; + } + return *this; + } + virtual TInputStreamInterface &operator>>(TPixel32 &x) { + m_is >> x; + return *this; + } + + /*! +\details Explicitly ovverrides the stream's version, returning m_version. + This is necessary since palettes have their \a own version number, + which is \a not the TIStream's file one. +*/ + virtual VersionNumber versionNumber() const { + return m_version; + } //!< Returns the palette's version number. }; TFilePath StyleWriter::m_rootDir = TFilePath(); TFilePath StyleReader::m_rootDir = TFilePath(); -} // namespace +} // namespace //=================================================================== -void TPalette::setRootDir(const TFilePath &fp) -{ - StyleWriter::setRootDir(fp); - StyleReader::setRootDir(fp); +void TPalette::setRootDir(const TFilePath &fp) { + StyleWriter::setRootDir(fp); + StyleReader::setRootDir(fp); } //------------------------------------------------------------------- -void TPalette::saveData(TOStream &os) -{ - os.child("version") << 71 << 0; // Inserting the version tag at this level. - // This is necessary to support the tpl format - if (m_refImgPath != TFilePath()) // since it performs *untagged* stream output - os.child("refImgPath") << m_refImgPath; // (the palette is streamed directly). - - os.openChild("styles"); - { - for (int i = 0; i < getStyleCount(); ++i) { - os.openChild("style"); - { - StyleWriter w(os, i); - m_styles[i].second->save(w); - } - os.closeChild(); - } - } - os.closeChild(); - - os.openChild("stylepages"); - { - for (int i = 0; i < getPageCount(); ++i) { - Page *page = getPage(i); - os.openChild("page"); - { - os.child("name") << page->getName(); - - os.openChild("indices"); - { - int m = page->getStyleCount(); - - for (int j = 0; j < m; ++j) - os << page->getStyleId(j); - } - os.closeChild(); - } - os.closeChild(); - } - } - os.closeChild(); - - if (isAnimated()) { - os.openChild("animation"); - { - StyleAnimationTable::iterator sat, saEnd = m_styleAnimationTable.end(); - for (sat = m_styleAnimationTable.begin(); sat != saEnd; ++sat) { - int styleId = sat->first; - StyleAnimation &animation = sat->second; - - std::map attributes; - attributes["id"] = std::to_string(styleId); - - os.openChild("style", attributes); - { - StyleAnimation::iterator kt, kEnd = animation.end(); - for (kt = animation.begin(); kt != kEnd; ++kt) { - int frame = kt->first; - - TColorStyle *cs = kt->second.getPointer(); - assert(cs); - - attributes.clear(); - attributes["frame"] = std::to_string(frame); - - /*os.openChild("keycolor", attributes); // Up to Toonz 7.0, animations saved +void TPalette::saveData(TOStream &os) { + os.child("version") << 71 << 0; // Inserting the version tag at this level. + // This is necessary to support the tpl format + if (m_refImgPath != + TFilePath()) // since it performs *untagged* stream output + os.child("refImgPath") + << m_refImgPath; // (the palette is streamed directly). + + os.openChild("styles"); + { + for (int i = 0; i < getStyleCount(); ++i) { + os.openChild("style"); + { + StyleWriter w(os, i); + m_styles[i].second->save(w); + } + os.closeChild(); + } + } + os.closeChild(); + + os.openChild("stylepages"); + { + for (int i = 0; i < getPageCount(); ++i) { + Page *page = getPage(i); + os.openChild("page"); + { + os.child("name") << page->getName(); + + os.openChild("indices"); + { + int m = page->getStyleCount(); + + for (int j = 0; j < m; ++j) os << page->getStyleId(j); + } + os.closeChild(); + } + os.closeChild(); + } + } + os.closeChild(); + + if (isAnimated()) { + os.openChild("animation"); + { + StyleAnimationTable::iterator sat, saEnd = m_styleAnimationTable.end(); + for (sat = m_styleAnimationTable.begin(); sat != saEnd; ++sat) { + int styleId = sat->first; + StyleAnimation &animation = sat->second; + + std::map attributes; + attributes["id"] = std::to_string(styleId); + + os.openChild("style", attributes); + { + StyleAnimation::iterator kt, kEnd = animation.end(); + for (kt = animation.begin(); kt != kEnd; ++kt) { + int frame = kt->first; + + TColorStyle *cs = kt->second.getPointer(); + assert(cs); + + attributes.clear(); + attributes["frame"] = std::to_string(frame); + + /*os.openChild("keycolor", attributes); // Up to Toonz 7.0, animations saved os << cs->getMainColor(); // the main color only - os.closeChild();*/ // - - os.openChild("keyframe", attributes); - { - StyleWriter w(os, sat->first); - kt->second->save(w); - } - os.closeChild(); - } - } - os.closeChild(); - } - } - os.closeChild(); - } - - // salvo gli shortcuts solo se sono non standard - int i; - for (i = 0; i < 10; ++i) - if (getShortcutValue('0' + i) != i) - break; - - if (i < 10) { - os.openChild("shortcuts"); - { - for (i = 0; i < 10; i++) - os << getShortcutValue('0' + i); - } - os.closeChild(); - } - if (isLocked()) { - os.openChild("lock"); - os << 1; - os.closeChild(); - } + os.closeChild();*/ // + + os.openChild("keyframe", attributes); + { + StyleWriter w(os, sat->first); + kt->second->save(w); + } + os.closeChild(); + } + } + os.closeChild(); + } + } + os.closeChild(); + } + + // salvo gli shortcuts solo se sono non standard + int i; + for (i = 0; i < 10; ++i) + if (getShortcutValue('0' + i) != i) break; + + if (i < 10) { + os.openChild("shortcuts"); + { + for (i = 0; i < 10; i++) os << getShortcutValue('0' + i); + } + os.closeChild(); + } + if (isLocked()) { + os.openChild("lock"); + os << 1; + os.closeChild(); + } } //------------------------------------------------------------------- -void TPalette::loadData(TIStream &is) -{ - m_styles.clear(); - clearPointerContainer(m_pages); - - VersionNumber version = is.getVersion(); - - std::string tagName; - while (is.openChild(tagName)) { - if (tagName == "version") { - is >> version.first >> version.second; - if (version > VersionNumber(71, 0)) - throw TException("palette, unsupported version number"); - } else if (tagName == "styles") { - while (!is.eos()) // I think while(is.openChild(tagName)) - { // would be better. However, I don't trust - if (!is.openChild(tagName) || tagName != "style") // TIStream's implementation very much. Keeping it - throw TException("palette, expected tag