Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "tsystem.h"
Toshihiro Shimizu 890ddd
#include "tstream.h"
Toshihiro Shimizu 890ddd
#include "tthreadmessage.h"
Toshihiro Shimizu 890ddd
#include "tconvert.h"
Toshihiro Shimizu 890ddd
#include "tstopwatch.h"
Toshihiro Shimizu 890ddd
#include "tlevel_io.h"
Toshihiro Shimizu 890ddd
#include "tflash.h"
Toshihiro Shimizu 890ddd
#include "trasterimage.h"
Toshihiro Shimizu 890ddd
#include "ttoonzimage.h"
Toshihiro Shimizu 890ddd
#include "tvectorimage.h"
Toshihiro Shimizu 890ddd
#include "timagecache.h"
Toshihiro Shimizu 890ddd
#include "timageinfo.h"
Toshihiro Shimizu 890ddd
#include "tropcm.h"
Toshihiro Shimizu 890ddd
#include "tofflinegl.h"
Toshihiro Shimizu 890ddd
#include "tvectorrenderdata.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzBase includes
Toshihiro Shimizu 890ddd
#include "ttzpimagefx.h"
Toshihiro Shimizu 890ddd
#include "trasterfx.h"
Toshihiro Shimizu 890ddd
#include "tzeraryfx.h"
Toshihiro Shimizu 890ddd
#include "trenderer.h"
Toshihiro Shimizu 890ddd
#include "tfxcachemanager.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzLib includes
Toshihiro Shimizu 890ddd
#include "toonz/toonzscene.h"
Toshihiro Shimizu 890ddd
#include "toonz/txsheet.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshlevelcolumn.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshpalettecolumn.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshzeraryfxcolumn.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshlevel.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshcell.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshsimplelevel.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshpalettelevel.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshleveltypes.h"
Toshihiro Shimizu 890ddd
#include "toonz/levelset.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshchildlevel.h"
Toshihiro Shimizu 890ddd
#include "toonz/fxdag.h"
Toshihiro Shimizu 890ddd
#include "toonz/tcolumnfxset.h"
Toshihiro Shimizu 890ddd
#include "toonz/stage.h"
Toshihiro Shimizu 890ddd
#include "toonz/fill.h"
Toshihiro Shimizu 890ddd
#include "toonz/tstageobjectid.h"
Toshihiro Shimizu 890ddd
#include "toonz/tstageobject.h"
Toshihiro Shimizu 890ddd
#include "toonz/levelproperties.h"
Toshihiro Shimizu 890ddd
#include "toonz/imagemanager.h"
Toshihiro Shimizu 890ddd
#include "toonz/toonzimageutils.h"
Toshihiro Shimizu 890ddd
#include "toonz/tvectorimageutils.h"
Toshihiro Shimizu 890ddd
#include "toonz/preferences.h"
Toshihiro Shimizu 890ddd
#include "toonz/dpiscale.h"
Toshihiro Shimizu 890ddd
#include "imagebuilders.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// 4.6 compatibility - sandor fxs
Toshihiro Shimizu 890ddd
#include "toonz4.6/raster.h"
Toshihiro Shimizu 890ddd
#include "sandor_fxs/blend.h"
Toshihiro Shimizu 890ddd
extern "C" {
Toshihiro Shimizu 890ddd
#include "sandor_fxs/calligraph.h"
Toshihiro Shimizu 890ddd
#include "sandor_fxs/patternmap.h"
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "toonz/tcolumnfx.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
//    Preliminaries
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 9f5a1b
#ifdef _WIN32
Toshihiro Shimizu 890ddd
template class DV_EXPORT_API TFxDeclarationT<tlevelcolumnfx>;</tlevelcolumnfx>
Toshihiro Shimizu 890ddd
template class DV_EXPORT_API TFxDeclarationT<tzerarycolumnfx>;</tzerarycolumnfx>
Toshihiro Shimizu 890ddd
template class DV_EXPORT_API TFxDeclarationT<txsheetfx>;</txsheetfx>
Toshihiro Shimizu 890ddd
template class DV_EXPORT_API TFxDeclarationT<toutputfx>;</toutputfx>
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TFxDeclarationT<tlevelcolumnfx> columnFxInfo(TFxInfo("Toonz_columnFx", true));</tlevelcolumnfx>
Shinya Kitaoka 120a6e
TFxDeclarationT<tpalettecolumnfx> paletteColumnFxInfo(</tpalettecolumnfx>
Shinya Kitaoka 120a6e
    TFxInfo("Toonz_paletteColumnFx", true));
Shinya Kitaoka 120a6e
TFxDeclarationT<tzerarycolumnfx> zeraryColumnFxInfo(</tzerarycolumnfx>
Shinya Kitaoka 120a6e
    TFxInfo("Toonz_zeraryColumnFx", true));
Toshihiro Shimizu 890ddd
TFxDeclarationT<txsheetfx> infoTXsheetFx(TFxInfo("Toonz_xsheetFx", true));</txsheetfx>
Toshihiro Shimizu 890ddd
TFxDeclarationT<toutputfx> infoTOutputFx(TFxInfo("Toonz_outputFx", true));</toutputfx>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
//    Local namespace  -  misc functions
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void setMaxMatte(TRasterP r) {
Shinya Kitaoka 120a6e
  TRaster32P r32 = (TRaster32P)r;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TRaster64P r64 = (TRaster64P)r;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (r32)
Shinya Kitaoka 120a6e
    for (int i = 0; i < r32->getLy(); i++) {
Shinya Kitaoka 120a6e
      TPixel *pix = r32->pixels(i);
Shinya Kitaoka 120a6e
      for (int j = 0; j < r32->getLx(); j++, pix++) pix->m = 255;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  else if (r64)
Shinya Kitaoka 120a6e
    for (int i = 0; i < r64->getLy(); i++) {
Shinya Kitaoka 120a6e
      TPixel64 *pix = r64->pixels(i);
Shinya Kitaoka 120a6e
      for (int j = 0; j < r64->getLx(); j++, pix++) pix->m = 65535;
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
char *strsave(const char *t) {
Shinya Kitaoka 120a6e
  char *s;
Shinya Kitaoka 120a6e
  s = (char *)malloc(
Shinya Kitaoka 120a6e
      strlen(t) +
Shinya Kitaoka 120a6e
      1);  // I'm almost sure that this malloc is LEAKED! Please, check that !
Shinya Kitaoka 120a6e
  strcpy(s, t);
Shinya Kitaoka 120a6e
  return s;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline TRect myConvert(const TRectD &r) {
Shinya Kitaoka 120a6e
  return TRect(tfloor(r.x0), tfloor(r.y0), tceil(r.x1), tceil(r.y1));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline TRect myConvert(const TRectD &r, TPointD &dp) {
Shinya Kitaoka 120a6e
  TRect ri(tfloor(r.x0), tfloor(r.y0), tceil(r.x1), tceil(r.y1));
Shinya Kitaoka 120a6e
  dp.x = r.x0 - ri.x0;
Shinya Kitaoka 120a6e
  dp.y = r.y0 - ri.y0;
Shinya Kitaoka 120a6e
  assert(dp.x >= 0 && dp.y >= 0);
Shinya Kitaoka 120a6e
  return ri;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Currently used on debug only
Shinya Kitaoka 120a6e
inline QString traduce(const TRectD &rect) {
Shinya Kitaoka 120a6e
  return "[" + QString::number(rect.x0) + " " + QString::number(rect.y0) + " " +
Shinya Kitaoka 120a6e
         QString::number(rect.x1) + " " + QString::number(rect.y1) + "]";
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Currently used on debug only
Shinya Kitaoka 120a6e
inline QString traduce(const TRectD &rect, const TRenderSettings &info) {
Shinya Kitaoka 120a6e
  return "[" + QString::number(rect.x0) + " " + QString::number(rect.y0) + " " +
Shinya Kitaoka 120a6e
         QString::number(rect.x1) + " " + QString::number(rect.y1) +
Shinya Kitaoka 120a6e
         "]; aff = (" + QString::number(info.m_affine.a11, 'f') + " " +
Shinya Kitaoka 120a6e
         QString::number(info.m_affine.a12, 'f') + " " +
Shinya Kitaoka 120a6e
         QString::number(info.m_affine.a13, 'f') + " " +
Shinya Kitaoka 120a6e
         QString::number(info.m_affine.a21, 'f') + " " +
Shinya Kitaoka 120a6e
         QString::number(info.m_affine.a22, 'f') + " " +
Shinya Kitaoka 120a6e
         QString::number(info.m_affine.a23, 'f') + ")";
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline int colorDistance(const TPixel32 &c0, const TPixel32 &c1) {
Shinya Kitaoka 120a6e
  return (c0.r - c1.r) * (c0.r - c1.r) + (c0.g - c1.g) * (c0.g - c1.g) +
Shinya Kitaoka 120a6e
         (c0.b - c1.b) * (c0.b - c1.b);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::string getAlias(TXsheet *xsh, double frame, const TRenderSettings &info) {
Shinya Kitaoka 120a6e
  TFxSet *fxs = xsh->getFxDag()->getTerminalFxs();
Shinya Kitaoka 120a6e
  std::string alias;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Add the alias for each
Shinya Kitaoka 120a6e
  for (int i = 0; i < fxs->getFxCount(); ++i) {
Shinya Kitaoka 120a6e
    TRasterFx *fx = dynamic_cast<trasterfx *="">(fxs->getFx(i));</trasterfx>
Shinya Kitaoka 120a6e
    assert(fx);
Shinya Kitaoka 120a6e
    if (!fx) continue;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    alias += fx->getAlias(frame, info) + ";";
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return alias;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
//    Local namespace  -  Colormap (Sandor) Fxs stuff
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool vectorMustApplyCmappedFx(const std::vector<trasterfxrenderdatap> &fxs) {</trasterfxrenderdatap>
Shinya Kitaoka 120a6e
  std::vector<trasterfxrenderdatap>::const_iterator ft, fEnd(fxs.end());</trasterfxrenderdatap>
Shinya Kitaoka 120a6e
  for (ft = fxs.begin(); ft != fEnd; ++ft) {
Shinya Kitaoka 120a6e
    PaletteFilterFxRenderData *paletteFilterData =
Shinya Kitaoka 120a6e
        dynamic_cast<palettefilterfxrenderdata *="">(ft->getPointer());</palettefilterfxrenderdata>
Shinya Kitaoka 120a6e
    SandorFxRenderData *sandorData =
Shinya Kitaoka 120a6e
        dynamic_cast<sandorfxrenderdata *="">(ft->getPointer());</sandorfxrenderdata>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // (Daniele) Sandor fxs perform on raster colormaps *only* - while texture
Shinya Kitaoka 120a6e
    // fxs use palette filters to work.
Shinya Kitaoka 120a6e
    // In the latter case, vector-to-colormap conversion makes sure that regions
Shinya Kitaoka 120a6e
    // are not rendered under full ink
Shinya Kitaoka 120a6e
    // pixels (which causes problems**).
Shinya Kitaoka 120a6e
    if (sandorData || (paletteFilterData &&
Shinya Kitaoka 120a6e
                       paletteFilterData->m_type != ::eApplyToInksAndPaints))
Shinya Kitaoka 120a6e
      return true;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    /*
Shinya Kitaoka 120a6e
(Daniele) Disregarding the above reasons - palette filter fxs do not forcibly
Shinya Kitaoka 120a6e
return true.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
Err... ok, my fault - when I wrote that, I forgot to specify WHICH problems**
Shinya Kitaoka 120a6e
occurred. Whops!
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
Now, it happens that if palette filters DO NOT convert to colormapped forcedly,
Shinya Kitaoka 120a6e
special styles can be
Shinya Kitaoka 120a6e
retained... so, let's see what happens.
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
Will have to inquire further, though...
Shinya Kitaoka 120a6e
*/
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool mustApplySandorFx(const std::vector<trasterfxrenderdatap> &fxs) {</trasterfxrenderdatap>
Shinya Kitaoka 120a6e
  std::vector<trasterfxrenderdatap>::const_iterator ft, fEnd(fxs.end());</trasterfxrenderdatap>
Shinya Kitaoka 120a6e
  for (ft = fxs.begin(); ft != fEnd; ++ft) {
Shinya Kitaoka 120a6e
    SandorFxRenderData *sandorData =
Shinya Kitaoka 120a6e
        dynamic_cast<sandorfxrenderdata *="">(ft->getPointer());</sandorfxrenderdata>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (sandorData) return true;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int getEnlargement(const std::vector<trasterfxrenderdatap> &fxs, double scale) {</trasterfxrenderdatap>
Shinya Kitaoka 120a6e
  int enlargement = 1;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::vector<trasterfxrenderdatap>::const_iterator ft, fEnd(fxs.end());</trasterfxrenderdatap>
Shinya Kitaoka 120a6e
  for (ft = fxs.begin(); ft != fEnd; ++ft) {
Shinya Kitaoka 120a6e
    SandorFxRenderData *sandorData =
Shinya Kitaoka 120a6e
        dynamic_cast<sandorfxrenderdata *="">(ft->getPointer());</sandorfxrenderdata>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (sandorData) {
Shinya Kitaoka 120a6e
      switch (sandorData->m_type) {
Shinya Kitaoka 120a6e
      case BlendTz: {
Shinya Kitaoka 120a6e
        // Nothing happen, unless we have color 0 among the blended ones. In
Shinya Kitaoka 120a6e
        // such case,
Shinya Kitaoka 120a6e
        // we have to enlarge the bbox proportionally to the amount param.
Shinya Kitaoka 120a6e
        std::vector<std::string> items;</std::string>
Shinya Kitaoka 120a6e
        std::string indexes = std::string(sandorData->m_argv[0]);
Shinya Kitaoka 120a6e
        parseIndexes(indexes, items);
Shinya Kitaoka 120a6e
        PaletteFilterFxRenderData paletteFilterData;
Shinya Kitaoka 120a6e
        insertIndexes(items, &paletteFilterData);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        if (!paletteFilterData.m_colors.empty() &&
Shinya Kitaoka 120a6e
            *paletteFilterData.m_colors.begin() == 0) {
Shinya Kitaoka 120a6e
          BlendTzParams ¶ms = sandorData->m_blendParams;
Shinya Kitaoka 120a6e
          enlargement           = params.m_amount * scale;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka d4642c
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      case Calligraphic:
Shinya Kitaoka 120a6e
      case OutBorder: {
Shinya Kitaoka 120a6e
        CalligraphicParams ¶ms = sandorData->m_callParams;
Shinya Kitaoka 120a6e
        enlargement                = params.m_thickness * scale;
Shinya Kitaoka d4642c
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      case ArtAtContour: {
Shinya Kitaoka 120a6e
        ArtAtContourParams ¶ms = sandorData->m_contourParams;
Shinya Kitaoka 120a6e
        enlargement = std::max(tceil(sandorData->m_controllerBBox.getLx()),
Shinya Kitaoka 120a6e
                               tceil(sandorData->m_controllerBBox.getLy())) *
Shinya Kitaoka 120a6e
                      params.m_maxSize;
Shinya Kitaoka d4642c
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return enlargement;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void applyPaletteFilter(TPalette *&plt, bool keep, const set<int> &colors,</int>
Shinya Kitaoka 120a6e
                        const TPalette *srcPlt) {
Shinya Kitaoka 120a6e
  if (colors.empty()) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!plt) plt = srcPlt->clone();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (keep) {
Shinya Kitaoka 120a6e
    for (int i = 0; i < plt->getStyleCount(); ++i) {
Shinya Kitaoka 120a6e
      if (colors.find(i) == colors.end())
Shinya Kitaoka 120a6e
        plt->setStyle(i, TPixel32::Transparent);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    std::set<int>::const_iterator ct, cEnd(colors.end());</int>
Shinya Kitaoka 120a6e
    for (ct = colors.begin(); ct != cEnd; ++ct) {
Shinya Kitaoka 120a6e
      TColorStyle *style = plt->getStyle(*ct);
Shinya Kitaoka 120a6e
      if (style) plt->setStyle(*ct, TPixel32::Transparent);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TPalette *getPliPalette(const TFilePath &path) {
Shinya Kitaoka 120a6e
  TLevelReaderP levelReader = TLevelReaderP(path);
Shinya Kitaoka 120a6e
  if (!levelReader.getPointer()) return 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TLevelP level = levelReader->loadInfo();
Shinya Kitaoka 120a6e
  TPalette *plt = level->getPalette();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return plt ? plt->clone() : (TPalette *)0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline bool fxLess(TRasterFxRenderDataP a, TRasterFxRenderDataP b) {
Shinya Kitaoka 120a6e
  SandorFxRenderData *sandorDataA =
Shinya Kitaoka 120a6e
      dynamic_cast<sandorfxrenderdata *="">(a.getPointer());</sandorfxrenderdata>
Shinya Kitaoka 120a6e
  if (!sandorDataA) return false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  SandorFxRenderData *sandorDataB =
Shinya Kitaoka 120a6e
      dynamic_cast<sandorfxrenderdata *="">(b.getPointer());</sandorfxrenderdata>
Shinya Kitaoka 120a6e
  if (!sandorDataB) return true;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int aIndex = sandorDataA->m_type == OutBorder
Shinya Kitaoka 120a6e
                   ? 2
Shinya Kitaoka 120a6e
                   : sandorDataA->m_type == BlendTz ? 1 : 0;
Shinya Kitaoka 120a6e
  int bIndex = sandorDataB->m_type == OutBorder
Shinya Kitaoka 120a6e
                   ? 2
Shinya Kitaoka 120a6e
                   : sandorDataB->m_type == BlendTz ? 1 : 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return aIndex < bIndex;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
inline void sortCmappedFxs(std::vector<trasterfxrenderdatap> &fxs) {</trasterfxrenderdatap>
Shinya Kitaoka 120a6e
  std::stable_sort(fxs.begin(), fxs.end(), fxLess);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::vector<int> getAllBut(std::vector<int> &colorIds) {</int></int>
Shinya Kitaoka 120a6e
  assert(TPixelCM32::getMaxInk() == TPixelCM32::getMaxPaint());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::vector<int> curColorIds;</int>
Shinya Kitaoka 120a6e
  std::sort(colorIds.begin(), colorIds.end());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Taking all colors EXCEPT those in colorIds
Shinya Kitaoka 120a6e
  unsigned int count1 = 0, count2 = 0;
Shinya Kitaoka 120a6e
  int size = TPixelCM32::getMaxInk();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  curColorIds.resize(size + 1 - colorIds.size());
Shinya Kitaoka 120a6e
  for (int i = 0; i < size; i++)
Shinya Kitaoka 120a6e
    if (count1 < colorIds.size() && colorIds[count1] == i)
Shinya Kitaoka 120a6e
      count1++;
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      curColorIds[count2++] = i;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return curColorIds;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! \b IMPORTANT \b NOTE: This function is now written so that the passed Toonz
Shinya Kitaoka 120a6e
//! Image
Shinya Kitaoka 120a6e
//! will be destroyed at the most appropriate time. You should definitely *COPY*
Shinya Kitaoka 120a6e
//! all
Shinya Kitaoka 120a6e
//! necessary informations before calling it - however, since the intent was
Shinya Kitaoka 120a6e
//! that of
Toshihiro Shimizu 890ddd
//! optimizing memory usage, please avoid copying the entire image buffer...
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TImageP applyCmappedFx(TToonzImageP &ti,
Shinya Kitaoka 120a6e
                       const std::vector<trasterfxrenderdatap> &fxs, int frame,</trasterfxrenderdatap>
Shinya Kitaoka 120a6e
                       double scale) {
Shinya Kitaoka 120a6e
  TImageP result = ti;
Shinya Kitaoka 120a6e
  TTile resultTile;  // Just a quick wrapper to the ImageCache
Shinya Kitaoka 120a6e
  TPalette *inPalette, *tempPlt;
Shinya Kitaoka 120a6e
  TPaletteP filteredPalette;
Shinya Kitaoka 120a6e
  TRasterCM32P copyRas;
Shinya Kitaoka 120a6e
  std::string cmRasCacheId;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Retrieve the image dpi
Shinya Kitaoka 120a6e
  double dpiX, dpiY;
Shinya Kitaoka 120a6e
  ti->getDpi(dpiX, dpiY);
Shinya Kitaoka 120a6e
  double dpi = (dpiX > 0) ? dpiX / Stage::inch : 1.0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // First, sort the fxs.
Shinya Kitaoka 120a6e
  std::vector<trasterfxrenderdatap> fxsCopy = fxs;</trasterfxrenderdatap>
Shinya Kitaoka 120a6e
  sortCmappedFxs(fxsCopy);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // First, let's deal with all fxs working on palettes
Shinya Kitaoka 120a6e
  inPalette = ti->getPalette();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::vector<trasterfxrenderdatap>::reverse_iterator it;</trasterfxrenderdatap>
Shinya Kitaoka 120a6e
  for (it = fxsCopy.rbegin(); it != fxsCopy.rend(); ++it) {
Shinya Kitaoka 120a6e
    ExternalPaletteFxRenderData *extpltData =
Shinya Kitaoka 120a6e
        dynamic_cast<externalpalettefxrenderdata *="">((*it).getPointer());</externalpalettefxrenderdata>
Shinya Kitaoka 120a6e
    PaletteFilterFxRenderData *PaletteFilterData =
Shinya Kitaoka 120a6e
        dynamic_cast<palettefilterfxrenderdata *="">((*it).getPointer());</palettefilterfxrenderdata>
Shinya Kitaoka 120a6e
    if (extpltData && extpltData->m_palette) {
Shinya Kitaoka 120a6e
      filteredPalette = extpltData->m_palette->clone();
Shinya Kitaoka 120a6e
      filteredPalette->setFrame(frame);
Shinya Kitaoka 120a6e
    } else if (PaletteFilterData &&
Shinya Kitaoka 120a6e
               PaletteFilterData->m_type == eApplyToInksAndPaints) {
Shinya Kitaoka 120a6e
      bool keep = PaletteFilterData->m_keep;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      set<int> colors;</int>
Shinya Kitaoka 120a6e
      colors.insert(PaletteFilterData->m_colors.begin(),
Shinya Kitaoka 120a6e
                    PaletteFilterData->m_colors.end());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // Apply the palette filters
Shinya Kitaoka 120a6e
      tempPlt = filteredPalette.getPointer();
Shinya Kitaoka 120a6e
      applyPaletteFilter(tempPlt, keep, colors, inPalette);
Shinya Kitaoka 120a6e
      filteredPalette = tempPlt;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      inPalette = filteredPalette.getPointer();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (filteredPalette) {
Shinya Kitaoka 120a6e
    // result= ti = ti->clone();   //Is copying truly necessary??
Shinya Kitaoka 120a6e
    result = ti = TToonzImageP(ti->getRaster(), ti->getSavebox());
Shinya Kitaoka 120a6e
    filteredPalette->setFrame(frame);
Shinya Kitaoka 120a6e
    ti->setPalette(filteredPalette.getPointer());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Next, deal with fxs working on colormaps themselves
Shinya Kitaoka 120a6e
  bool firstSandorFx = true;
Shinya Kitaoka 120a6e
  TRasterCM32P cmRas = ti->getRaster();
Shinya Kitaoka 120a6e
  TRect tiSaveBox(ti->getSavebox());
Shinya Kitaoka 120a6e
  TPaletteP tiPalette(ti->getPalette());
Shinya Kitaoka 120a6e
  ti = 0;  // Release the reference to colormap
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Now, apply cmapped->cmapped fxs
Shinya Kitaoka 120a6e
  for (it = fxsCopy.rbegin(); it != fxsCopy.rend(); ++it) {
Shinya Kitaoka 120a6e
    PaletteFilterFxRenderData *PaletteFilterData =
Shinya Kitaoka 120a6e
        dynamic_cast<palettefilterfxrenderdata *="">(it->getPointer());</palettefilterfxrenderdata>
Shinya Kitaoka 120a6e
    if (PaletteFilterData &&
Shinya Kitaoka 120a6e
        PaletteFilterData->m_type != eApplyToInksAndPaints) {
Shinya Kitaoka 120a6e
      std::vector<int> indexes;</int>
Shinya Kitaoka 120a6e
      indexes.resize(PaletteFilterData->m_colors.size());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      set<int>::const_iterator jt = PaletteFilterData->m_colors.begin();</int>
Shinya Kitaoka 120a6e
      for (int j = 0; j < (int)indexes.size(); ++j, ++jt) indexes[j] = *jt;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (copyRas == TRasterCM32P())
Shinya Kitaoka 120a6e
        copyRas =
Shinya Kitaoka 120a6e
            cmRas->clone();  // Pixels are literally cleared on a copy buffer
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      /*-- 処理するIndexを反転 --*/
Shinya Kitaoka 120a6e
      if (PaletteFilterData->m_keep) indexes = getAllBut(indexes);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      /*-- Paintの消去("Lines Including All
Shinya Kitaoka 120a6e
       * Areas"のみ、Areaに何も操作をしない) --*/
Shinya Kitaoka 120a6e
      if (PaletteFilterData->m_type !=
Shinya Kitaoka 120a6e
          eApplyToInksKeepingAllPaints)  // se non e'
Shinya Kitaoka 120a6e
                                         // eApplyToInksKeepingAllPaints,
Shinya Kitaoka 120a6e
                                         // sicuramente devo cancellare dei
Shinya Kitaoka 120a6e
                                         // paint
Shinya Kitaoka 120a6e
        TRop::eraseColors(
Shinya Kitaoka 120a6e
            copyRas, PaletteFilterData->m_type == eApplyToInksDeletingAllPaints
Shinya Kitaoka 120a6e
                         ? 0
Shinya Kitaoka 120a6e
                         : &indexes,
Shinya Kitaoka 120a6e
            false);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      /*-- Inkの消去 --*/
Shinya Kitaoka 120a6e
      if (PaletteFilterData->m_type !=
Shinya Kitaoka 120a6e
          eApplyToPaintsKeepingAllInks)  // se non e'
Shinya Kitaoka 120a6e
                                         // eApplyToPaintsKeepingAllInks,
Shinya Kitaoka 120a6e
                                         // sicuramente devo cancellare degli
Shinya Kitaoka 120a6e
                                         // ink
Shinya Kitaoka 120a6e
        TRop::eraseColors(
Shinya Kitaoka 120a6e
            copyRas, PaletteFilterData->m_type == eApplyToPaintsDeletingAllInks
Shinya Kitaoka 120a6e
                         ? 0
Shinya Kitaoka 120a6e
                         : &indexes,
Shinya Kitaoka 120a6e
            true);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (copyRas) {
Shinya Kitaoka 120a6e
    cmRas  = copyRas;
Shinya Kitaoka 120a6e
    result = TToonzImageP(cmRas, tiSaveBox);
Shinya Kitaoka 120a6e
    result->setPalette(tiPalette.getPointer());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Finally, apply cmapped->fullcolor fxs
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Prefetch all Blend fxs
Shinya Kitaoka 120a6e
  std::vector<blendparam> blendParams;</blendparam>
Shinya Kitaoka 120a6e
  for (it = fxsCopy.rbegin(); it != fxsCopy.rend(); ++it) {
Shinya Kitaoka 120a6e
    SandorFxRenderData *sandorData =
Shinya Kitaoka 120a6e
        dynamic_cast<sandorfxrenderdata *="">(it->getPointer());</sandorfxrenderdata>
Shinya Kitaoka 120a6e
    if (sandorData && sandorData->m_type == BlendTz) {
Shinya Kitaoka 120a6e
      BlendParam param;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      param.intensity =
Shinya Kitaoka 120a6e
          std::stod(std::string(sandorData->m_argv[3])) * scale * dpi;
Shinya Kitaoka 120a6e
      param.smoothness     = sandorData->m_blendParams.m_smoothness;
Shinya Kitaoka 120a6e
      param.stopAtCountour = sandorData->m_blendParams.m_noBlending;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      param.superSampling = sandorData->m_blendParams.m_superSampling;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // Build the color indexes
Shinya Kitaoka 120a6e
      std::vector<std::string> items;</std::string>
Shinya Kitaoka 120a6e
      std::string indexes = std::string(sandorData->m_argv[0]);
Shinya Kitaoka 120a6e
      parseIndexes(indexes, items);
Shinya Kitaoka 120a6e
      PaletteFilterFxRenderData paletteFilterData;
Shinya Kitaoka 120a6e
      insertIndexes(items, &paletteFilterData);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      param.colorsIndexes.reserve(paletteFilterData.m_colors.size());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      std::set<int>::iterator it;</int>
Shinya Kitaoka 120a6e
      for (it = paletteFilterData.m_colors.begin();
Shinya Kitaoka 120a6e
           it != paletteFilterData.m_colors.end(); ++it)
Shinya Kitaoka 120a6e
        param.colorsIndexes.push_back(*it);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      blendParams.push_back(param);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Apply each sandor
Shinya Kitaoka 120a6e
  for (it = fxsCopy.rbegin(); it != fxsCopy.rend(); ++it) {
Shinya Kitaoka 120a6e
    SandorFxRenderData *sandorData =
Shinya Kitaoka 120a6e
        dynamic_cast<sandorfxrenderdata *="">(it->getPointer());</sandorfxrenderdata>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (sandorData) {
Shinya Kitaoka 120a6e
      // Avoid dealing with specific cases
Shinya Kitaoka 120a6e
      if ((sandorData->m_type == BlendTz && blendParams.empty()) ||
Shinya Kitaoka 120a6e
          (sandorData->m_type == OutBorder && !firstSandorFx))
Shinya Kitaoka 120a6e
        continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (!firstSandorFx) {
Shinya Kitaoka 120a6e
        // Retrieve the colormap from cache
Shinya Kitaoka 120a6e
        cmRas = TToonzImageP(TImageCache::instance()->get(cmRasCacheId, true))
Shinya Kitaoka 120a6e
                    ->getRaster();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        // Apply a palette filter in order to keep only the colors specified in
Shinya Kitaoka 120a6e
        // the sandor argv
Shinya Kitaoka 120a6e
        std::vector<std::string> items;</std::string>
Shinya Kitaoka 120a6e
        std::string indexes = std::string(sandorData->m_argv[0]);
Shinya Kitaoka 120a6e
        parseIndexes(indexes, items);
Shinya Kitaoka 120a6e
        PaletteFilterFxRenderData paletteFilterData;
Shinya Kitaoka 120a6e
        insertIndexes(items, &paletteFilterData);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        filteredPalette = tempPlt = 0;
Shinya Kitaoka 120a6e
        applyPaletteFilter(tempPlt, true, paletteFilterData.m_colors,
Shinya Kitaoka 120a6e
                           tiPalette.getPointer());
Shinya Kitaoka 120a6e
        filteredPalette = tempPlt;
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        // Pass the input colormap to the cache and release its reference as
Shinya Kitaoka 120a6e
        // final result
Shinya Kitaoka 120a6e
        cmRasCacheId = TImageCache::instance()->getUniqueId();
Shinya Kitaoka 120a6e
        TImageCache::instance()->add(cmRasCacheId,
Shinya Kitaoka 120a6e
                                     TToonzImageP(cmRas, tiSaveBox));
Shinya Kitaoka 120a6e
        result = 0;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // Convert current smart pointers to a 4.6 'fashion'. The former ones are
Shinya Kitaoka 120a6e
      // released - so they
Shinya Kitaoka 120a6e
      // do not occupy smart object references.
Shinya Kitaoka 120a6e
      RASTER *oldRasterIn, *oldRasterOut;
Shinya Kitaoka 120a6e
      oldRasterIn = TRop::convertRaster50to46(
Shinya Kitaoka 120a6e
          cmRas, filteredPalette ? filteredPalette : tiPalette.getPointer());
Shinya Kitaoka 120a6e
      cmRas = TRasterCM32P(0);
Shinya Kitaoka 120a6e
      {
Shinya Kitaoka 120a6e
        TRaster32P rasterOut(TDimension(oldRasterIn->lx, oldRasterIn->ly));
Shinya Kitaoka 120a6e
        oldRasterOut = TRop::convertRaster50to46(rasterOut, 0);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      switch (sandorData->m_type) {
Shinya Kitaoka 120a6e
      case BlendTz: {
Shinya Kitaoka 120a6e
        if (blendParams.empty()) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        // Retrieve the colormap from cache
Shinya Kitaoka 120a6e
        cmRas = TToonzImageP(TImageCache::instance()->get(cmRasCacheId, true))
Shinya Kitaoka 120a6e
                    ->getRaster();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        TToonzImageP ti(cmRas, tiSaveBox);
Shinya Kitaoka 120a6e
        ti->setPalette(filteredPalette ? filteredPalette.getPointer()
Shinya Kitaoka 120a6e
                                       : tiPalette.getPointer());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        TRasterImageP riOut(TImageCache::instance()->get(
Shinya Kitaoka 120a6e
            std::string(oldRasterOut->cacheId, oldRasterOut->cacheIdLength),
Shinya Kitaoka 120a6e
            true));
Shinya Kitaoka 120a6e
        TRaster32P rasterOut = riOut->getRaster();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        blend(ti, rasterOut, blendParams);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        blendParams.clear();
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      case Calligraphic:
Shinya Kitaoka 120a6e
      case OutBorder: {
Shinya Kitaoka 120a6e
        if (sandorData->m_type == OutBorder && !firstSandorFx) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        const char *argv[12];
Shinya Kitaoka 120a6e
        memcpy(argv, sandorData->m_argv, 12 * sizeof(const char *));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        double thickness =
Shinya Kitaoka 120a6e
            std::stod(std::string(sandorData->m_argv[7])) * scale * dpi;
Shinya Kitaoka 120a6e
        argv[7] = strsave(std::to_string(thickness).c_str());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        calligraph(oldRasterIn, oldRasterOut, sandorData->m_border,
Shinya Kitaoka 120a6e
                   sandorData->m_argc, argv, sandorData->m_shrink,
Shinya Kitaoka 120a6e
                   sandorData->m_type == OutBorder);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      case ArtAtContour: {
Shinya Kitaoka 120a6e
        const char *argv[12];
Shinya Kitaoka 120a6e
        memcpy(argv, sandorData->m_argv, 12 * sizeof(const char *));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        double distance =
Shinya Kitaoka 120a6e
            std::stod(std::string(sandorData->m_argv[6])) * scale * dpi;
Shinya Kitaoka 120a6e
        argv[6]  = strsave(std::to_string(distance).c_str());
Shinya Kitaoka 120a6e
        distance = std::stod(std::string(sandorData->m_argv[7])) * scale * dpi;
Shinya Kitaoka 120a6e
        argv[7]  = strsave(std::to_string(distance).c_str());
Shinya Kitaoka 120a6e
        double density =
Shinya Kitaoka 120a6e
            std::stod(std::string(sandorData->m_argv[8])) / sq(scale * dpi);
Shinya Kitaoka 120a6e
        argv[8] = strsave(std::to_string(density).c_str());
Shinya Kitaoka 120a6e
        double size =
Shinya Kitaoka 120a6e
            std::stod(std::string(sandorData->m_argv[1])) * scale * dpi;
Shinya Kitaoka 120a6e
        argv[1] = strsave(std::to_string(size).c_str());
Shinya Kitaoka 120a6e
        size    = std::stod(std::string(sandorData->m_argv[2])) * scale * dpi;
Shinya Kitaoka 120a6e
        argv[2] = strsave(std::to_string(size).c_str());
Shinya Kitaoka 120a6e
        RASTER *imgContour =
Shinya Kitaoka 120a6e
            TRop::convertRaster50to46(sandorData->m_controller, 0);
Shinya Kitaoka 120a6e
        patternmap(oldRasterIn, oldRasterOut, sandorData->m_border,
Shinya Kitaoka 120a6e
                   sandorData->m_argc, argv, sandorData->m_shrink, imgContour);
Shinya Kitaoka 120a6e
        TRop::releaseRaster46(imgContour);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      default:
Shinya Kitaoka 120a6e
        assert(false);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TRasterImageP riOut(TImageCache::instance()->get(
Shinya Kitaoka 120a6e
          std::string(oldRasterOut->cacheId, oldRasterOut->cacheIdLength),
Shinya Kitaoka 120a6e
          true));
Shinya Kitaoka 120a6e
      TRaster32P rasterOut = riOut->getRaster();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TRop::releaseRaster46(oldRasterIn);
Shinya Kitaoka 120a6e
      TRop::releaseRaster46(oldRasterOut);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (firstSandorFx) {
Shinya Kitaoka 120a6e
        resultTile.setRaster(rasterOut);
Shinya Kitaoka 120a6e
        firstSandorFx = false;
Shinya Kitaoka 120a6e
      } else
Shinya Kitaoka 120a6e
        TRop::over(resultTile.getRaster(), rasterOut);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Release cmRas cache identifier if any
Shinya Kitaoka 120a6e
  TImageCache::instance()->remove(cmRasCacheId);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!result) result = TRasterImageP(resultTile.getRaster());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return result;
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
//-------------------------------------------------------------------
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
void applyCmappedFx(TVectorImageP &vi,
Shinya Kitaoka 120a6e
                    const std::vector<trasterfxrenderdatap> &fxs, int frame) {</trasterfxrenderdatap>
Shinya Kitaoka 120a6e
  TRasterP ras;
Shinya Kitaoka 120a6e
  bool keep = false;
Shinya Kitaoka 120a6e
  TPaletteP modPalette;
Shinya Kitaoka 120a6e
  set<int> colors;</int>
Shinya Kitaoka 120a6e
  std::vector<trasterfxrenderdatap>::const_iterator it = fxs.begin();</trasterfxrenderdatap>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // prima tutti gli effetti che agiscono sulla paletta....
Shinya Kitaoka 120a6e
  for (; it != fxs.end(); ++it) {
Shinya Kitaoka 120a6e
    ExternalPaletteFxRenderData *extpltData =
Shinya Kitaoka 120a6e
        dynamic_cast<externalpalettefxrenderdata *="">((*it).getPointer());</externalpalettefxrenderdata>
Shinya Kitaoka 120a6e
    PaletteFilterFxRenderData *pltFilterData =
Shinya Kitaoka 120a6e
        dynamic_cast<palettefilterfxrenderdata *="">((*it).getPointer());</palettefilterfxrenderdata>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (extpltData && extpltData->m_palette)
Shinya Kitaoka 120a6e
      modPalette = extpltData->m_palette->clone();
Shinya Kitaoka 120a6e
    else if (pltFilterData) {
Shinya Kitaoka 120a6e
      assert(
Shinya Kitaoka 120a6e
          pltFilterData->m_type ==
Shinya Kitaoka 120a6e
          eApplyToInksAndPaints);  // Must have been converted to CM32 otherwise
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      keep = pltFilterData->m_keep;
Shinya Kitaoka 120a6e
      colors.insert(pltFilterData->m_colors.begin(),
Shinya Kitaoka 120a6e
                    pltFilterData->m_colors.end());
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPalette *tempPlt = modPalette.getPointer();
Shinya Kitaoka 120a6e
  applyPaletteFilter(tempPlt, keep, colors, vi->getPalette());
Shinya Kitaoka 120a6e
  modPalette = tempPlt;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (modPalette) {
Shinya Kitaoka 120a6e
    vi = vi->clone();
Shinya Kitaoka 120a6e
    vi->setPalette(modPalette.getPointer());
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
//    LevelFxResourceBuilder  definition
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class LevelFxBuilder : public ResourceBuilder {
Shinya Kitaoka 120a6e
  TRasterP m_loadedRas;
Shinya Kitaoka 120a6e
  TPaletteP m_palette;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TXshSimpleLevel *m_sl;
Shinya Kitaoka 120a6e
  TFrameId m_fid;
Shinya Kitaoka 120a6e
  TRectD m_tileGeom;
Shinya Kitaoka 120a6e
  bool m_64bit;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TRect m_rasBounds;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  LevelFxBuilder(const std::string &resourceName, double frame,
Shinya Kitaoka 120a6e
                 const TRenderSettings &rs, TXshSimpleLevel *sl, TFrameId fid)
Shinya Kitaoka 120a6e
      : ResourceBuilder(resourceName, 0, frame, rs)
Shinya Kitaoka 120a6e
      , m_loadedRas()
Shinya Kitaoka 120a6e
      , m_palette()
Shinya Kitaoka 120a6e
      , m_sl(sl)
Shinya Kitaoka 120a6e
      , m_fid(fid)
Shinya Kitaoka 120a6e
      , m_64bit(rs.m_bpp == 64) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void setRasBounds(const TRect &rasBounds) { m_rasBounds = rasBounds; }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void compute(const TRectD &tileRect) override {
Shinya Kitaoka 120a6e
    // Load the image
Shinya Kitaoka 120a6e
    TImageP img(m_sl->getFullsampledFrame(
Shinya Kitaoka 120a6e
        m_fid, (m_64bit ? ImageManager::is64bitEnabled : 0) |
Shinya Kitaoka 120a6e
                   ImageManager::dontPutInCache));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (!img) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TRasterImageP rimg(img);
Shinya Kitaoka 120a6e
    TToonzImageP timg(img);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_loadedRas = rimg ? (TRasterP)rimg->getRaster()
Shinya Kitaoka 120a6e
                       : timg ? (TRasterP)timg->getRaster() : TRasterP();
Shinya Kitaoka 120a6e
    assert(m_loadedRas);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (timg) m_palette = timg->getPalette();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    assert(tileRect ==
Shinya Kitaoka 120a6e
           TRectD(0, 0, m_loadedRas->getLx(), m_loadedRas->getLy()));
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void simCompute(const TRectD &rect) override {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void upload(TCacheResourceP &resource) override {
Shinya Kitaoka 120a6e
    assert(m_loadedRas);
Shinya Kitaoka 120a6e
    resource->upload(TPoint(), m_loadedRas);
Shinya Kitaoka 120a6e
    if (m_palette) resource->uploadPalette(m_palette);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  bool download(TCacheResourceP &resource) override {
Shinya Kitaoka 120a6e
    // If the image has been loaded in this builder, just use it
Shinya Kitaoka 120a6e
    if (m_loadedRas) return true;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // If the image has yet to be loaded by this builder, skip without
Shinya Kitaoka 120a6e
    // allocating anything
Shinya Kitaoka 120a6e
    if (resource->canDownloadAll(m_rasBounds)) {
Shinya Kitaoka 120a6e
      m_loadedRas = resource->buildCompatibleRaster(m_rasBounds.getSize());
Shinya Kitaoka 120a6e
      resource->downloadPalette(m_palette);
Shinya Kitaoka 120a6e
      return resource->downloadAll(TPoint(), m_loadedRas);
Shinya Kitaoka 120a6e
    } else
Shinya Kitaoka 120a6e
      return false;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TImageP getImage() const {
Shinya Kitaoka 120a6e
    if (!m_loadedRas) return TImageP();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TRasterCM32P cm(m_loadedRas);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TImageP result(cm ? TImageP(TToonzImageP(cm, cm->getBounds()))
Shinya Kitaoka 120a6e
                      : TImageP(TRasterImageP(m_loadedRas)));
Shinya Kitaoka 120a6e
    if (m_palette) result->setPalette(m_palette.getPointer());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    return result;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
//    TLevelColumnFx  implementation
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TLevelColumnFx::TLevelColumnFx()
Shinya Kitaoka 120a6e
    : m_levelColumn(0), m_isCachable(true), m_mutex(), m_offlineContext(0) {
Shinya Kitaoka 120a6e
  setName(L"LevelColumn");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TLevelColumnFx::~TLevelColumnFx() {
Shinya Kitaoka 120a6e
  if (m_offlineContext) delete m_offlineContext;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TLevelColumnFx::canHandle(const TRenderSettings &info, double frame) {
Shinya Kitaoka 120a6e
  // NOTE 1: Currently, it is necessary that level columns return FALSE for
Shinya Kitaoka 120a6e
  // raster levels - just a quick way to tell the cache functions that they
Shinya Kitaoka 120a6e
  // have to be cached.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!m_levelColumn) return true;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TXshCell cell = m_levelColumn->getCell(m_levelColumn->getFirstRow());
Shinya Kitaoka 120a6e
  if (cell.isEmpty()) return true;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TXshSimpleLevel *sl = cell.m_level->getSimpleLevel();
Shinya Kitaoka 120a6e
  if (!sl) return true;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return (sl->getType() == PLI_XSHLEVEL &&
Shinya Kitaoka 120a6e
          !vectorMustApplyCmappedFx(info.m_data));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TAffine TLevelColumnFx::handledAffine(const TRenderSettings &info,
Shinya Kitaoka 120a6e
                                      double frame) {
Shinya Kitaoka 120a6e
  if (!m_levelColumn) return TAffine();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TXshCell cell = m_levelColumn->getCell(m_levelColumn->getFirstRow());
Shinya Kitaoka 120a6e
  if (cell.isEmpty()) return TAffine();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TXshSimpleLevel *sl = cell.m_level->getSimpleLevel();
Shinya Kitaoka 120a6e
  if (!sl) return TAffine();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (sl->getType() == PLI_XSHLEVEL)
Shinya Kitaoka 120a6e
    return vectorMustApplyCmappedFx(info.m_data)
Shinya Kitaoka 120a6e
               ? TRasterFx::handledAffine(info, frame)
Shinya Kitaoka 120a6e
               : info.m_affine;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Accept any translation consistent with the image's pixels geometry
Shinya Kitaoka 120a6e
  TImageInfo imageInfo;
Shinya Kitaoka 120a6e
  getImageInfo(imageInfo, sl, cell.m_frameId);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TPointD pixelsOrigin(-0.5 * imageInfo.m_lx, -0.5 * imageInfo.m_ly);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const TAffine &aff = info.m_affine;
Shinya Kitaoka 120a6e
  if (aff.a11 != 1.0 || aff.a22 != 1.0 || aff.a12 != 0.0 || aff.a21 != 0.0)
Shinya Kitaoka 120a6e
    return TTranslation(-pixelsOrigin);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // This is a translation, ok. Just ensure it is consistent.
Shinya Kitaoka 120a6e
  TAffine consistentAff(aff);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  consistentAff.a13 -= pixelsOrigin.x, consistentAff.a23 -= pixelsOrigin.y;
Shinya Kitaoka 120a6e
  consistentAff.a13 = tfloor(consistentAff.a13),
Shinya Kitaoka 120a6e
  consistentAff.a23 = tfloor(consistentAff.a23);
Shinya Kitaoka 120a6e
  consistentAff.a13 += pixelsOrigin.x, consistentAff.a23 += pixelsOrigin.y;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return consistentAff;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TFilePath TLevelColumnFx::getPalettePath(int frame) const {
Shinya Kitaoka 120a6e
  if (!m_levelColumn) return TFilePath();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TXshCell cell = m_levelColumn->getCell(frame);
Shinya Kitaoka 120a6e
  if (cell.isEmpty()) return TFilePath();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TXshSimpleLevel *sl = cell.m_level->getSimpleLevel();
Shinya Kitaoka 120a6e
  if (!sl) return TFilePath();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (sl->getType() == TZP_XSHLEVEL)
Shinya Kitaoka 120a6e
    return sl->getScene()->decodeFilePath(
Shinya Kitaoka 120a6e
        sl->getPath().withNoFrame().withType("tpl"));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (sl->getType() == PLI_XSHLEVEL)
Shinya Kitaoka 120a6e
    return sl->getScene()->decodeFilePath(sl->getPath());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return TFilePath();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TPalette *TLevelColumnFx::getPalette(int frame) const {
Shinya Kitaoka 120a6e
  if (!m_levelColumn) return 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TXshCell cell = m_levelColumn->getCell(frame);
Shinya Kitaoka 120a6e
  if (cell.isEmpty()) return 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TXshSimpleLevel *sl = cell.m_level->getSimpleLevel();
Shinya Kitaoka 120a6e
  if (!sl) return 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return sl->getPalette();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TFx *TLevelColumnFx::clone(bool recursive) const {
Shinya Kitaoka 120a6e
  TLevelColumnFx *clonedFx =
Shinya Kitaoka 120a6e
      dynamic_cast<tlevelcolumnfx *="">(TFx::clone(recursive));</tlevelcolumnfx>
Shinya Kitaoka 120a6e
  assert(clonedFx);
Shinya Kitaoka 120a6e
  clonedFx->m_levelColumn = m_levelColumn;
Shinya Kitaoka 120a6e
  clonedFx->m_isCachable  = m_isCachable;
Shinya Kitaoka 120a6e
  return clonedFx;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TLevelColumnFx::doDryCompute(TRectD &rect, double frame,
Shinya Kitaoka 120a6e
                                  const TRenderSettings &info) {
Shinya Kitaoka 120a6e
  if (!m_levelColumn) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int row       = (int)frame;
Shinya Kitaoka 120a6e
  TXshCell cell = m_levelColumn->getCell(row);
Shinya Kitaoka 120a6e
  if (cell.isEmpty()) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TXshSimpleLevel *sl = cell.m_level->getSimpleLevel();
Shinya Kitaoka 120a6e
  if (!sl) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // In case this is a vector level, the image is renderized quickly and
Shinya Kitaoka 120a6e
  // directly at the
Shinya Kitaoka 120a6e
  // correct resolution. Caching is disabled in such case, at the moment.
Shinya Kitaoka 120a6e
  if (sl->getType() == PLI_XSHLEVEL) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int renderStatus =
Shinya Kitaoka 120a6e
      TRenderer::instance().getRenderStatus(TRenderer::renderId());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::string alias = getAlias(frame, TRenderSettings()) + "_image";
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TImageInfo imageInfo;
Shinya Kitaoka 120a6e
  getImageInfo(imageInfo, sl, cell.m_frameId);
Shinya Kitaoka 120a6e
  TRectD imgRect(0, 0, imageInfo.m_lx, imageInfo.m_ly);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (renderStatus == TRenderer::FIRSTRUN) {
Shinya Kitaoka 120a6e
    ResourceBuilder::declareResource(alias, 0, imgRect, frame, info, false);
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    LevelFxBuilder builder(alias, frame, info, sl, cell.m_frameId);
Shinya Kitaoka 120a6e
    builder.setRasBounds(TRect(0, 0, imageInfo.m_lx - 1, imageInfo.m_ly - 1));
Shinya Kitaoka 120a6e
    builder.simBuild(imgRect);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool isSubsheetChainOnColumn0(TXsheet *topXsheet, TXsheet *subsheet,
Shinya Kitaoka 120a6e
                              int frame) {
Shinya Kitaoka 120a6e
  if (topXsheet == subsheet) return true;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const TXshCell cell = topXsheet->getCell(frame, 0);
Shinya Kitaoka 120a6e
  if (!cell.m_level) return false;
Shinya Kitaoka 120a6e
  TXshChildLevel *cl = cell.m_level->getChildLevel();
Shinya Kitaoka 120a6e
  if (!cl) return false;
Shinya Kitaoka 120a6e
  return isSubsheetChainOnColumn0(cl->getXsheet(), subsheet, frame);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TLevelColumnFx::doCompute(TTile &tile, double frame,
Shinya Kitaoka 120a6e
                               const TRenderSettings &info) {
Shinya Kitaoka 120a6e
  if (!m_levelColumn) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Ensure that a corresponding cell and level exists
Shinya Kitaoka 120a6e
  int row       = (int)frame;
Shinya Kitaoka 120a6e
  TXshCell cell = m_levelColumn->getCell(row);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (cell.isEmpty()) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TXshSimpleLevel *sl = cell.m_level->getSimpleLevel();
Shinya Kitaoka 120a6e
  if (!sl) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TFrameId fid = cell.m_frameId;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TImageP img;
Shinya Kitaoka 120a6e
  TImageInfo imageInfo;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Now, fetch the image
Shinya Kitaoka 120a6e
  if (sl->getType() != PLI_XSHLEVEL) {
Shinya Kitaoka 120a6e
    // Raster case
Shinya Kitaoka 120a6e
    LevelFxBuilder builder(getAlias(frame, TRenderSettings()) + "_image", frame,
Shinya Kitaoka 120a6e
                           info, sl, fid);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    getImageInfo(imageInfo, sl, fid);
Shinya Kitaoka 120a6e
    TRectD imgRect(0, 0, imageInfo.m_lx, imageInfo.m_ly);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    builder.setRasBounds(TRect(0, 0, imageInfo.m_lx - 1, imageInfo.m_ly - 1));
Shinya Kitaoka 120a6e
    builder.build(imgRect);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    img = builder.getImage();
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    // Vector case (loading is immediate)
Shinya Kitaoka 120a6e
    if (!img) {
Shinya Kitaoka 120a6e
      img = sl->getFullsampledFrame(
Shinya Kitaoka 120a6e
          fid, ((info.m_bpp == 64) ? ImageManager::is64bitEnabled : 0) |
Shinya Kitaoka 120a6e
                   ImageManager::dontPutInCache);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Extract the required geometry
Shinya Kitaoka 120a6e
  TRect tileBounds(tile.getRaster()->getBounds());
Shinya Kitaoka 120a6e
  TRectD tileRectD = TRectD(tileBounds.x0, tileBounds.y0, tileBounds.x1 + 1,
Shinya Kitaoka 120a6e
                            tileBounds.y1 + 1) +
Shinya Kitaoka 120a6e
                     tile.m_pos;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // To be sure, if there is no image, return.
Shinya Kitaoka 120a6e
  if (!img) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRectD bBox = img->getBBox();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Discriminate image type
Shinya Kitaoka 120a6e
  if (TVectorImageP vectorImage = img) {
Shinya Kitaoka 120a6e
    // Vector case
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (vectorMustApplyCmappedFx(info.m_data)) {
Shinya Kitaoka 120a6e
      // Deal separately
Shinya Kitaoka 120a6e
      applyTzpFxsOnVector(vectorImage, tile, frame, info);
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      QMutexLocker m(&m_mutex);
Shinya Kitaoka 120a6e
      bBox = info.m_affine * vectorImage->getBBox();
Shinya Kitaoka 120a6e
      TDimension size(tile.getRaster()->getSize());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TAffine aff = TTranslation(-tile.m_pos.x, -tile.m_pos.y) *
Shinya Kitaoka 120a6e
                    TScale(1.0 / info.m_shrinkX, 1.0 / info.m_shrinkY) *
Shinya Kitaoka 120a6e
                    info.m_affine;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      applyCmappedFx(vectorImage, info.m_data, (int)frame);
Shinya Kitaoka 120a6e
      TPalette *vpalette = vectorImage->getPalette();
Shinya Kitaoka 120a6e
      assert(vpalette);
Shinya Kitaoka 120a6e
      m_isCachable = !vpalette->isAnimated();
Shinya Kitaoka 120a6e
      int oldFrame = vpalette->getFrame();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TVectorRenderData rd(TVectorRenderData::ProductionSettings(), aff,
Shinya Kitaoka 120a6e
                           TRect(size), vpalette);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (!m_offlineContext || m_offlineContext->getLx() < size.lx ||
Shinya Kitaoka 120a6e
          m_offlineContext->getLy() < size.ly) {
Shinya Kitaoka 120a6e
        if (m_offlineContext) delete m_offlineContext;
Shinya Kitaoka 120a6e
        m_offlineContext = new TOfflineGL(size);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      m_offlineContext->makeCurrent();
Shinya Kitaoka 120a6e
      m_offlineContext->clear(TPixel32(0, 0, 0, 0));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // If level has animated palette, it is necessary to lock palette's color
Shinya Kitaoka 120a6e
      // against
Shinya Kitaoka 120a6e
      // concurrents TPalette::setFrame.
Shinya Kitaoka 120a6e
      if (!m_isCachable) vpalette->mutex()->lock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      vpalette->setFrame((int)frame);
Shinya Kitaoka 120a6e
      m_offlineContext->draw(vectorImage, rd, true);
Shinya Kitaoka 120a6e
      vpalette->setFrame(oldFrame);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (!m_isCachable) vpalette->mutex()->unlock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      m_offlineContext->getRaster(tile.getRaster());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      m_offlineContext->doneCurrent();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    // Raster case
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TRasterP ras;
Shinya Kitaoka 120a6e
    TAffine aff;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TRasterImageP ri = img;
Shinya Kitaoka 120a6e
    TToonzImageP ti  = img;
Shinya Kitaoka 120a6e
    img              = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (ri) {
Shinya Kitaoka 120a6e
      // Fullcolor case
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      ras = ri->getRaster();
Shinya Kitaoka 120a6e
      ri  = 0;
Shinya Kitaoka 120a6e
      TRaster32P ras32(ras);
Shinya Kitaoka 120a6e
      TRaster64P ras64(ras);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // Ensure that ras is either a 32 or 64 fullcolor.
Shinya Kitaoka 120a6e
      // Otherwise, we have to convert it.
Shinya Kitaoka 120a6e
      if (!ras32 && !ras64) {
Shinya Kitaoka 120a6e
        TRasterP tileRas(tile.getRaster());
Shinya Kitaoka 120a6e
        TRaster32P tileRas32(tileRas);
Shinya Kitaoka 120a6e
        TRaster64P tileRas64(tileRas);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if (tileRas32) {
Shinya Kitaoka 120a6e
          ras32 = TRaster32P(ras->getLx(), ras->getLy());
Shinya Kitaoka 120a6e
          TRop::convert(ras32, ras);
Shinya Kitaoka 120a6e
          ras = ras32;
Shinya Kitaoka 120a6e
        } else if (tileRas64) {
Shinya Kitaoka 120a6e
          ras64 = TRaster64P(ras->getLx(), ras->getLy());
Shinya Kitaoka 120a6e
          TRop::convert(ras64, ras);
Shinya Kitaoka 120a6e
          ras = ras64;
Shinya Kitaoka 120a6e
        } else
Shinya Kitaoka 120a6e
          assert(0);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      TXsheet *xsh  = m_levelColumn->getLevelColumn()->getXsheet();
Shinya Kitaoka 120a6e
      TXsheet *txsh = sl->getScene()->getTopXsheet();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      LevelProperties *levelProp = sl->getProperties();
Shinya Kitaoka 120a6e
      if (Preferences::instance()->isIgnoreAlphaonColumn1Enabled() &&
Shinya Kitaoka 120a6e
          m_levelColumn->getIndex() == 0 &&
Shinya Kitaoka 120a6e
          isSubsheetChainOnColumn0(txsh, xsh, frame)) {
Shinya Kitaoka 120a6e
        TRasterP appRas(ras->clone());
Shinya Kitaoka 120a6e
        setMaxMatte(appRas);
Shinya Kitaoka 120a6e
        ras = appRas;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      if (levelProp->doPremultiply()) {
Shinya Kitaoka 120a6e
        TRasterP appRas = ras->clone();
Shinya Kitaoka 120a6e
        TRop::premultiply(appRas);
Shinya Kitaoka 120a6e
        ras = appRas;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      if (levelProp->whiteTransp()) {
Shinya Kitaoka 120a6e
        TRasterP appRas(ras->clone());
Shinya Kitaoka 120a6e
        TRop::whiteTransp(appRas);
Shinya Kitaoka 120a6e
        ras = appRas;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      if (levelProp->antialiasSoftness() > 0) {
Shinya Kitaoka 120a6e
        TRasterP appRas = ras->create(ras->getLx(), ras->getLy());
Shinya Kitaoka 120a6e
        TRop::antialias(ras, appRas, 10, levelProp->antialiasSoftness());
Shinya Kitaoka 120a6e
        ras = appRas;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (TXshSimpleLevel::m_fillFullColorRaster) {
Shinya Kitaoka 120a6e
        TRasterP appRas(ras->clone());
Shinya Kitaoka 120a6e
        FullColorAreaFiller filler(appRas);
Shinya Kitaoka 120a6e
        TPaletteP palette = new TPalette();
Shinya Kitaoka 120a6e
        int styleId       = palette->getPage(0)->addStyle(TPixel32::White);
Shinya Kitaoka 120a6e
        FillParameters params;
Shinya Kitaoka 120a6e
        params.m_palette      = palette.getPointer();
Shinya Kitaoka 120a6e
        params.m_styleId      = styleId;
Shinya Kitaoka 120a6e
        params.m_minFillDepth = 0;
Shinya Kitaoka 120a6e
        params.m_maxFillDepth = 15;
Shinya Kitaoka 120a6e
        filler.rectFill(appRas->getBounds(), params, false);
Shinya Kitaoka 120a6e
        ras = appRas;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else if (ti) {
Shinya Kitaoka 120a6e
      // Colormap case
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // Use the imageInfo's dpi
Shinya Kitaoka 120a6e
      ti->setDpi(imageInfo.m_dpix, imageInfo.m_dpiy);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TImageP newImg = applyTzpFxs(ti, frame, info);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      ri = newImg;
Shinya Kitaoka 120a6e
      ti = newImg;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (ri)
Shinya Kitaoka 120a6e
        ras = ri->getRaster();
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        ras = ti->getRaster();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (sl->getProperties()->antialiasSoftness() > 0) {
Shinya Kitaoka 120a6e
        TRasterP appRas = ras->create(ras->getLx(), ras->getLy());
Shinya Kitaoka 120a6e
        TRop::antialias(ras, appRas, 10,
Shinya Kitaoka 120a6e
                        sl->getProperties()->antialiasSoftness());
Shinya Kitaoka 120a6e
        ras = appRas;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      ri = 0;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (ras) {
Shinya Kitaoka 120a6e
      double lx_2 = ras->getLx() / 2.0;
Shinya Kitaoka 120a6e
      double ly_2 = ras->getLy() / 2.0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TRenderSettings infoAux(info);
Shinya Kitaoka 120a6e
      assert(info.m_affine.isTranslation());
Shinya Kitaoka 120a6e
      infoAux.m_data.clear();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // Place the output rect in the image's reference
Shinya Kitaoka 120a6e
      tileRectD += TPointD(lx_2 - info.m_affine.a13, ly_2 - info.m_affine.a23);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // Then, retrieve loaded image's interesting region
Shinya Kitaoka 120a6e
      TRectD inTileRectD;
Shinya Kitaoka 120a6e
      if (ti) {
Shinya Kitaoka 120a6e
        TRect saveBox(ti->getSavebox());
Shinya Kitaoka 120a6e
        inTileRectD =
Shinya Kitaoka 120a6e
            TRectD(saveBox.x0, saveBox.y0, saveBox.x1 + 1, saveBox.y1 + 1);
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        TRect rasBounds(ras->getBounds());
Shinya Kitaoka 120a6e
        inTileRectD = TRectD(rasBounds.x0, rasBounds.y0, rasBounds.x1 + 1,
Shinya Kitaoka 120a6e
                             rasBounds.y1 + 1);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // And intersect the two
Shinya Kitaoka 120a6e
      inTileRectD *= tileRectD;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // Should the intersection be void, return
Shinya Kitaoka 120a6e
      if (inTileRectD.x0 >= inTileRectD.x1 || inTileRectD.y0 >= inTileRectD.y1)
Shinya Kitaoka 120a6e
        return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // Output that intersection in the requested tile
Shinya Kitaoka 120a6e
      TRect inTileRect(tround(inTileRectD.x0), tround(inTileRectD.y0),
Shinya Kitaoka 120a6e
                       tround(inTileRectD.x1) - 1, tround(inTileRectD.y1) - 1);
Shinya Kitaoka 120a6e
      TTile inTile(ras->extract(inTileRect),
Shinya Kitaoka 120a6e
                   inTileRectD.getP00() + TPointD(-lx_2, -ly_2));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // Observe that inTile is in the standard reference, ie image's minus the
Shinya Kitaoka 120a6e
      // center coordinates
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (ti) {
Shinya Kitaoka 120a6e
        // In the colormapped case, we have to convert the cmap to fullcolor
Shinya Kitaoka 120a6e
        TPalette *palette = ti->getPalette();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if (!m_isCachable) palette->mutex()->lock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        int prevFrame = palette->getFrame();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        palette->setFrame((int)frame);
Shinya Kitaoka 120a6e
        TTile auxtile(TRaster32P(inTile.getRaster()->getSize()), inTile.m_pos);
Shinya Kitaoka 120a6e
        TRop::convert(auxtile, inTile, palette, false, true);
Shinya Kitaoka 120a6e
        palette->setFrame(prevFrame);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if (!m_isCachable) palette->mutex()->unlock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        inTile.setRaster(auxtile.getRaster());
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TRasterFx::applyAffine(tile, inTile, infoAux);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TImageP TLevelColumnFx::applyTzpFxs(TToonzImageP &ti, double frame,
Shinya Kitaoka 120a6e
                                    const TRenderSettings &info) {
Shinya Kitaoka 120a6e
  double scale = sqrt(fabs(info.m_affine.det()));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int prevFrame = ti->getPalette()->getFrame();
Shinya Kitaoka 120a6e
  m_isCachable  = !ti->getPalette()->isAnimated();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!m_isCachable) ti->getPalette()->mutex()->lock();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TPaletteP palette(ti->getPalette());
Shinya Kitaoka 120a6e
  palette->setFrame((int)frame);
Shinya Kitaoka 120a6e
  TImageP newImg = applyCmappedFx(ti, info.m_data, (int)frame, scale);
Shinya Kitaoka 120a6e
  palette->setFrame(prevFrame);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!m_isCachable) palette->mutex()->unlock();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return newImg;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TLevelColumnFx::applyTzpFxsOnVector(const TVectorImageP &vi, TTile &tile,
Shinya Kitaoka 120a6e
                                         double frame,
Shinya Kitaoka 120a6e
                                         const TRenderSettings &info) {
Shinya Kitaoka 120a6e
  TRect tileBounds(tile.getRaster()->getBounds());
Shinya Kitaoka 120a6e
  TRectD tileRectD = TRectD(tileBounds.x0, tileBounds.y0, tileBounds.x1 + 1,
Shinya Kitaoka 120a6e
                            tileBounds.y1 + 1) +
Shinya Kitaoka 120a6e
                     tile.m_pos;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Info's affine is not the identity only in case the loaded image is a vector
Shinya Kitaoka 120a6e
  // one.
Shinya Kitaoka 120a6e
  double scale    = sqrt(fabs(info.m_affine.det()));
Shinya Kitaoka 120a6e
  int enlargement = getEnlargement(info.m_data, scale);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Extract the vector image's groups
Shinya Kitaoka 120a6e
  std::vector<tvectorimagep> groupsList;</tvectorimagep>
Shinya Kitaoka 120a6e
  getGroupsList(vi, groupsList);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // For each group, apply the tzp fxs stored in info. The result is immediately
Shinya Kitaoka 120a6e
  // converted
Shinya Kitaoka 120a6e
  // to a raster image if necessary.
Shinya Kitaoka 120a6e
  unsigned int i;
Shinya Kitaoka 120a6e
  for (i = 0; i < groupsList.size(); ++i) {
Shinya Kitaoka 120a6e
    TVectorImageP &groupVi = groupsList[i];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Extract the group's bbox.
Shinya Kitaoka 120a6e
    TRectD groupBBox(info.m_affine * groupVi->getBBox());
Shinya Kitaoka 120a6e
    if (!mustApplySandorFx(info.m_data)) groupBBox *= tileRectD;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    groupBBox = groupBBox.enlarge(enlargement);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (groupBBox.x0 >= groupBBox.x1 || groupBBox.y0 >= groupBBox.y1) continue;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Ensure that groupBBox and tile have the same integer geometry
Shinya Kitaoka 120a6e
    groupBBox -= tile.m_pos;
Shinya Kitaoka 120a6e
    groupBBox.x0 = tfloor(groupBBox.x0);
Shinya Kitaoka 120a6e
    groupBBox.y0 = tfloor(groupBBox.y0);
Shinya Kitaoka 120a6e
    groupBBox.x1 = tceil(groupBBox.x1);
Shinya Kitaoka 120a6e
    groupBBox.y1 = tceil(groupBBox.y1);
Shinya Kitaoka 120a6e
    groupBBox += tile.m_pos;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Build groupBBox's relative position to the tile
Shinya Kitaoka 120a6e
    TPoint groupRelativePosToTile(groupBBox.x0 - tile.m_pos.x,
Shinya Kitaoka 120a6e
                                  groupBBox.y0 - tile.m_pos.y);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Convert the group to a strictly sufficient Toonz image
Shinya Kitaoka 120a6e
    TToonzImageP groupTi = ToonzImageUtils::vectorToToonzImage(
Shinya Kitaoka 120a6e
        groupVi, info.m_affine, groupVi->getPalette(), groupBBox.getP00(),
Shinya Kitaoka 120a6e
        TDimension(groupBBox.getLx(), groupBBox.getLy()), &info.m_data, true);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Apply the tzp fxs to the converted Toonz image
Shinya Kitaoka 120a6e
    TImageP groupResult = applyTzpFxs(groupTi, frame, info);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // If necessary, convert the result to fullcolor
Shinya Kitaoka 120a6e
    TRasterImageP groupRi = groupResult;
Shinya Kitaoka 120a6e
    if (!groupRi) {
Shinya Kitaoka 120a6e
      groupTi = groupResult;
Shinya Kitaoka 120a6e
      assert(groupTi);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      TRasterP groupTiRas(groupTi->getRaster());
Shinya Kitaoka 120a6e
      TRaster32P tempRas(groupTiRas->getSize());
Shinya Kitaoka 120a6e
      groupRi = TRasterImageP(tempRas);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      TRop::convert(tempRas, groupTiRas, groupTi->getPalette());
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Over the group image on the output
Shinya Kitaoka 120a6e
    TRasterP tileRas(tile.getRaster());
Shinya Kitaoka 120a6e
    TRop::over(tileRas, groupRi->getRaster(), groupRelativePosToTile);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TLevelColumnFx::getMemoryRequirement(const TRectD &rect, double frame,
Shinya Kitaoka 120a6e
                                         const TRenderSettings &info) {
Shinya Kitaoka 120a6e
  // Sandor fxs are currently considered *VERY* inefficient upon tile
Shinya Kitaoka 120a6e
  // subdivision
Shinya Kitaoka 120a6e
  if (mustApplySandorFx(info.m_data)) {
Shinya Kitaoka 120a6e
    return -1;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TLevelColumnFx::getImageInfo(TImageInfo &info, TXshSimpleLevel *sl,
Shinya Kitaoka 120a6e
                                  TFrameId frameId) {
Shinya Kitaoka 120a6e
  int type = sl->getType();
Shinya Kitaoka 120a6e
  assert(type != PLI_XSHLEVEL);
Shinya Kitaoka 120a6e
  if (type == PLI_XSHLEVEL) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::string imageId = sl->getImageId(frameId);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const TImageInfo *storedInfo =
Shinya Kitaoka 120a6e
      ImageManager::instance()->getInfo(imageId, ImageManager::none, 0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!storedInfo)  // sulle pict caricate info era nullo, ma l'immagine c'e'!
Shinya Kitaoka 120a6e
  // con la getFullSampleFrame riprendo   l'immagine e ricalcolo la savebox...
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    TImageP img;
Shinya Kitaoka 120a6e
    if (!(img =
Shinya Kitaoka 120a6e
              sl->getFullsampledFrame(frameId, ImageManager::dontPutInCache))) {
Shinya Kitaoka 120a6e
      assert(false);
Shinya Kitaoka 120a6e
      return;
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    info.m_lx = (int)img->getBBox().getLx();
Shinya Kitaoka 120a6e
    info.m_ly = (int)img->getBBox().getLy();
Shinya Kitaoka 120a6e
    info.m_x0 = info.m_y0 = 0;
Shinya Kitaoka 120a6e
    info.m_x1             = (int)img->getBBox().getP11().x;
Shinya Kitaoka 120a6e
    info.m_y1             = (int)img->getBBox().getP11().y;
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    info = *storedInfo;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TLevelColumnFx::doGetBBox(double frame, TRectD &bBox,
Shinya Kitaoka 120a6e
                               const TRenderSettings &info) {
Shinya Kitaoka 120a6e
  // Usual preliminaries (make sure a level/cell exists, etc...)
Shinya Kitaoka 120a6e
  if (!m_levelColumn) return false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int row              = (int)frame;
Shinya Kitaoka 120a6e
  const TXshCell &cell = m_levelColumn->getCell(row);
Shinya Kitaoka 120a6e
  if (cell.isEmpty()) return false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TXshLevelP xshl = cell.m_level;
Shinya Kitaoka 120a6e
  if (!xshl) return false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TXshSimpleLevel *sl = xshl->getSimpleLevel();
Shinya Kitaoka 120a6e
  if (!sl) return false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double dpi = 1.0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Discriminate for level type
Shinya Kitaoka 120a6e
  int type = xshl->getType();
Shinya Kitaoka 120a6e
  if (type != PLI_XSHLEVEL) {
Shinya Kitaoka 120a6e
    TImageInfo imageInfo;
Shinya Kitaoka 120a6e
    getImageInfo(imageInfo, sl, cell.m_frameId);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TRect imageSavebox(imageInfo.m_x0, imageInfo.m_y0, imageInfo.m_x1,
Shinya Kitaoka 120a6e
                       imageInfo.m_y1);
Shinya Kitaoka 120a6e
    double cx = 0.5 * imageInfo.m_lx;
Shinya Kitaoka 120a6e
    double cy = 0.5 * imageInfo.m_ly;
Shinya Kitaoka 120a6e
    double x0 = (imageSavebox.x0 - cx);
Shinya Kitaoka 120a6e
    double y0 = (imageSavebox.y0 - cy);
Shinya Kitaoka 120a6e
    double x1 = x0 + imageSavebox.getLx();
Shinya Kitaoka 120a6e
    double y1 = y0 + imageSavebox.getLy();
Shinya Kitaoka 120a6e
    bBox      = TRectD(x0, y0, x1, y1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    dpi = imageInfo.m_dpix / Stage::inch;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    TImageP img = m_levelColumn->getCell(row).getImage(false);
Shinya Kitaoka 120a6e
    if (!img) return false;
Shinya Kitaoka 120a6e
    bBox = img->getBBox();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Add the enlargement of the bbox due to Tzp render datas
Shinya Kitaoka 120a6e
  if (info.m_data.size()) {
Shinya Kitaoka 120a6e
    TRectD imageBBox(bBox);
Shinya Kitaoka 120a6e
    for (unsigned int i = 0; i < info.m_data.size(); ++i) {
Shinya Kitaoka 120a6e
      TRectD enlargedImageBBox = info.m_data[i]->getBBoxEnlargement(imageBBox);
Shinya Kitaoka 120a6e
      double enlargement       = enlargedImageBBox.x1 - imageBBox.x1;
Shinya Kitaoka 120a6e
      bBox += imageBBox.enlarge(enlargement * dpi);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
const TPersistDeclaration *TLevelColumnFx::getDeclaration() const {
Shinya Kitaoka 120a6e
  return &columnFxInfo;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::string TLevelColumnFx::getPluginId() const { return "Toonz_"; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TFxTimeRegion TLevelColumnFx::getTimeRegion() const {
Shinya Kitaoka 120a6e
  if (!m_levelColumn) return TFxTimeRegion();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int first = m_levelColumn->getFirstRow();
Shinya Kitaoka 120a6e
  int last  = m_levelColumn->getRowCount();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return TFxTimeRegion(first, last);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TLevelColumnFx::setColumn(TXshLevelColumn *column) {
Shinya Kitaoka 120a6e
  m_levelColumn = column;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::wstring TLevelColumnFx::getColumnId() const {
Shinya Kitaoka 120a6e
  if (!m_levelColumn) return L"Col?";
Shinya Kitaoka 120a6e
  return L"Col" + std::to_wstring(m_levelColumn->getIndex() + 1);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::wstring TLevelColumnFx::getColumnName() const {
Shinya Kitaoka 120a6e
  if (!m_levelColumn) return L"";
Shinya Kitaoka 120a6e
  int idx = getColumnIndex();
Shinya Kitaoka 120a6e
  return ::to_wstring(m_levelColumn->getXsheet()
Shinya Kitaoka 120a6e
                          ->getStageObject(TStageObjectId::ColumnId(idx))
Shinya Kitaoka 120a6e
                          ->getName());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::string TLevelColumnFx::getAlias(double frame,
Shinya Kitaoka 120a6e
                                     const TRenderSettings &info) const {
Shinya Kitaoka 120a6e
  if (!m_levelColumn || m_levelColumn->getCell((int)frame).isEmpty())
Shinya Kitaoka 120a6e
    return std::string();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const TXshCell &cell = m_levelColumn->getCell((int)frame);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TFilePath fp;
Shinya Kitaoka 120a6e
  TXshSimpleLevel *sl = cell.getSimpleLevel();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!sl) {
Shinya Kitaoka 120a6e
    // Try with the sub-xsheet case
Shinya Kitaoka 120a6e
    TXshChildLevel *childLevel = cell.m_level->getChildLevel();
Shinya Kitaoka 120a6e
    if (childLevel) return ::getAlias(childLevel->getXsheet(), frame, info);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    return std::string();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TFilePath path = sl->getPath();
Shinya Kitaoka 120a6e
  if (!cell.m_frameId.isNoFrame())
Shinya Kitaoka 120a6e
    fp = path.withFrame(cell.m_frameId);
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    fp = path;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::string rdata;
Shinya Kitaoka 120a6e
  std::vector<trasterfxrenderdatap>::const_iterator it = info.m_data.begin();</trasterfxrenderdatap>
Shinya Kitaoka 120a6e
  for (; it != info.m_data.end(); ++it) {
Shinya Kitaoka 120a6e
    TRasterFxRenderDataP data = *it;
Shinya Kitaoka 120a6e
    if (data) rdata += data->toString();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (sl->getType() == PLI_XSHLEVEL || sl->getType() == TZP_XSHLEVEL) {
Shinya Kitaoka 120a6e
    TPalette *palette = cell.getPalette();
Shinya Kitaoka 120a6e
    if (palette && palette->isAnimated())
Shinya Kitaoka 120a6e
      rdata += "animatedPlt" + std::to_string(frame);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (Preferences::instance()->isIgnoreAlphaonColumn1Enabled()) {
Shinya Kitaoka 120a6e
    TXsheet *xsh  = m_levelColumn->getLevelColumn()->getXsheet();
Shinya Kitaoka 120a6e
    TXsheet *txsh = sl->getScene()->getTopXsheet();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (m_levelColumn->getIndex() == 0 &&
Shinya Kitaoka 120a6e
        isSubsheetChainOnColumn0(txsh, xsh, frame))
Shinya Kitaoka 120a6e
      rdata += "column_0";
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return getFxType() + "[" + ::to_string(fp.getWideString()) + "," + rdata +
Shinya Kitaoka 120a6e
         "]";
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TLevelColumnFx::getColumnIndex() const {
Shinya Kitaoka 120a6e
  return m_levelColumn ? m_levelColumn->getIndex() : -1;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TXshColumn *TLevelColumnFx::getXshColumn() const { return m_levelColumn; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TLevelColumnFx::compute(TFlash &flash, int frame) {
Shinya Kitaoka 120a6e
  if (!m_levelColumn) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TImageP img = m_levelColumn->getCell(frame).getImage(false);
Shinya Kitaoka 120a6e
  if (!img) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  flash.draw(img, 0);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TAffine TLevelColumnFx::getDpiAff(int frame) {
Shinya Kitaoka 120a6e
  if (!m_levelColumn) return TAffine();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TXshCell cell = m_levelColumn->getCell(frame);
Shinya Kitaoka 120a6e
  if (cell.isEmpty()) return TAffine();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TXshSimpleLevel *sl = cell.m_level->getSimpleLevel();
Shinya Kitaoka 120a6e
  TFrameId fid        = cell.m_frameId;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (sl) return ::getDpiAffine(sl, cell.m_frameId, true);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return TAffine();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TLevelColumnFx::saveData(TOStream &os) {
Shinya Kitaoka 120a6e
  assert(m_levelColumn);
Shinya Kitaoka 120a6e
  TFx::saveData(os);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TLevelColumnFx::loadData(TIStream &is) {
Shinya Kitaoka 120a6e
  // The internal numeric identifier is set here but not in constructors.
Shinya Kitaoka 120a6e
  // This is *intended* as fx cloning needs to retain the original id
Shinya Kitaoka 120a6e
  // through the fxs tree deployment procedure happening just before a
Shinya Kitaoka 120a6e
  // render process (see scenefx.cpp).
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TFx::loadData(is);
Shinya Kitaoka 120a6e
  setNewIdentifier();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
//    TPaletteColumnFx  implementation
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TPaletteColumnFx::TPaletteColumnFx() : m_paletteColumn(0) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TPaletteColumnFx::~TPaletteColumnFx() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TFx *TPaletteColumnFx::clone(bool recursive) const {
Shinya Kitaoka 120a6e
  TPaletteColumnFx *clonedFx =
Shinya Kitaoka 120a6e
      dynamic_cast<tpalettecolumnfx *="">(TFx::clone(recursive));</tpalettecolumnfx>
Shinya Kitaoka 120a6e
  assert(clonedFx);
Shinya Kitaoka 120a6e
  clonedFx->m_paletteColumn = m_paletteColumn;
Shinya Kitaoka 120a6e
  return clonedFx;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TPaletteColumnFx::doCompute(TTile &tile, double frame,
Shinya Kitaoka 120a6e
                                 const TRenderSettings &) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TPaletteColumnFx::doGetBBox(double frame, TRectD &bBox,
Shinya Kitaoka 120a6e
                                 const TRenderSettings &info) {
Shinya Kitaoka 120a6e
  return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TAffine TPaletteColumnFx::getDpiAff(int frame) { return TAffine(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TPaletteColumnFx::canHandle(const TRenderSettings &info, double frame) {
Shinya Kitaoka 120a6e
  return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TFilePath TPaletteColumnFx::getPalettePath(int frame) const {
Shinya Kitaoka 120a6e
  if (!m_paletteColumn) return TFilePath();
Shinya Kitaoka 120a6e
  TXshCell cell = m_paletteColumn->getCell(frame);
Shinya Kitaoka 120a6e
  if (cell.isEmpty() || cell.m_level->getPaletteLevel() == 0)
Shinya Kitaoka 120a6e
    return TFilePath();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TXshPaletteLevel *paletteLevel = cell.m_level->getPaletteLevel();
Shinya Kitaoka 120a6e
  TFilePath path                 = paletteLevel->getPath();
Shinya Kitaoka 120a6e
  path = paletteLevel->getScene()->decodeFilePath(path);
Shinya Kitaoka 120a6e
  return path;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TPalette *TPaletteColumnFx::getPalette(int frame) const {
Shinya Kitaoka 120a6e
  if (!m_paletteColumn) return 0;
Shinya Kitaoka 120a6e
  TXshCell cell = m_paletteColumn->getCell(frame);
Shinya Kitaoka 120a6e
  if (cell.isEmpty() || cell.m_level->getPaletteLevel() == 0) return 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TXshPaletteLevel *paletteLevel = cell.m_level->getPaletteLevel();
Shinya Kitaoka 120a6e
  return paletteLevel->getPalette();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
const TPersistDeclaration *TPaletteColumnFx::getDeclaration() const {
Shinya Kitaoka 120a6e
  return &paletteColumnFxInfo;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::string TPaletteColumnFx::getPluginId() const { return "Toonz_"; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TFxTimeRegion TPaletteColumnFx::getTimeRegion() const {
Shinya Kitaoka 120a6e
  int first = 0;
Shinya Kitaoka 120a6e
  int last  = 11;
Shinya Kitaoka 120a6e
  return TFxTimeRegion(first, last);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::wstring TPaletteColumnFx::getColumnName() const {
Shinya Kitaoka 120a6e
  if (!m_paletteColumn) return L"Col?";
Shinya Kitaoka 120a6e
  return L"Col" + std::to_wstring(m_paletteColumn->getIndex() + 1);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::wstring TPaletteColumnFx::getColumnId() const {
Shinya Kitaoka 120a6e
  if (!m_paletteColumn) return L"Col?";
Shinya Kitaoka 120a6e
  return L"Col" + std::to_wstring(m_paletteColumn->getIndex() + 1);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::string TPaletteColumnFx::getAlias(double frame,
Shinya Kitaoka 120a6e
                                       const TRenderSettings &info) const {
Shinya Kitaoka 120a6e
  TFilePath palettePath = getPalettePath(frame);
Shinya Kitaoka 120a6e
  return "TPaletteColumnFx[" + ::to_string(palettePath.getWideString()) + "]";
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TPaletteColumnFx::compute(TFlash &flash, int frame) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TPaletteColumnFx::getColumnIndex() const {
Shinya Kitaoka 120a6e
  return m_paletteColumn ? m_paletteColumn->getIndex() : -1;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TXshColumn *TPaletteColumnFx::getXshColumn() const { return m_paletteColumn; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
//    TZeraryColumnFx  implementation
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TZeraryColumnFx::TZeraryColumnFx() : m_zeraryFxColumn(0), m_fx(0) {
Shinya Kitaoka 120a6e
  setName(L"ZeraryColumn");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TZeraryColumnFx::~TZeraryColumnFx() {
Shinya Kitaoka 120a6e
  if (m_zeraryFxColumn) m_zeraryFxColumn->release();
Shinya Kitaoka 120a6e
  if (m_fx) {
Shinya Kitaoka 120a6e
    m_fx->m_columnFx = 0;
Shinya Kitaoka 120a6e
    m_fx->release();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TZeraryColumnFx::doCompute(TTile &tile, double frame,
Shinya Kitaoka 120a6e
                                const TRenderSettings &info) {
Shinya Kitaoka 120a6e
  if (m_zeraryFxColumn) {
Shinya Kitaoka 120a6e
    TRasterFx *fx = dynamic_cast<trasterfx *="">(m_fx);</trasterfx>
Shinya Kitaoka 120a6e
    if (fx) fx->compute(tile, frame, info);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TZeraryColumnFx::doGetBBox(double frame, TRectD &bBox,
Shinya Kitaoka 120a6e
                                const TRenderSettings &info) {
Shinya Kitaoka 120a6e
  if (m_zeraryFxColumn) {
Shinya Kitaoka 120a6e
    TRasterFx *fx = dynamic_cast<trasterfx *="">(m_fx);</trasterfx>
Shinya Kitaoka 120a6e
    if (fx) return fx->doGetBBox(frame, bBox, info);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
const TPersistDeclaration *TZeraryColumnFx::getDeclaration() const {
Shinya Kitaoka 120a6e
  return &zeraryColumnFxInfo;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::string TZeraryColumnFx::getPluginId() const { return "Toonz_"; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TFxTimeRegion TZeraryColumnFx::getTimeRegion() const {
Shinya Kitaoka 120a6e
  return TFxTimeRegion(0, (std::numeric_limits<double>::max)());</double>
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TZeraryColumnFx::setColumn(TXshZeraryFxColumn *column) {
Shinya Kitaoka 120a6e
  m_zeraryFxColumn = column;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::wstring TZeraryColumnFx::getColumnName() const {
Shinya Kitaoka 120a6e
  return getZeraryFx()->getName();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::wstring TZeraryColumnFx::getColumnId() const {
Shinya Kitaoka 120a6e
  return getZeraryFx()->getFxId();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TZeraryColumnFx::setZeraryFx(TFx *fx) {
Shinya Kitaoka 120a6e
  TZeraryFx *zfx = static_cast<tzeraryfx *="">(fx);</tzeraryfx>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (fx) {
Shinya Kitaoka 120a6e
    assert(dynamic_cast<tzeraryfx *="">(fx));</tzeraryfx>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    fx->addRef();
Shinya Kitaoka 120a6e
    fx->setNewIdentifier();  // When adopting zerary fxs, ensure that they
Shinya Kitaoka 120a6e
                             // have a new numeric identifier
Shinya Kitaoka 120a6e
    zfx->m_columnFx = this;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_fx) {
Shinya Kitaoka 120a6e
    m_fx->m_columnFx = 0;
Shinya Kitaoka 120a6e
    m_fx->release();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_fx = zfx;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::string TZeraryColumnFx::getAlias(double frame,
Shinya Kitaoka 120a6e
                                      const TRenderSettings &info) const {
Shinya Kitaoka 120a6e
  return "TZeraryColumnFx[" + m_fx->getAlias(frame, info) + "]";
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TZeraryColumnFx::loadData(TIStream &is) {
Shinya Kitaoka 120a6e
  if (m_fx) m_fx->release();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_fx        = 0;
Shinya Kitaoka 120a6e
  TPersist *p = 0;
Shinya Kitaoka 120a6e
  is >> p;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_fx = dynamic_cast<tzeraryfx *="">(p);</tzeraryfx>
Shinya Kitaoka 120a6e
  if (m_fx) {
Shinya Kitaoka 120a6e
    m_fx->addRef();
Shinya Kitaoka 120a6e
    m_fx->m_columnFx = this;
Shinya Kitaoka 120a6e
    m_fx->setNewIdentifier();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TFx::loadData(is);
Shinya Kitaoka 120a6e
  setNewIdentifier();  // Same as with TColumnFx
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TZeraryColumnFx::saveData(TOStream &os) {
Shinya Kitaoka 120a6e
  assert(m_fx);
Shinya Kitaoka 120a6e
  os << m_fx;
Shinya Kitaoka 120a6e
  TFx::saveData(os);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TZeraryColumnFx::getColumnIndex() const {
Shinya Kitaoka 120a6e
  return m_zeraryFxColumn ? m_zeraryFxColumn->getIndex() : -1;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TXshColumn *TZeraryColumnFx::getXshColumn() const { return m_zeraryFxColumn; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
//    TXSheetFx  implementation
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
const TPersistDeclaration *TXsheetFx::getDeclaration() const {
Shinya Kitaoka 120a6e
  return &infoTXsheetFx;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TXsheetFx::TXsheetFx() : m_fxDag(0) { setName(L"Xsheet"); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TXsheetFx::doCompute(TTile &tile, double frame, const TRenderSettings &) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TXsheetFx::doGetBBox(double frame, TRectD &bBox,
Shinya Kitaoka 120a6e
                          const TRenderSettings &info) {
Shinya Kitaoka 120a6e
  return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::string TXsheetFx::getPluginId() const { return "Toonz_"; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::string TXsheetFx::getAlias(double frame,
Shinya Kitaoka 120a6e
                                const TRenderSettings &info) const {
Shinya Kitaoka 120a6e
  std::string alias = getFxType();
Shinya Kitaoka 120a6e
  alias += "[";
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Add each terminal fx's alias
Shinya Kitaoka 120a6e
  TFxSet *terminalFxs = m_fxDag->getTerminalFxs();
Shinya Kitaoka 120a6e
  int i, fxsCount = terminalFxs->getFxCount();
Shinya Kitaoka 120a6e
  for (i = 0; i < fxsCount; ++i) {
Shinya Kitaoka 120a6e
    alias +=
Shinya Kitaoka 120a6e
        static_cast<trasterfx *="">(terminalFxs->getFx(i))->getAlias(frame, info) +</trasterfx>
Shinya Kitaoka 120a6e
        ",";
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return alias + "]";
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TXsheetFx::setFxDag(FxDag *fxDag) { m_fxDag = fxDag; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
//    TOutputFx  implementation
Toshihiro Shimizu 890ddd
//****************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TOutputFx::TOutputFx() {
Shinya Kitaoka 120a6e
  addInputPort("source", m_input);
Shinya Kitaoka 120a6e
  setName(L"Output");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
const TPersistDeclaration *TOutputFx::getDeclaration() const {
Shinya Kitaoka 120a6e
  return &infoTOutputFx;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TOutputFx::doCompute(TTile &tile, double frame, const TRenderSettings &) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TOutputFx::doGetBBox(double frame, TRectD &bBox,
Shinya Kitaoka 120a6e
                          const TRenderSettings &info) {
Shinya Kitaoka 120a6e
  return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::string TOutputFx::getPluginId() const { return "Toonz_"; }