virtual bool WriteChemObject(OBConversion* pConv) { //If there is a PNG input file, embed all the subsequent molecules in it if(!CopyOfInput.empty() && bytesToIEND>0) { OBBase* pOb = pConv->GetChemObject(); return WriteMolecule(pOb, pConv); } else { _hasInputPngFile = false; //draw image in PNG2, which will test whether embedding is required OBFormat* ppng2 = OBConversion::FindFormat("_png2"); if(!ppng2) { obErrorLog.ThrowError("PNG Format","PNG2Format not found. Probably the Cairo library is not loaded.", obError); return false; } bool ret = ppng2->WriteChemObject(pConv); if(pConv->IsLast()) pConv->SetOutFormat(""); // report as output objects, not "PNG_files" return ret; } };
bool SVGFormat::WriteChemObject(OBConversion* pConv) { //Molecules are stored here as pointers to OBBase objects, which are not deleted as usual. //When there are no more they are sent to WriteMolecule. //This allows their number to be determined whatever their source //(they may also have been filtered), so that the table can be properly dimensioned. //NOT CURRENTLY IMPLEMENTED //If the first object is OBText, the part of it before each insertion point (if it exists) //is output before every molecule. This allows molecule structures to be displayed //in a template. The x option to omit the XML header is set OBBase* pOb = pConv->GetChemObject(); if(pConv->GetOutputIndex()<=1) { _objects.clear(); _nmax=0; pConv->AddOption("svgwritechemobject"); // to show WriteMolecule that this function has been called const char* pc = pConv->IsOption("c"); //alternative for babel because -xc cannot take a parameter, because some other format uses it //similarly for -xr -xp if(!pc) pc = pConv->IsOption("cols", OBConversion::GENOPTIONS); const char* pr = pConv->IsOption("r"); if(!pr) pr = pConv->IsOption("rows", OBConversion::GENOPTIONS); if(pr) _nrows = atoi(pr); if(pc) _ncols = atoi(pc); if(pr && pc) // both specified: fixes maximum number objects to be output _nmax = _nrows * _ncols; //explicit max number of objects const char* pmax =pConv->IsOption("N"); if(pmax) _nmax = atoi(pmax); /* _ptext = dynamic_cast<OBText*>(pOb); if(_ptext) { pConv->AddOption("x");//omit XML header _textpos = 0; return true; } */ } OBMoleculeFormat::DoOutputOptions(pOb, pConv); //save molecule _objects.push_back(pOb); bool ret=true; //Finish if no more input or if the number of molecules has reached the allowed maximum(if specified) bool nomore = _nmax && (_objects.size()==_nmax); if((pConv->IsLast() || nomore)) { int nmols = _objects.size(); //Set table properties according to the options and the number of molecules to be output if(!(nmols==0 || //ignore this block if there is no input or (_nrows && _ncols) || //if the user has specified both rows and columns or (!_nrows && !_ncols) && nmols==1)//if neither is specified and there is one output molecule ) { if(!_nrows && !_ncols ) //neither specified { //assign cols/rows in square _ncols = (int)ceil(sqrt(((double)nmols))); } if(_nrows) _ncols = (nmols-1) / _nrows + 1; //rounds up else if(_ncols) _nrows = (nmols-1) / _ncols + 1; } //output all collected molecules int n=0; /* if(_ptext) { _textpos =0; //Output the text up to the first insertion point, or all of it if there is no insertion point. *pConv->GetOutStream() << _ptext->GetText(_textpos); } */ vector<OBBase*>::iterator iter; for(iter=_objects.begin(); ret && iter!=_objects.end(); ++iter) { //need to manually set these to mimic normal conversion pConv->SetOutputIndex(++n); pConv->SetLast(n==_objects.size()); ret=WriteMolecule(*iter, pConv); /* //If there is a subsequent insertion point, output text up to it and update _textpos. //If there is not, do nothing. if(_ptext) *pConv->GetOutStream() << _ptext->GetText(_textpos, true); */ } /* //Output remaining text if(_ptext) *pConv->GetOutStream() << _ptext->GetText(_textpos); */ //delete all the molecules for(iter=_objects.begin();iter!=_objects.end(); ++iter) delete *iter; delete _ptext;//delete text, NULL or not _objects.clear(); _ptext = NULL; _nmax = _ncols = _nrows = 0; } //OBConversion decrements OutputIndex when returns false because it thinks it is an error //So we compensate. if(!ret || nomore) pConv->SetOutputIndex(pConv->GetOutputIndex()+1); return ret && !nomore; }