Logo Search packages:      
Sourcecode: kmess version File versions  Download package

Drawing & Stream::reader ( const QByteArray &  rawData,
bool  decodeFromBase64 = false 
) [static]

Convert a raw ISF data stream into a drawing.

If the ISF data is invalid, a null Drawing is returned.

Parameters:
rawDataSource byte array with an ISF stream
decodeFromBase64Whether the bytes are in the Base64 format and need to be decoded first
Returns:
an Isf::Drawing, with null contents on error

Definition at line 64 of file isfqt.cpp.

References Isf::Drawing::boundingRect(), Isf::Drawing::error_, Isf::ISF_ERROR_BAD_STREAMSIZE, Isf::ISF_ERROR_BAD_VERSION, Isf::ISF_ERROR_NONE, Isf::ISF_PARSER_FINISH, Isf::ISF_PARSER_START, Isf::ISF_PARSER_STREAMSIZE, Isf::ISF_PARSER_TAG, Isf::Drawing::isNull_, Isf::Drawing::maxPenSize_, Isf::TagsParser::nextTag(), and Isf::Drawing::setBoundingRect().

{
  // Create a new drawing on the heap to ensure it will keep
  // living after this method returns
  Drawing* drawing = new Drawing();

  ParserState state = ISF_PARSER_START;

  streamData_ = new StreamData();
  streamData_->dataSource = new DataSource( decodeFromBase64
                                            ? QByteArray::fromBase64( rawData )
                                            : rawData );

  int size = streamData_->dataSource->size();
  if( size == 0 )
  {
    state = ISF_PARSER_FINISH;
    drawing->error_ = ISF_ERROR_BAD_STREAMSIZE;
  }

  while( state != ISF_PARSER_FINISH )
  {
    switch( state )
    {
      case ISF_PARSER_START:
      {
        // step 1: read ISF version.
        quint8 version = decodeUInt( streamData_->dataSource );
#ifdef ISFQT_DEBUG_VERBOSE
        qDebug() << "Version:" << version;
#endif
        if ( version != SUPPORTED_ISF_VERSION )
        {
          drawing->error_ = ISF_ERROR_BAD_VERSION;
          drawing->isNull_ = true;
          state = ISF_PARSER_FINISH;
        }
        else
        {
          // version is OK. find ISF stream size next.
          state = ISF_PARSER_STREAMSIZE;
        }

        break;
      }

      case ISF_PARSER_STREAMSIZE:
      {
        // read ISF stream size.
        // check it matches the length of the data array.
        quint64 streamSize = decodeUInt( streamData_->dataSource );

        if ( streamSize != (quint64)( streamData_->dataSource->size() - streamData_->dataSource->pos() ) )
        {
#ifdef ISFQT_DEBUG
          qDebug() << "Invalid stream size" << streamSize
                   << ", expected" << ( streamData_->dataSource->size() - streamData_->dataSource->pos() );
#endif
          // streamsize is bad.
          drawing->error_ = ISF_ERROR_BAD_STREAMSIZE;
          state = ISF_PARSER_FINISH;
        }
        else
        {
#ifdef ISFQT_DEBUG
          qDebug() << "Reading ISF stream of size:" << streamSize << "...";
#endif
          // Validate the drawing
          drawing->isNull_ = false;

          // start looking for ISF tags.
          state = ISF_PARSER_TAG;
        }

        break;
      }

      case ISF_PARSER_TAG:
      {
        if( streamData_->dataSource->atEnd() )
        {
          state = ISF_PARSER_FINISH;
          break;
        }

        // Read the next tag from the stream
        drawing->error_ = TagsParser::nextTag( streamData_, drawing );

        if( drawing->error_ != ISF_ERROR_NONE )
        {
#ifdef ISFQT_DEBUG_VERBOSE
          qWarning() << "Error in last operation, stopping.";
#endif
          state = ISF_PARSER_FINISH;
        }

        break;
      }

      // Should never arrive here! It's here only to avoid compiler warnings.
      case ISF_PARSER_FINISH:
        break;

      break;
    }
  }

#ifdef ISFQT_DEBUG
  qDebug() << "Finished with" << ( drawing->error_ == ISF_ERROR_NONE ? "success" : "error" );
  qDebug();
#endif

  delete streamData_->dataSource;

  if( drawing->error_ != ISF_ERROR_NONE )
  {
    delete streamData_;
    streamData_ = 0;
    return *drawing;
  }

  // Perform the last operations on the drawing

  // Adjust the bounding rectangle to include the strokes borders
  QSize penSize( drawing->maxPenSize_.toSize() );
  streamData_->boundingRect.adjust( -penSize.width() - 1, -penSize.height() - 1,
                                   +penSize.width() + 1, +penSize.height() + 1 );
  drawing->setBoundingRect( streamData_->boundingRect );

#ifdef ISFQT_DEBUG_VERBOSE
  qDebug() << "Drawing bounding rectangle:" << drawing->boundingRect();
  qDebug() << "Maximum thickness:" << drawing->maxPenSize_;
#endif

  delete streamData_;
  streamData_ = 0;
  return *drawing;
}

Here is the call graph for this function:


Generated by  Doxygen 1.6.0   Back to index