#include "tiio_pli.h" //#include "tstrokeoutline.h" #include "tsystem.h" #include "pli_io.h" //#include "tstrokeutil.h" #include "tregion.h" #include "tsimplecolorstyles.h" #include "tpalette.h" //#include "tspecialstyleid.h" #include "tiio.h" #include "tconvert.h" #include "tcontenthistory.h" #include "tstroke.h" typedef TVectorImage::IntersectionBranch IntersectionBranch; //============================================================================= const TSolidColorStyle ConstStyle(TPixel32::Black); static TSolidColorStyle *CurrStyle = NULL; namespace { //--------------------------------------------------------------------------- class PliOuputStream final : public TOutputStreamInterface { std::vector *m_stream; public: PliOuputStream(std::vector *stream) : m_stream(stream) {} TOutputStreamInterface &operator<<(double x) override { m_stream->push_back(TStyleParam(x)); return *this; } TOutputStreamInterface &operator<<(int x) override { m_stream->push_back(TStyleParam(x)); return *this; } TOutputStreamInterface &operator<<(std::string x) override { m_stream->push_back(TStyleParam(x)); return *this; } TOutputStreamInterface &operator<<(USHORT x) override { m_stream->push_back(TStyleParam(x)); return *this; } TOutputStreamInterface &operator<<(BYTE x) override { m_stream->push_back(TStyleParam(x)); return *this; } TOutputStreamInterface &operator<<(const TRaster32P &x) override { m_stream->push_back(TStyleParam(x)); return *this; } }; //--------------------------------------------------------------------------- class PliInputStream final : public TInputStreamInterface { std::vector *m_stream; VersionNumber m_version; int m_count; public: PliInputStream(std::vector *stream, int majorVersion, int minorVersion) : m_stream(stream), m_version(majorVersion, minorVersion), m_count(0) {} TInputStreamInterface &operator>>(double &x) override { assert((*m_stream)[m_count].m_type == TStyleParam::SP_DOUBLE); x = (*m_stream)[m_count++].m_numericVal; return *this; } TInputStreamInterface &operator>>(int &x) override { assert((*m_stream)[m_count].m_type == TStyleParam::SP_INT); x = (int)(*m_stream)[m_count++].m_numericVal; return *this; } TInputStreamInterface &operator>>(std::string &x) override { if ((*m_stream)[m_count].m_type == TStyleParam::SP_INT) x = std::to_string(static_cast((*m_stream)[m_count++].m_numericVal)); else { assert((*m_stream)[m_count].m_type == TStyleParam::SP_STRING); x = (*m_stream)[m_count++].m_string; } return *this; } TInputStreamInterface &operator>>(BYTE &x) override { assert((*m_stream)[m_count].m_type == TStyleParam::SP_BYTE); x = (BYTE)(*m_stream)[m_count++].m_numericVal; return *this; } TInputStreamInterface &operator>>(USHORT &x) override { assert((*m_stream)[m_count].m_type == TStyleParam::SP_USHORT); x = (USHORT)(*m_stream)[m_count++].m_numericVal; return *this; } TInputStreamInterface &operator>>(TRaster32P &x) override { assert((*m_stream)[m_count].m_type == TStyleParam::SP_RASTER); x = (*m_stream)[m_count++].m_r; return *this; } VersionNumber versionNumber() const override { return m_version; } }; //--------------------------------------------------------------------------- TPixel32 getColor(const TStroke *stroke) { // const TStrokeStyle* style = stroke->getStyle(); // const TSolidColorStrokeStyle* style = dynamic_cast( ); // if(style) return style->getAverageColor(); return TPixel32::Transparent; } //--------------------------------------------------------------------------- /* Crea la palette dei colori, in funzione di quelli trovati dalla funzione findColor */ UINT findColor(const TPixel32 &color, const std::vector &colorArray) { for (UINT i = 0; i < colorArray.size(); i++) if (colorArray[i] == color) return i; return colorArray.size(); } //--------------------------------------------------------------------------- void buildPalette(ParsedPli *pli, const TImageP img) { if (!pli->m_palette_tags.empty()) return; TVectorImageP tempVecImg = img; TPalette *vPalette = tempVecImg->getPalette(); unsigned int i; // if (pli->m_idWrittenColorsArray.empty()) // { // assert(vPalette); // pli->m_idWrittenColorsArray.resize(vPalette->getStyleCount()); // } // se c'e' una reference image, uso il primo stile della palette per // memorizzare il path TFilePath fp; if ((fp = vPalette->getRefImgPath()) != TFilePath()) { TStyleParam styleParam("refimage" + ::to_string(fp)); StyleTag *refImageTag = new StyleTag(0, 0, 1, &styleParam); pli->m_palette_tags.push_back((PliObjectTag *)refImageTag); } // per scrivere le pages della palette, uso in modo improprio uno stile: il // primo stile // della paletta(o il secondo, se c'e' una refimage) ha tutti parametri // stringa, che coincidono con i nomi delle pages // ilcampo m_id viene usato anche per mettere il frameIndex(per multi palette) assert(vPalette->getPageCount()); std::vector pageNames(vPalette->getPageCount()); for (i = 0; i < pageNames.size(); i++) pageNames[i] = TStyleParam(::to_string(vPalette->getPage(i)->getName())); StyleTag *pageNamesTag = new StyleTag(0, 0, pageNames.size(), pageNames.data()); pli->m_palette_tags.push_back((PliObjectTag *)pageNamesTag); /* for(i=1 ; im_idWrittenColorsArray.size(); i++ ) pli->m_idWrittenColorsArray[i]=false; pli->m_idWrittenColorsArray[0]=true; */ for (i = 1; i < (unsigned)vPalette->getStyleCount(); i++) { TColorStyle *style = vPalette->getStyle(i); TPalette::Page *page = vPalette->getStylePage(i); if (!page) continue; int pageIndex = 65535; // if (page) pageIndex = page->getIndex(); // TColorStyle*style = tempVecImg->getPalette()->getStyle(styleId); std::vector stream; PliOuputStream chan(&stream); style->save(chan); // viene riempito lo stream; assert(pageIndex >= 0 && pageIndex <= 65535); StyleTag *styleTag = new StyleTag(i, pageIndex, stream.size(), stream.data()); pli->m_palette_tags.push_back((PliObjectTag *)styleTag); } if (vPalette->isAnimated()) { std::set keyFrames; for (i = 0; i < (unsigned)vPalette->getStyleCount(); i++) for (int j = 0; j < vPalette->getKeyframeCount(i); j++) keyFrames.insert(vPalette->getKeyframe(i, j)); std::set::const_iterator it = keyFrames.begin(); for (; it != keyFrames.end(); ++it) { int frame = *it; vPalette->setFrame(frame); StyleTag *pageNamesTag = new StyleTag( frame, 0, 0, 0); // lo so, e' orrendo. devo mettere un numero intero pli->m_palette_tags.push_back((PliObjectTag *)pageNamesTag); for (i = 1; i < (unsigned)vPalette->getStyleCount(); i++) { if (vPalette->isKeyframe(i, frame)) { TColorStyle *style = vPalette->getStyle(i); TPalette::Page *page = vPalette->getStylePage(i); if (!page) continue; int pageIndex = 65535; // if (page) pageIndex = page->getIndex(); // TColorStyle*style = tempVecImg->getPalette()->getStyle(styleId); std::vector stream; PliOuputStream chan(&stream); style->save(chan); // viene riempito lo stream; assert(pageIndex >= 0 && pageIndex <= 65535); StyleTag *styleTag = new StyleTag(i, pageIndex, stream.size(), stream.data()); pli->m_palette_tags.push_back((PliObjectTag *)styleTag); } } } } } //--------------------------------------------------------------------------- } // unnamed namespace //----------------------------------------------------------------------------- //=========================================================================== /* Classe locale per la scrittura di un frame del livello. */ class TImageWriterPli final : public TImageWriter { public: TImageWriterPli(const TFilePath &, const TFrameId &frameId, TLevelWriterPli *); ~TImageWriterPli() {} private: UCHAR m_precision; // double m_maxThickness; // not implemented TImageWriterPli(const TImageWriterPli &); TImageWriterPli &operator=(const TImageWriterPli &src); public: void save(const TImageP &) override; TFrameId m_frameId; private: TLevelWriterPli *m_lwp; }; //============= TImageP TImageReaderPli::load() { if (!m_lrp->m_doesExist) throw TImageException(getFilePath(), "Error file doesn't exist"); UINT majorVersionNumber, minorVersionNumber; m_lrp->m_pli->getVersion(majorVersionNumber, minorVersionNumber); assert(majorVersionNumber > 5 || (majorVersionNumber == 5 && minorVersionNumber >= 5)); return doLoad(); } //=========================================================================== static void readRegionVersion4x(IntersectionDataTag *tag, TVectorImage *img) { #ifndef NEW_REGION_FILL img->setFillData(tag->m_branchArray, tag->m_branchCount); #endif } //----------------------------------------------------------------------------- namespace { struct CreateStrokeData { int m_styleId; TStroke::OutlineOptions m_options; CreateStrokeData() : m_styleId(-1) {} }; void createStroke(ThickQuadraticChainTag *quadTag, TVectorImage *outVectImage, const CreateStrokeData &data) { std::vector chunks(quadTag->m_numCurves); for (UINT k = 0; k < quadTag->m_numCurves; k++) chunks[k] = &quadTag->m_curve[k]; TStroke *stroke = TStroke::create(chunks); assert(data.m_styleId != -1); stroke->setStyle(data.m_styleId); stroke->outlineOptions() = data.m_options; if (quadTag->m_isLoop) stroke->setSelfLoop(); // stroke->setSketchMode(groupTag->m_type==GroupTag::SKETCH_STROKE); outVectImage->addStroke(stroke, false); } } // namespace //----------------------------------------------------------------------------- static void createGroup(GroupTag *groupTag, TVectorImage *vi, CreateStrokeData &data) { int count = vi->getStrokeCount(); for (int j = 0; j < groupTag->m_numObjects; j++) { if (groupTag->m_object[j]->m_type == PliTag::COLOR_NGOBJ) data.m_styleId = ((ColorTag *)groupTag->m_object[j])->m_color[0]; else if (groupTag->m_object[j]->m_type == PliTag::OUTLINE_OPTIONS_GOBJ) data.m_options = ((StrokeOutlineOptionsTag *)groupTag->m_object[j])->m_options; else if (groupTag->m_object[j]->m_type == PliTag::GROUP_GOBJ) createGroup((GroupTag *)groupTag->m_object[j], vi, data); else { assert(groupTag->m_object[j]->m_type == PliTag::THICK_QUADRATIC_CHAIN_GOBJ); createStroke((ThickQuadraticChainTag *)groupTag->m_object[j], vi, data); } } vi->group(count, vi->getStrokeCount() - count); } //----------------------------------------------------------------------------- TImageP TImageReaderPli::doLoad() { CreateStrokeData strokeData; // preparo l'immagine da restituire TVectorImage *outVectImage = new TVectorImage(true); // fisso il colore di default a nero opaco // TPixel currentColor=TPixel::Black; // TStrokeStyle *currStyle = NULL; // chiudo tutto dentro un blocco try per cautelarmi // dalle eccezioni generate in lettura // try //{ // un contatore UINT i; outVectImage->setAutocloseTolerance(m_lrp->m_pli->getAutocloseTolerance()); ImageTag *imageTag; imageTag = m_lrp->m_pli->loadFrame(m_frameId); if (!imageTag) throw TImageException(m_path, "Corrupted or invalid image data"); if (m_lrp->m_mapOfImage[m_frameId].second == false) m_lrp->m_mapOfImage[m_frameId].second = true; // per tutti gli oggetti presenti nel tag for (i = 0; i < imageTag->m_numObjects; i++) { switch (imageTag->m_object[i]->m_type) { case PliTag::GROUP_GOBJ: assert(((GroupTag *)imageTag->m_object[i])->m_type == GroupTag::STROKE); createGroup((GroupTag *)imageTag->m_object[i], outVectImage, strokeData); break; case PliTag::INTERSECTION_DATA_GOBJ: readRegionVersion4x((IntersectionDataTag *)imageTag->m_object[i], outVectImage); break; case PliTag::THICK_QUADRATIC_CHAIN_GOBJ: // aggiunge le stroke quadratiche createStroke((ThickQuadraticChainTag *)imageTag->m_object[i], outVectImage, strokeData); break; case PliTag::COLOR_NGOBJ: { // aggiunge curve quadratiche con spessore costante ColorTag *colorTag = (ColorTag *)imageTag->m_object[i]; assert(colorTag->m_numColors == 1); strokeData.m_styleId = colorTag->m_color[0]; // isSketch=(colorTag->m_color[0] < c_maxSketchColorNum); // isSketch=(colorTag->m_color[0] < c_maxSketchColorNum); break; } case PliTag::OUTLINE_OPTIONS_GOBJ: // adds outline options data strokeData.m_options = ((StrokeOutlineOptionsTag *)imageTag->m_object[i])->m_options; break; case PliTag::AUTOCLOSE_TOLERANCE_GOBJ: { // aggiunge curve quadratiche con spessore costante AutoCloseToleranceTag *toleranceTag = (AutoCloseToleranceTag *)imageTag->m_object[i]; assert(toleranceTag->m_autoCloseTolerance >= 0); outVectImage->setAutocloseTolerance( ((double)toleranceTag->m_autoCloseTolerance) / 1000); break; } default: break; } // switch(groupTag->m_object[j]->m_type) } // for (i=0; im_numObjects; i++) //} // try // catch(...) // cosi' e' inutile o raccolgo qualcosa prima di rilanciare o lo // elimino //{ // throw; // } // if (regionsComputed) //WARNING !!! la seedFill mette il flag a ValidRegion a // TRUE // outVectImage->seedFill(); //le vecchie immagini hanno il seed // (version<3.1) #ifdef _DEBUG outVectImage->checkIntersections(); #endif outVectImage->findRegions(); return TImageP(outVectImage); } //----------------------------------------------------------------------------- TDimension TImageReaderPli::getSize() const { return TDimension(-1, -1); } //----------------------------------------------------------------------------- TRect TImageReaderPli::getBBox() const { return TRect(); } //============================================================================= TImageWriterPli::TImageWriterPli(const TFilePath &f, const TFrameId &frameId, TLevelWriterPli *pli) : TImageWriter(f) , m_frameId(frameId) , m_lwp(pli) , m_precision(2) //, m_maxThickness(0) {} //----------------------------------------------------------------------------- static void putStroke(TStroke *stroke, int &currStyleId, std::vector &tags) { double maxThickness = 0; bool nonStdOutline = false; assert(stroke); int chunkCount = stroke->getChunkCount(); std::vector strokeChain(chunkCount); int styleId = stroke->getStyle(); assert(styleId >= 0); if (currStyleId == -1 || styleId != currStyleId) { currStyleId = styleId; std::unique_ptr color(new TUINT32[1]); color[0] = (TUINT32)styleId; std::unique_ptr colorTag(new ColorTag( ColorTag::SOLID, ColorTag::STROKE_COLOR, 1, std::move(color))); tags.push_back(colorTag.release()); } // If the outline options are non-standard (not round), add the outline infos TStroke::OutlineOptions &options = stroke->outlineOptions(); if (options.m_capStyle != TStroke::OutlineOptions::ROUND_CAP || options.m_joinStyle != TStroke::OutlineOptions::ROUND_JOIN || options.m_miterLower != 0.0 || options.m_miterUpper != 4.0) { StrokeOutlineOptionsTag *outlineOptionsTag = new StrokeOutlineOptionsTag(options); tags.push_back((PliObjectTag *)outlineOptionsTag); nonStdOutline = true; } UINT k; for (k = 0; k < (UINT)chunkCount; ++k) { const TThickQuadratic *q = stroke->getChunk(k); maxThickness = std::max({maxThickness, q->getThickP0().thick, q->getThickP1().thick}); strokeChain[k] = *q; } maxThickness = std::max(maxThickness, stroke->getChunk(chunkCount - 1)->getThickP2().thick); ThickQuadraticChainTag *quadChainTag = new ThickQuadraticChainTag(k, &strokeChain[0], maxThickness); quadChainTag->m_isLoop = stroke->isSelfLoop(); // pli->addTag((PliObjectTag *)quadChainTag); tags.push_back((PliObjectTag *)quadChainTag); // pli->addTag(groupTag[count++]); if (nonStdOutline) { // Restore default outline settings TStroke::OutlineOptions resetoptions; StrokeOutlineOptionsTag *outlineOptionsTag = new StrokeOutlineOptionsTag(resetoptions); tags.push_back((PliObjectTag *)outlineOptionsTag); } } //----------------------------------------------------------------------------- GroupTag *makeGroup(TVectorImageP &vi, int &currStyleId, int &index, int currDepth); void TImageWriterPli::save(const TImageP &img) { // Allocate an image TVectorImageP tempVecImg = img; int currStyleId = -1; if (!tempVecImg) throw TImageException(m_path, "No data to save"); // Check that the frame about to insert is not already present // So you do not increase the number of current frames ++m_lwp->m_frameNumber; std::unique_ptr v; UINT intersectionSize = tempVecImg->getFillData(v); // alloco l'oggetto m_lwp->m_pli ( di tipo ParsedPli ) che si occupa di // costruire la struttura if (!m_lwp->m_pli) { m_lwp->m_pli.reset(new ParsedPli(m_lwp->m_frameNumber, m_precision, 40, tempVecImg->getAutocloseTolerance())); m_lwp->m_pli->setCreator(m_lwp->m_creator); } buildPalette(m_lwp->m_pli.get(), img); ParsedPli *pli = m_lwp->m_pli.get(); /* comunico che il numero di frame e' aumentato (il parsed lo riceve nel solo nel costruttore) */ pli->setFrameCount(m_lwp->m_frameNumber); // alloco la struttura che conterra' i tag per la vector image corrente std::vector tags; // tags = new std::vector; // Store the precision scale to be used in saving the quadratics { int precisionScale = sq(128); pli->precisionScale() = precisionScale; PliTag *tag = new PrecisionScaleTag(precisionScale); tags.push_back((PliObjectTag *)tag); } // Store the auto close tolerance double pliTolerance = m_lwp->m_pli->getAutocloseTolerance(); // write the tag if the frame's tolerance has been changed or // if the first frame's tolerance (and therefore the level's tolerance) // has been changed. if (!areAlmostEqual(tempVecImg->getAutocloseTolerance(), 1.15, 0.001) || !areAlmostEqual(pliTolerance, 1.15, 0.001)) { int tolerance = (int)((roundf(tempVecImg->getAutocloseTolerance() * 100) / 100) * 1000); PliTag *tag = new AutoCloseToleranceTag(tolerance); tags.push_back((PliObjectTag *)tag); pli->setVersion(120, 0); } else { pli->setVersion(71, 0); } // recupero il numero di stroke dall'immagine int numStrokes = tempVecImg->getStrokeCount(); int i = 0; while (i < (UINT)numStrokes) { if (tempVecImg->isStrokeGrouped(i)) tags.push_back(makeGroup(tempVecImg, currStyleId, i, 1)); else putStroke(tempVecImg->getStroke(i++), currStyleId, tags); } if (intersectionSize > 0) { PliTag *tag = new IntersectionDataTag(intersectionSize, std::move(v)); tags.push_back((PliObjectTag *)tag); } int tagsSize = tags.size(); std::unique_ptr imageTagPtr(new ImageTag( m_frameId, tagsSize, (tagsSize > 0) ? tags.data() : nullptr)); pli->addTag(imageTagPtr.release()); // il ritorno e' fissato a false in quanto la // scrittura avviene alla distruzione dello scrittore di livelli return; // davedere false; } //============================================================================= TLevelWriterPli::TLevelWriterPli(const TFilePath &path, TPropertyGroup *winfo) : TLevelWriter(path, winfo), m_frameNumber(0) {} //----------------------------------------------------------------------------- TLevelWriterPli::~TLevelWriterPli() { if (!m_pli) { return; } try { // aggiungo il tag della palette CurrStyle = NULL; assert(!m_pli->m_palette_tags.empty()); std::unique_ptr groupTag( new GroupTag(GroupTag::PALETTE, m_pli->m_palette_tags.size(), m_pli->m_palette_tags.data())); m_pli->addTag(groupTag.release(), true); if (m_contentHistory) { QString his = m_contentHistory->serialize(); std::unique_ptr textTag(new TextTag(his.toStdString())); m_pli->addTag(textTag.release(), true); } m_pli->writePli(m_path); } catch (...) { } } //----------------------------------------------------------------------------- TImageWriterP TLevelWriterPli::getFrameWriter(TFrameId fid) { TImageWriterPli *iwm = new TImageWriterPli(m_path, fid, this); return TImageWriterP(iwm); } //============================================================================= TLevelReaderPli::TLevelReaderPli(const TFilePath &path) : TLevelReader(path) , m_palette(0) , m_paletteCount(0) , m_doesExist(false) , m_pli(0) , m_readPalette(true) , m_level() , m_init(false) { if (!(m_doesExist = TFileStatus(path).doesExist())) throw TImageException(getFilePath(), "Error file doesn't exist"); } //----------------------------------------------------------------------------- TLevelReaderPli::~TLevelReaderPli() { delete m_pli; } //----------------------------------------------------------------------------- TImageReaderP TLevelReaderPli::getFrameReader(TFrameId fid) { TImageReaderPli *irm = new TImageReaderPli(m_path, fid, this); return TImageReaderP(irm); } //----------------------------------------------------------------------------- TPalette *readPalette(GroupTag *paletteTag, int majorVersion, int minorVersion) { bool newPli = (majorVersion > 5 || (majorVersion == 5 && minorVersion >= 6)); // wstring pageName(L"colors"); TPalette *palette = new TPalette(); // palette->addStyleToPage(0, pageName); // palette->setStyle(0,TPixel32(255,255,255,0)); // palette->setVersion(isNew?0:-1); // tolgo dalla pagina lo stile #1 palette->getPage(0)->removeStyle(1); int frame = -1; // int m = page->getStyleCount(); bool pagesRead = false; // i primi due styletag della palette sono speciali; // il primo, che potrebbe non esserci, contiene l'eventuale reference image // path; // il secondo, che c'e' sempre contiene i nomi delle pagine. for (unsigned int i = 0; i < paletteTag->m_numObjects; i++) { StyleTag *styleTag = (StyleTag *)paletteTag->m_object[i]; if (i == 0 && styleTag->m_numParams == 1 && strncmp(styleTag->m_param[0].m_string.c_str(), "refimage", 8) == 0) // questo stile contiene l'eventuale refimagepath { palette->setRefImgPath( TFilePath(styleTag->m_param[0].m_string.c_str() + 8)); continue; } assert(styleTag->m_type == PliTag::STYLE_NGOBJ); int id = styleTag->m_id; int pageIndex = styleTag->m_pageIndex; if (!pagesRead && newPli) // quewsto stile contiene le stringhe dei nomi // delle pagine della paletta! { pagesRead = true; assert(id == 0 && pageIndex == 0); assert(palette->getPageCount() == 1); for (int j = 0; j < styleTag->m_numParams; j++) { assert(styleTag->m_param[j].m_type == TStyleParam::SP_STRING); if (j == 0) palette->getPage(0)->setName( ::to_wstring(styleTag->m_param[j].m_string)); else { palette->addPage(::to_wstring(styleTag->m_param[j].m_string)); // palette->getPage(j)->addStyle(TPixel32::Red); } } continue; } if (styleTag->m_numParams == 0) // styletag contiene il frame di una multipalette! { frame = styleTag->m_id; palette->setFrame(frame); continue; } TPalette::Page *page = 0; if (pageIndex < 65535) // questo valore pseciale significa che il colore // non sta in alcuna pagina { page = palette->getPage(pageIndex); assert(page); } else continue; // i pli prima salvavano pure i colori non usati...evito di // caricarli! std::vector params(styleTag->m_numParams); for (int j = 0; j < styleTag->m_numParams; j++) params[j] = styleTag->m_param[j]; PliInputStream chan(¶ms, majorVersion, minorVersion); TColorStyle *style = TColorStyle::load(chan); // leggo params assert(id > 0); if (id < palette->getStyleCount()) { if (frame > -1) { TColorStyle *oldStyle = palette->getStyle(id); oldStyle->copy(*style); palette->setKeyframe(id, frame); } else palette->setStyle(id, style); } else { assert(frame == -1); // uno stile animato, ci deve gia' essere nella paletta! while (palette->getStyleCount() < id) palette->addStyle(TPixel32::Red); if (page) page->addStyle(palette->addStyle(style)); else palette->addStyle(style); } if (id > 0 && page && frame == -1) page->addStyle(id); // m = page->getStyleCount(); } palette->setFrame(0); return palette; } /* Carico le informazioni relative al livello */ void TLevelReaderPli::doReadPalette(bool doReadIt) { m_readPalette = doReadIt; } QString TLevelReaderPli::getCreator() { loadInfo(); if (m_pli) return m_pli->getCreator(); return ""; } TLevelP TLevelReaderPli::loadInfo() { if (m_init) return m_level; m_init = true; // m_level = TLevelP(); // TLevelP level; // chiudo tutto dentro un blocco try per cautelarmi // dalle eccezioni generate in lettura try { // alloco l'oggetto parsed assert(!m_pli); m_pli = new ParsedPli(getFilePath()); UINT majorVersionNumber, minorVersionNumber; m_pli->getVersion(majorVersionNumber, minorVersionNumber); if (majorVersionNumber <= 5 && (majorVersionNumber != 5 || minorVersionNumber < 5)) return m_level; TPalette *palette = 0; m_pli->loadInfo(m_readPalette, palette, m_contentHistory); if (palette) m_level->setPalette(palette); for (int i = 0; i < m_pli->getFrameCount(); i++) m_level->setFrame(m_pli->getFrameNumber(i), TVectorImageP()); } catch (std::exception &e) { TSystem::outputDebug(e.what()); throw TImageException(getFilePath(), "Unknow error on reading file"); } catch (...) { throw; } return m_level; } //----------------------------------------------------------------------------- TImageReaderPli::TImageReaderPli(const TFilePath &f, const TFrameId &frameId, TLevelReaderPli *pli) : TImageReader(f), m_frameId(frameId), m_lrp(pli) {} //============================================================================= GroupTag *makeGroup(TVectorImageP &vi, int &currStyleId, int &index, int currDepth) { std::vector tags; int i = index; while (i < (UINT)vi->getStrokeCount() && vi->getCommonGroupDepth(i, index) >= currDepth) { int strokeDepth = vi->getGroupDepth(i); if (strokeDepth == currDepth) putStroke(vi->getStroke(i++), currStyleId, tags); else if (strokeDepth > currDepth) tags.push_back(makeGroup(vi, currStyleId, i, currDepth + 1)); else assert(false); } index = i; return new GroupTag(GroupTag::STROKE, tags.size(), tags.data()); } //=============================================================================