Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// Toonz includes
Toshihiro Shimizu 890ddd
#include "tvectorimage.h"
Toshihiro Shimizu 890ddd
#include "trasterimage.h"
Toshihiro Shimizu 890ddd
#include "tlevel_io.h"
Toshihiro Shimizu 890ddd
#include "tofflinegl.h"
Toshihiro Shimizu 890ddd
#include "tropcm.h"
Toshihiro Shimizu 890ddd
#include "tvectorrenderdata.h"
Toshihiro Shimizu 890ddd
#include "tsystem.h"
shun-iwasawa c96e49
#include "tvectorgl.h"
justburner 981d46
#include "tcolorstyles.h"
justburner 981d46
justburner 981d46
// TnzCore includes
justburner 981d46
#include "tfiletype.h"
justburner 981d46
#include "tvectorbrushstyle.h"
justburner 981d46
justburner 981d46
// TnzLib includes
justburner 981d46
#include "toonz/imagestyles.h"
justburner 981d46
#include "toonz/toonzfolders.h"
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// Qt includes
Toshihiro Shimizu 890ddd
#include <qdir></qdir>
Toshihiro Shimizu 890ddd
#include <qimage></qimage>
shun-iwasawa c96e49
#include <qoffscreensurface></qoffscreensurface>
shun-iwasawa c96e49
#include <qthread></qthread>
shun-iwasawa c96e49
#include <qguiapplication></qguiapplication>
shun-iwasawa c96e49
#include <qopenglcontext></qopenglcontext>
shun-iwasawa c96e49
#include <qopenglframebufferobject></qopenglframebufferobject>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "toonz/stylemanager.h"
Toshihiro Shimizu 890ddd
justburner 981d46
#include <qvector></qvector>
justburner 981d46
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
//    Local namespace stuff
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void convertRaster32ToImage(TRaster32P ras, QImage *image) {
Shinya Kitaoka 120a6e
  int lx = ras->getLx();
Shinya Kitaoka 120a6e
  int ly = ras->getLy();
Shinya Kitaoka 120a6e
  int i, j;
Shinya Kitaoka 120a6e
  ras->lock();
Shinya Kitaoka 120a6e
  for (i = 0; i < lx; i++)
Shinya Kitaoka 120a6e
    for (j = 0; j < ly; j++) {
Shinya Kitaoka 120a6e
      TPixel32 pix = ras->pixels(ly - 1 - j)[i];
Shinya Kitaoka 120a6e
      QRgb value;
Shinya Kitaoka 120a6e
      value = qRgba(pix.r, pix.g, pix.b, pix.m);
Shinya Kitaoka 120a6e
      image->setPixel(i, j, value);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  ras->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
justburner 981d46
//-----------------------------------------------------------------------------
justburner 981d46
justburner 981d46
QImage rasterToQImage(const TRasterP &ras, bool premultiplied = true,
justburner 981d46
                      bool mirrored = true) {
justburner 981d46
  if (TRaster32P ras32 = ras) {
justburner 981d46
    QImage image(ras->getRawData(), ras->getLx(), ras->getLy(),
justburner 981d46
                 premultiplied ? QImage::Format_ARGB32_Premultiplied
justburner 981d46
                               : QImage::Format_ARGB32);
justburner 981d46
    if (mirrored) return image.mirrored();
justburner 981d46
    return image;
justburner 981d46
  } else if (TRasterGR8P ras8 = ras) {
justburner 981d46
    QImage image(ras->getRawData(), ras->getLx(), ras->getLy(), ras->getWrap(),
justburner 981d46
                 QImage::Format_Indexed8);
justburner 981d46
    static QVector<qrgb> colorTable;</qrgb>
justburner 981d46
    if (colorTable.size() == 0) {
justburner 981d46
      int i;
justburner 981d46
      for (i = 0; i < 256; i++) colorTable.append(QColor(i, i, i).rgb());
justburner 981d46
    }
justburner 981d46
    image.setColorTable(colorTable);
justburner 981d46
    if (mirrored) return image.mirrored();
justburner 981d46
    return image;
justburner 981d46
  }
justburner 981d46
  return QImage();
justburner 981d46
}
justburner 981d46
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//********************************************************************************
justburner 981d46
//    FavoritesManager implementation
justburner 981d46
//********************************************************************************
justburner 981d46
justburner 981d46
FavoritesManager::FavoritesManager() {
justburner 981d46
  m_fpPinsToTop = ToonzFolder::getMyModuleDir() + "pintotopbrushes.txt";
justburner 981d46
  m_xxPinsToTop = false;
justburner 981d46
  loadPinsToTop();
justburner 981d46
}
justburner 981d46
justburner 981d46
//-----------------------------------------------------------------------------
justburner 981d46
justburner 981d46
FavoritesManager *FavoritesManager::instance() {
justburner 981d46
  static FavoritesManager _instance;
justburner 981d46
  return &_instance;
justburner 981d46
}
justburner 981d46
justburner 981d46
//-----------------------------------------------------------------------------
justburner 981d46
justburner 981d46
bool FavoritesManager::loadPinsToTop() {
justburner 981d46
  if (!TFileStatus(m_fpPinsToTop).doesExist()) return false;
justburner 981d46
justburner 981d46
  TIStream is(m_fpPinsToTop);
justburner 981d46
  if (!is) throw TException("Can't read XML");
justburner 981d46
  std::string tagName;
justburner 981d46
justburner 981d46
  if (!is.matchTag(tagName) || tagName != "PinsToTop") return false;
justburner 981d46
justburner 981d46
  m_pinsToTop.clear();
justburner 981d46
  while (!is.matchEndTag()) {
justburner 981d46
    if (!is.matchTag(tagName)) throw TException("Expected tag");
justburner 981d46
    if (tagName == "BrushIdName") {
justburner 981d46
      std::string brushname;
justburner 981d46
      is >> brushname;
justburner 981d46
      m_pinsToTop.push_back(brushname);
justburner 981d46
      if (!is.matchEndTag()) throw TException("Expected end tag");
justburner 981d46
    }
justburner 981d46
  }
justburner 981d46
  m_xxPinsToTop = false;
justburner 981d46
justburner 981d46
  return true;
justburner 981d46
}
justburner 981d46
justburner 981d46
//-----------------------------------------------------------------------------
justburner 981d46
justburner 981d46
void FavoritesManager::savePinsToTop() {
justburner 981d46
  if (!m_xxPinsToTop) return;
justburner 981d46
justburner 981d46
  TOStream os(m_fpPinsToTop);
justburner 981d46
  if (!os) throw TException("Can't write XML");
justburner 981d46
justburner 981d46
  os.openChild("PinsToTop");
justburner 981d46
  for (auto &idname : m_pinsToTop) {
justburner 981d46
    os.openChild("BrushIdName", {});
justburner 981d46
    os << idname;
justburner 981d46
    os.closeChild();
justburner 981d46
  }
justburner 981d46
  os.closeChild();
justburner 981d46
}
justburner 981d46
justburner 981d46
//-----------------------------------------------------------------------------
justburner 981d46
justburner 981d46
bool FavoritesManager::getPinToTop(std::string idname) const {
justburner 981d46
  return m_pinsToTop.contains(idname);
justburner 981d46
}
justburner 981d46
justburner 981d46
//-----------------------------------------------------------------------------
justburner 981d46
justburner 981d46
void FavoritesManager::setPinToTop(std::string idname, bool state) {
justburner 981d46
  int index = m_pinsToTop.indexOf(idname);
justburner 981d46
  if (state && index == -1) {
justburner 981d46
    m_xxPinsToTop = true;
justburner 981d46
    m_pinsToTop.append(idname);
justburner 981d46
  } else if (!state && index != -1) {
justburner 981d46
    m_xxPinsToTop = true;
justburner 981d46
    m_pinsToTop.removeAll(idname);
justburner 981d46
  }
justburner 981d46
}
justburner 981d46
justburner 981d46
//-----------------------------------------------------------------------------
justburner 981d46
justburner 981d46
void FavoritesManager::togglePinToTop(std::string idname) {
justburner 981d46
  int index = m_pinsToTop.indexOf(idname);
justburner 981d46
  if (index != -1)
justburner 981d46
    m_pinsToTop.removeAt(index);
justburner 981d46
  else
justburner 981d46
    m_pinsToTop.append(idname);
justburner 981d46
  m_xxPinsToTop = true;
justburner 981d46
}
justburner 981d46
justburner 981d46
//********************************************************************************
justburner 981d46
//    BaseStyleManager implementation
justburner 981d46
//********************************************************************************
justburner 981d46
justburner 981d46
TFilePath BaseStyleManager::s_rootPath;
justburner 981d46
BaseStyleManager::ChipData BaseStyleManager::s_emptyChipData;
justburner 981d46
justburner 981d46
BaseStyleManager::BaseStyleManager(const TFilePath &stylesFolder,
justburner 981d46
                                   QString filters, QSize chipSize)
justburner 981d46
    : m_stylesFolder(stylesFolder)
justburner 981d46
    , m_filters(filters)
justburner 981d46
    , m_chipSize(chipSize)
justburner 981d46
    , m_loaded(false)
justburner 981d46
    , m_isIndexed(false) {}
justburner 981d46
justburner 981d46
//-----------------------------------------------------------------------------
justburner 981d46
justburner 981d46
const BaseStyleManager::ChipData &BaseStyleManager::getData(int index) const {
justburner 981d46
  if (m_isIndexed) {
justburner 981d46
    return (index < 0 || index >= m_indexes.count())
justburner 981d46
               ? s_emptyChipData
justburner 981d46
               : m_chips[m_indexes[index]];
justburner 981d46
  } else {
justburner 981d46
    return (index < 0 || index >= m_chips.count()) ? s_emptyChipData
justburner 981d46
                                                   : m_chips[index];
justburner 981d46
  }
justburner 981d46
}
justburner 981d46
justburner 981d46
//-----------------------------------------------------------------------------
justburner 981d46
justburner 981d46
void BaseStyleManager::applyFilter() {
justburner 981d46
  FavoritesManager *favMan = FavoritesManager::instance();
justburner 981d46
  QList<int> indexes;</int>
justburner 981d46
justburner 981d46
  m_indexes.clear();
justburner 981d46
  int len = m_chips.count();
justburner 981d46
  for (int i = 0; i < len; i++) {
justburner 981d46
    auto &chip = m_chips[i];
justburner 981d46
    if (chip.desc.indexOf(m_searchText, 0, Qt::CaseInsensitive) >= 0) {
justburner 981d46
      if (favMan->getPinToTop(chip.idname)) {
justburner 981d46
        chip.markPinToTop = true;
justburner 981d46
        m_indexes.append(i);
justburner 981d46
      } else {
justburner 981d46
        chip.markPinToTop = false;
justburner 981d46
        indexes.append(i);
justburner 981d46
      }
justburner 981d46
    }
justburner 981d46
  }
justburner 981d46
justburner 981d46
  bool hasPinsToTop = m_indexes.count() > 0;
justburner 981d46
  m_indexes.append(indexes);
justburner 981d46
  m_isIndexed = (m_indexes.count() != len) || hasPinsToTop;
justburner 981d46
}
justburner 981d46
justburner 981d46
//-----------------------------------------------------------------------------
justburner 981d46
justburner 981d46
TFilePath BaseStyleManager::getRootPath() { return s_rootPath; }
justburner 981d46
justburner 981d46
//-----------------------------------------------------------------------------
justburner 981d46
justburner 981d46
void BaseStyleManager::setRootPath(const TFilePath &rootPath) {
justburner 981d46
  s_rootPath = rootPath;
justburner 981d46
}
justburner 981d46
justburner 981d46
//********************************************************************************
Toshihiro Shimizu 890ddd
//    StyleLoaderTask definition
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class CustomStyleManager::StyleLoaderTask final : public TThread::Runnable {
Shinya Kitaoka 120a6e
  CustomStyleManager *m_manager;
Shinya Kitaoka 120a6e
  TFilePath m_fp;
justburner 981d46
  ChipData m_data;
shun-iwasawa c96e49
  std::shared_ptr<qoffscreensurface> m_offScreenSurface;</qoffscreensurface>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  StyleLoaderTask(CustomStyleManager *manager, const TFilePath &fp);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  void run() override;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  void onFinished(TThread::RunnableP sender) override;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
CustomStyleManager::StyleLoaderTask::StyleLoaderTask(
Shinya Kitaoka 120a6e
    CustomStyleManager *manager, const TFilePath &fp)
Shinya Kitaoka 120a6e
    : m_manager(manager), m_fp(fp) {
Shinya Kitaoka 120a6e
  connect(this, SIGNAL(finished(TThread::RunnableP)), this,
Shinya Kitaoka 120a6e
          SLOT(onFinished(TThread::RunnableP)));
shun-iwasawa c96e49
shun-iwasawa c96e49
  if (QThread::currentThread() == qGuiApp->thread()) {
shun-iwasawa c96e49
    m_offScreenSurface.reset(new QOffscreenSurface());
shun-iwasawa c96e49
    m_offScreenSurface->setFormat(QSurfaceFormat::defaultFormat());
shun-iwasawa c96e49
    m_offScreenSurface->create();
shun-iwasawa c96e49
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void CustomStyleManager::StyleLoaderTask::run() {
justburner 981d46
  m_data = m_manager->createPattern(m_fp, m_offScreenSurface);
justburner 981d46
}
justburner 981d46
justburner 981d46
//-----------------------------------------------------------------------------
justburner 981d46
justburner 981d46
void CustomStyleManager::StyleLoaderTask::onFinished(
justburner 981d46
    TThread::RunnableP sender) {
justburner 981d46
  // On the main thread...
justburner 981d46
  if (!m_data.image.isNull())  // Everything went ok
justburner 981d46
  {
justburner 981d46
    m_manager->m_chips.append(m_data);
justburner 981d46
    emit m_manager->patternAdded();
justburner 981d46
  }
justburner 981d46
}
justburner 981d46
justburner 981d46
//********************************************************************************
justburner 981d46
//    CustomStyleManager implementation
justburner 981d46
//********************************************************************************
justburner 981d46
justburner 981d46
CustomStyleManager::CustomStyleManager(std::string rasterIdName,
justburner 981d46
                                       std::string vectorIdName,
justburner 981d46
                                       const TFilePath &stylesFolder,
justburner 981d46
                                       QString filters, QSize chipSize)
justburner 981d46
    : BaseStyleManager(stylesFolder, filters, chipSize)
justburner 981d46
    , m_started(false)
justburner 981d46
    , m_rasterIdName(rasterIdName)
justburner 981d46
    , m_vectorIdName(vectorIdName) {
justburner 981d46
  m_executor.setMaxActiveTasks(1);
justburner 981d46
}
justburner 981d46
justburner 981d46
//-----------------------------------------------------------------------------
justburner 981d46
justburner 981d46
void CustomStyleManager::loadItems() {
justburner 981d46
  // Build the folder to be read
justburner 981d46
  const TFilePath &rootFP(getRootPath());
justburner 981d46
justburner 981d46
  assert(rootFP != TFilePath());
justburner 981d46
  if (rootFP == TFilePath()) return;
justburner 981d46
justburner 981d46
  QDir patternDir(
justburner 981d46
      QString::fromStdWString((rootFP + m_stylesFolder).getWideString()));
justburner 981d46
  patternDir.setNameFilters(m_filters.split(' '));
justburner 981d46
justburner 981d46
  // Read the said folder
justburner 981d46
  TFilePathSet fps;
justburner 981d46
  try {
justburner 981d46
    TSystem::readDirectory(fps, patternDir);
justburner 981d46
  } catch (...) {
justburner 981d46
    return;
justburner 981d46
  }
justburner 981d46
justburner 981d46
  // Delete patterns no longer in the folder
justburner 981d46
  TFilePathSet newFps;
justburner 981d46
  TFilePathSet::iterator it;
justburner 981d46
  int i;
justburner 981d46
  for (i = 0; i < m_chips.size(); i++) {
justburner 981d46
    ChipData data = m_chips.at(i);
justburner 981d46
    for (it = fps.begin(); it != fps.end(); ++it) {
justburner 981d46
      int isVector = (it->getType() == "pli") ? 1 : 0;
justburner 981d46
      QString name = QString::fromStdWString(it->getWideName());
justburner 981d46
      if (data.name == name && data.isVector == isVector) break;
justburner 981d46
    }
justburner 981d46
justburner 981d46
    if (it == fps.end()) {
justburner 981d46
      m_chips.removeAt(i);
justburner 981d46
      i--;
justburner 981d46
    } else
justburner 981d46
      fps.erase(it);  // The style is not new, so don't generate tasks for it
justburner 981d46
  }
justburner 981d46
justburner 981d46
  // For each (now new) file entry, generate a fetching task
justburner 981d46
  for (TFilePathSet::iterator it = fps.begin(); it != fps.end(); it++)
justburner 981d46
    m_executor.addTask(new StyleLoaderTask(this, *it));
justburner 981d46
}
justburner 981d46
justburner 981d46
QImage CustomStyleManager::makeIcon(
justburner 981d46
    const TFilePath &path, const QSize &qChipSize,
justburner 981d46
    std::shared_ptr<qoffscreensurface> offsurf) {</qoffscreensurface>
Shinya Kitaoka 120a6e
  try {
Shinya Kitaoka 120a6e
    // Fetch the level
justburner 981d46
    TLevelReaderP lr(path);
Shinya Kitaoka 120a6e
    TLevelP level = lr->loadInfo();
justburner 981d46
    if (!level || level->getFrameCount() == 0) return QImage();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Fetch the image of the first frame in the level
Shinya Kitaoka 120a6e
    TLevel::Iterator frameIt = level->begin();
justburner 981d46
    if (frameIt == level->end()) return QImage();
Shinya Kitaoka 120a6e
    TImageP img = lr->getFrameReader(frameIt->first)->load();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Process the image
Shinya Kitaoka 120a6e
    TDimension chipSize(qChipSize.width(), qChipSize.height());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TVectorImageP vimg = img;
Shinya Kitaoka 120a6e
    TRasterImageP rimg = img;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TRaster32P ras;
shun-iwasawa c96e49
justburner 981d46
    QImage image;
shun-iwasawa c96e49
Shinya Kitaoka 120a6e
    if (vimg) {
Shinya Kitaoka 120a6e
      assert(level->getPalette());
Shinya Kitaoka 120a6e
      TPalette *vPalette = level->getPalette();
Shinya Kitaoka 120a6e
      assert(vPalette);
Shinya Kitaoka 120a6e
      vimg->setPalette(vPalette);
Shinya Kitaoka 120a6e
manongjohn 829232
#ifdef LINUX
shun-iwasawa 84ffc5
      TOfflineGL *glContext = 0;
shun-iwasawa 84ffc5
      glContext             = TOfflineGL::getStock(chipSize);
shun-iwasawa 84ffc5
      glContext->clear(TPixel32::White);
manongjohn 829232
#else
shun-iwasawa c96e49
      QOpenGLContext *glContext = new QOpenGLContext();
shun-iwasawa c96e49
      if (QOpenGLContext::currentContext())
shun-iwasawa c96e49
        glContext->setShareContext(QOpenGLContext::currentContext());
shun-iwasawa c96e49
      glContext->setFormat(QSurfaceFormat::defaultFormat());
shun-iwasawa c96e49
      glContext->create();
justburner 981d46
      glContext->makeCurrent(offsurf.get());
shun-iwasawa c96e49
      // attaching stencil buffer here as some styles use it
shun-iwasawa c96e49
      QOpenGLFramebufferObject fb(
shun-iwasawa c96e49
          chipSize.lx, chipSize.ly,
shun-iwasawa c96e49
          QOpenGLFramebufferObject::CombinedDepthStencil);
shun-iwasawa c96e49
shun-iwasawa c96e49
      fb.bind();
shun-iwasawa c96e49
      // Draw
shun-iwasawa c96e49
      glViewport(0, 0, chipSize.lx, chipSize.ly);
shun-iwasawa c96e49
      glClearColor(1.0, 1.0, 1.0, 1.0);  // clear with white color
shun-iwasawa c96e49
      glClear(GL_COLOR_BUFFER_BIT);
shun-iwasawa c96e49
shun-iwasawa c96e49
      glMatrixMode(GL_PROJECTION);
shun-iwasawa c96e49
      glLoadIdentity();
shun-iwasawa c96e49
      gluOrtho2D(0, chipSize.lx, 0, chipSize.ly);
shun-iwasawa c96e49
shun-iwasawa c96e49
      glMatrixMode(GL_MODELVIEW);
shun-iwasawa c96e49
      glLoadIdentity();
manongjohn 829232
#endif
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TRectD bbox = img->getBBox();
Shinya Kitaoka 120a6e
      double scx  = 0.8 * chipSize.lx / bbox.getLx();
Shinya Kitaoka 120a6e
      double scy  = 0.8 * chipSize.ly / bbox.getLy();
Shinya Kitaoka 120a6e
      double sc   = std::min(scx, scy);
Shinya Kitaoka 120a6e
      double dx   = 0.5 * chipSize.lx;
Shinya Kitaoka 120a6e
      double dy   = 0.5 * chipSize.ly;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TAffine aff =
Shinya Kitaoka 120a6e
          TTranslation(dx, dy) * TScale(sc) *
Shinya Kitaoka 120a6e
          TTranslation(-0.5 * (bbox.x0 + bbox.x1), -0.5 * (bbox.y0 + bbox.y1));
Shinya Kitaoka 120a6e
      TVectorRenderData rd(aff, chipSize, vPalette, 0, true);
Shinya Kitaoka 120a6e
manongjohn 829232
#ifdef LINUX
shun-iwasawa 84ffc5
      glContext->draw(img, rd);
shun-iwasawa 84ffc5
      // No need to clone! The received raster already is a copy of the
shun-iwasawa 84ffc5
      // context's buffer
shun-iwasawa 84ffc5
      ras = glContext->getRaster();  //->clone();
manongjohn 829232
#else
shun-iwasawa c96e49
      tglDraw(rd, vimg.getPointer());
shun-iwasawa c96e49
justburner 981d46
      image = QImage(fb.toImage().scaled(QSize(chipSize.lx, chipSize.ly),
justburner 981d46
                                         Qt::IgnoreAspectRatio,
justburner 981d46
                                         Qt::SmoothTransformation));
shun-iwasawa c96e49
      fb.release();
shun-iwasawa c96e49
      glContext->deleteLater();
manongjohn 829232
#endif
Shinya Kitaoka 120a6e
    } else if (rimg) {
Shinya Kitaoka 120a6e
      TDimension size = rimg->getRaster()->getSize();
Shinya Kitaoka 120a6e
      if (size == chipSize)
Shinya Kitaoka 120a6e
        ras = rimg->getRaster()->clone();  // Yep, this may be necessary
Shinya Kitaoka 120a6e
      else {
Shinya Kitaoka 120a6e
        TRaster32P rout(chipSize);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        TRop::resample(rout, rimg->getRaster(),
Shinya Kitaoka 120a6e
                       TScale((double)chipSize.lx / size.lx,
Shinya Kitaoka 120a6e
                              (double)chipSize.ly / size.ly));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        TRop::addBackground(rout, TPixel::White);
Shinya Kitaoka 120a6e
        ras = rout;
Shinya Kitaoka 120a6e
      }
manongjohn 829232
#ifndef LINUX
justburner 981d46
      // image = QImage(chipSize.lx, chipSize.ly, QImage::Format_RGB32);
justburner 981d46
      // convertRaster32ToImage(ras, &image);
justburner 981d46
      image = rasterToQImage(ras);
manongjohn 829232
#endif
Shinya Kitaoka 120a6e
    } else
Shinya Kitaoka 120a6e
      assert(!"unsupported type for custom styles!");
Shinya Kitaoka 120a6e
manongjohn 829232
#ifdef LINUX
justburner 981d46
    // image = QImage(chipSize.lx, chipSize.ly, QImage::Format_RGB32);
justburner 981d46
    // convertRaster32ToImage(ras, &image);
justburner 981d46
    image = rasterToQImage(ras);
manongjohn 829232
#endif
manongjohn 829232
justburner 981d46
    return image;
Shinya Kitaoka 120a6e
  } catch (...) {
Shinya Kitaoka 120a6e
  }
justburner 981d46
justburner 981d46
  return QImage();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
justburner 981d46
CustomStyleManager::ChipData CustomStyleManager::createPattern(
justburner 981d46
    const TFilePath &path, std::shared_ptr<qoffscreensurface> offsurf) {</qoffscreensurface>
justburner 981d46
  ChipData data;
Toshihiro Shimizu 890ddd
justburner 981d46
  bool isVector = (path.getType() == "pli" || path.getType() == "svg");
justburner 981d46
justburner 981d46
  // Generate preview
justburner 981d46
  try {
justburner 981d46
    data.image = makeIcon(path, getChipSize(), offsurf);
justburner 981d46
  } catch (...) {
Shinya Kitaoka 120a6e
  }
justburner 981d46
justburner 981d46
  if (!data.image.isNull()) {
justburner 981d46
    data.name     = QString::fromStdWString(path.getWideName());
justburner 981d46
    data.desc     = data.name;
justburner 981d46
    data.isVector = isVector;
justburner 981d46
    if (isVector)
justburner 981d46
      data.idname = m_vectorIdName + data.name.toStdString();
justburner 981d46
    else
justburner 981d46
      data.idname = m_rasterIdName + data.name.toStdString();
justburner 981d46
    data.hash = TColorStyle::generateHash(data.idname);
justburner 981d46
  }
justburner 981d46
  return data;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//********************************************************************************
justburner 981d46
//    TextureStyleManager implementation
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
justburner 981d46
TextureStyleManager::TextureStyleManager(const TFilePath &stylesFolder,
justburner 981d46
                                         QSize chipSize)
justburner 981d46
    : BaseStyleManager(stylesFolder, QString(), chipSize) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
justburner 981d46
void TextureStyleManager::loadTexture(const TFilePath &fp) {
justburner 981d46
  if (fp == TFilePath()) {
justburner 981d46
    TRaster32P ras(25, 25);
justburner 981d46
    TTextureStyle::fillCustomTextureIcon(ras);
justburner 981d46
    // ras->fill(TPixel::Blue);
justburner 981d46
    ChipData customText(
justburner 981d46
        QString(""), QObject::tr("Custom Texture", "TextureStyleChooserPage"),
justburner 981d46
        rasterToQImage(ras), 4, false, ras,
justburner 981d46
        TTextureStyle::staticBrushIdName(L""));
justburner 981d46
    customText.hash = TTextureStyle::generateHash(customText.idname);
justburner 981d46
    m_chips.append(customText);
justburner 981d46
    return;
justburner 981d46
  }
Toshihiro Shimizu 890ddd
justburner 981d46
  TRasterP ras;
justburner 981d46
  TImageReader::load(fp, ras);
justburner 981d46
  if (!ras || ras->getLx() < 2 || ras->getLy() < 2) return;
justburner 981d46
justburner 981d46
  TRaster32P ras32 = ras;
justburner 981d46
  if (!ras32) return;
justburner 981d46
justburner 981d46
  TDimension d(2, 2);
justburner 981d46
  while (d.lx < 256 && d.lx * 2 <= ras32->getLx()) d.lx *= 2;
justburner 981d46
  while (d.ly < 256 && d.ly * 2 <= ras32->getLy()) d.ly *= 2;
justburner 981d46
justburner 981d46
  TRaster32P texture;
justburner 981d46
  if (d == ras32->getSize())
justburner 981d46
    texture = ras32;
justburner 981d46
  else {
justburner 981d46
    texture = TRaster32P(d);
justburner 981d46
    TScale sc((double)texture->getLx() / ras32->getLx(),
justburner 981d46
              (double)texture->getLy() / ras32->getLy());
justburner 981d46
    TRop::resample(texture, ras32, sc);
justburner 981d46
  }
Toshihiro Shimizu 890ddd
justburner 981d46
  QString name = QString::fromStdWString(fp.getLevelNameW());
justburner 981d46
  ChipData text(name, name, rasterToQImage(ras), 4, false, texture,
justburner 981d46
                TTextureStyle::staticBrushIdName(fp.getLevelNameW()));
justburner 981d46
  text.hash = TTextureStyle::generateHash(text.idname);
justburner 981d46
justburner 981d46
  m_chips.append(text);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
justburner 981d46
void TextureStyleManager::loadItems() {
justburner 981d46
  m_chips.clear();
justburner 981d46
  if (getRootPath() == TFilePath()) return;
Toshihiro Shimizu 890ddd
justburner 981d46
  TFilePath texturePath = getRootPath() + "textures";
justburner 981d46
  TFilePathSet fps;
justburner 981d46
  try {
justburner 981d46
    fps = TSystem::readDirectory(texturePath);
justburner 981d46
  } catch (...) {
justburner 981d46
    return;
justburner 981d46
  }
justburner 981d46
  if (fps.empty()) return;
justburner 981d46
  int count = 0;
justburner 981d46
  for (TFilePathSet::iterator it = fps.begin(); it != fps.end(); it++)
justburner 981d46
    if (TFileType::getInfo(*it) == TFileType::RASTER_IMAGE) {
justburner 981d46
      try {
justburner 981d46
        loadTexture(*it);
justburner 981d46
        ++count;
justburner 981d46
      } catch (...) {
justburner 981d46
      }
justburner 981d46
    }
justburner 981d46
  loadTexture(TFilePath());  // custom texture
Toshihiro Shimizu 890ddd
justburner 981d46
  m_loaded = true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
justburner 981d46
//********************************************************************************
justburner 981d46
//    MyPaintBrushStyleManager  implementation
justburner 981d46
//********************************************************************************
Toshihiro Shimizu 890ddd
justburner 981d46
MyPaintBrushStyleManager::MyPaintBrushStyleManager(QSize chipSize)
justburner 981d46
    : BaseStyleManager(TFilePath(), QString(), chipSize) {}
Shinya Kitaoka 120a6e
justburner 981d46
//-----------------------------------------------------------------------------
Shinya Kitaoka 120a6e
justburner 981d46
void MyPaintBrushStyleManager::loadItems() {
justburner 981d46
  m_brushes.clear();
justburner 981d46
  m_chips.clear();
justburner 981d46
  std::set<tfilepath> brushFiles;</tfilepath>
justburner 981d46
justburner 981d46
  TFilePathSet dirs = TMyPaintBrushStyle::getBrushesDirs();
justburner 981d46
  for (TFilePathSet::iterator i = dirs.begin(); i != dirs.end(); ++i) {
justburner 981d46
    TFileStatus fs(*i);
justburner 981d46
    if (fs.doesExist() && fs.isDirectory()) {
justburner 981d46
      TFilePathSet files = TSystem::readDirectoryTree(*i, false, true);
justburner 981d46
      for (TFilePathSet::iterator j = files.begin(); j != files.end(); ++j)
justburner 981d46
        if (j->getType() == TMyPaintBrushStyle::getBrushType())
justburner 981d46
          brushFiles.insert(*j - *i);
justburner 981d46
    }
justburner 981d46
  }
Shinya Kitaoka 120a6e
justburner 981d46
  // reserve memory to avoid reallocation
justburner 981d46
  m_brushes.reserve(brushFiles.size());
justburner 981d46
  for (std::set<tfilepath>::iterator i = brushFiles.begin();</tfilepath>
justburner 981d46
       i != brushFiles.end(); ++i) {
justburner 981d46
    TMyPaintBrushStyle style = TMyPaintBrushStyle(*i);
justburner 981d46
    m_brushes.push_back(style);
justburner 981d46
justburner 981d46
    // Generate a QImage preview to draw the chip faster at cost of few memory
justburner 981d46
    QImage previewQImage = rasterToQImage(style.getPreview());
justburner 981d46
    QString stylePath    = style.getPath().getQString();
justburner 981d46
    m_chips.append(ChipData(stylePath, stylePath, previewQImage, 4001, false,
justburner 981d46
                            TRasterP(), style.getBrushIdName(),
justburner 981d46
                            style.getBrushIdHash()));
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
justburner 981d46
  m_loaded = true;
justburner 981d46
}
Shinya Kitaoka 120a6e
justburner 981d46
//********************************************************************************
justburner 981d46
//    SpecialStyleManager  implementation
justburner 981d46
//********************************************************************************
justburner 981d46
justburner 981d46
SpecialStyleManager::SpecialStyleManager(QSize chipSize)
justburner 981d46
    : BaseStyleManager(TFilePath(), QString(), chipSize) {}
justburner 981d46
justburner 981d46
//-----------------------------------------------------------------------------
justburner 981d46
justburner 981d46
void SpecialStyleManager::loadItems() {
justburner 981d46
  m_chips.clear();
justburner 981d46
justburner 981d46
  std::vector<int> tags;</int>
justburner 981d46
  TColorStyle::getAllTags(tags);
justburner 981d46
justburner 981d46
  int chipCount = 0;
justburner 981d46
justburner 981d46
  for (int j = 0; j < (int)tags.size(); j++) {
justburner 981d46
    int tagId = tags[j];
justburner 981d46
    if (tagId == 3 ||     // solid color
justburner 981d46
        tagId == 4 ||     // texture
justburner 981d46
        tagId == 100 ||   // obsolete imagepattern id
justburner 981d46
        tagId == 2000 ||  // imagepattern
justburner 981d46
        tagId == 2800 ||  // imagepattern
justburner 981d46
        tagId == 2001 ||  // cleanup
justburner 981d46
        tagId == 2002 ||  // black cleanup
justburner 981d46
        tagId == 3000 ||  // vector brush
justburner 981d46
        tagId == 4001     // mypaint brush
justburner 981d46
    )
justburner 981d46
      continue;
justburner 981d46
justburner 981d46
    TColorStyle *style = TColorStyle::create(tagId);
justburner 981d46
    if (style->isRasterStyle()) {
justburner 981d46
      delete style;
justburner 981d46
      continue;
justburner 981d46
    }
justburner 981d46
    TDimension chipSize(getChipSize().width(), getChipSize().height());
justburner 981d46
    // QImage *image = new QImage(chipSize.lx, chipSize.ly,
justburner 981d46
    // QImage::Format_RGB32); convertRaster32ToImage(style->getIcon(chipSize),
justburner 981d46
    // image);
justburner 981d46
    TRaster32P raster = style->getIcon(chipSize);
justburner 981d46
    ChipData chip(style->getDescription(), style->getDescription(),
justburner 981d46
                  rasterToQImage(raster), tagId, true, raster,
justburner 981d46
                  style->getBrushIdName(), style->getBrushIdHash());
justburner 981d46
    m_chips.append(chip);
justburner 981d46
    delete style;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
justburner 981d46
  m_loaded = true;
Toshihiro Shimizu 890ddd
}