// -------------------------------------------------------------------
//  Get material library from file.
void ObjFileParser::getMaterialLib()
{
    // Translate tuple
    m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
    if( m_DataIt == m_DataItEnd ) {
        return;
    }

    char *pStart = &(*m_DataIt);
    while( m_DataIt != m_DataItEnd && !IsLineEnd( *m_DataIt ) ) {
        ++m_DataIt;
    }

    // Check for existence
    const std::string strMatName(pStart, &(*m_DataIt));
    IOStream *pFile = m_pIO->Open(strMatName);

    if (!pFile )
    {
        DefaultLogger::get()->error("OBJ: Unable to locate material file " + strMatName);
        m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
        return;
    }

    // Import material library data from file
    std::vector<char> buffer;
    BaseImporter::TextFileToBuffer(pFile,buffer);
    m_pIO->Close( pFile );

    // Importing the material library
    ObjFileMtlImporter mtlImporter( buffer, strMatName, m_pModel );
}
示例#2
0
// -------------------------------------------------------------------
void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) {
    size_t numComponents( 0 );
    DataArrayIt tmp( m_DataIt );
    while( !IsLineEnd( *tmp ) ) {
        if( *tmp == ' ' ) {
            ++numComponents;
        }
        tmp++;
    }
    float x, y, z;
    if( 2 == numComponents ) {
        copyNextWord( m_buffer, BUFFERSIZE );
        x = ( float ) fast_atof( m_buffer );

        copyNextWord( m_buffer, BUFFERSIZE );
        y = ( float ) fast_atof( m_buffer );
        z = 0.0;
    } else if( 3 == numComponents ) {
        copyNextWord( m_buffer, BUFFERSIZE );
        x = ( float ) fast_atof( m_buffer );

        copyNextWord( m_buffer, BUFFERSIZE );
        y = ( float ) fast_atof( m_buffer );

        copyNextWord( m_buffer, BUFFERSIZE );
        z = ( float ) fast_atof( m_buffer );
    } else {
        ai_assert( !"Invalid number of components" );
    }
    point3d_array.push_back( aiVector3D( x, y, z ) );
    m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
}
示例#3
0
// -------------------------------------------------------------------
//  Creates a material from loaded data.
void ObjFileMtlImporter::createMaterial()
{
    std::string line( "" );
    while( !IsLineEnd( *m_DataIt ) ) {
        line += *m_DataIt;
        ++m_DataIt;
    }

    std::vector<std::string> token;
    const unsigned int numToken = tokenize<std::string>( line, token, " \t" );
    std::string name( "" );
    if ( numToken == 1 ) {
        name = AI_DEFAULT_MATERIAL_NAME;
    } else {
        // skip newmtl and all following white spaces
        std::size_t first_ws_pos = line.find_first_of(" \t");
        std::size_t first_non_ws_pos = line.find_first_not_of(" \t", first_ws_pos);
        if (first_non_ws_pos != std::string::npos) {
            name = line.substr(first_non_ws_pos);
        }
    }

    std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( name );
    if ( m_pModel->m_MaterialMap.end() == it) {
        // New Material created
        m_pModel->m_pCurrentMaterial = new ObjFile::Material();
        m_pModel->m_pCurrentMaterial->MaterialName.Set( name );
        m_pModel->m_MaterialLib.push_back( name );
        m_pModel->m_MaterialMap[ name ] = m_pModel->m_pCurrentMaterial;
    } else {
        // Use older material
        m_pModel->m_pCurrentMaterial = (*it).second;
    }
}
// -------------------------------------------------------------------
void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) {
    size_t numComponents( 0 );
    const char* tmp( &m_DataIt[0] );
    while( !IsLineEnd( *tmp ) ) {
        if ( !SkipSpaces( &tmp ) ) {
            break;
        }
        SkipToken( tmp );
        ++numComponents;
    }
    float x, y, z;
    if( 2 == numComponents ) {
        copyNextWord( m_buffer, BUFFERSIZE );
        x = ( float ) fast_atof( m_buffer );

        copyNextWord( m_buffer, BUFFERSIZE );
        y = ( float ) fast_atof( m_buffer );
        z = 0.0;
    } else if( 3 == numComponents ) {
        copyNextWord( m_buffer, BUFFERSIZE );
        x = ( float ) fast_atof( m_buffer );

        copyNextWord( m_buffer, BUFFERSIZE );
        y = ( float ) fast_atof( m_buffer );

        copyNextWord( m_buffer, BUFFERSIZE );
        z = ( float ) fast_atof( m_buffer );
    } else {
        throw DeadlyImportError( "OBJ: Invalid number of components" );
    }
    point3d_array.push_back( aiVector3D( x, y, z ) );
    m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
}
示例#5
0
// -------------------------------------------------------------------
//  Get values for a new material description
void ObjFileParser::getMaterialDesc()
{
    // Get next data for material data
    m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
    if (m_DataIt == m_DataItEnd) {
        return;
    }

    char *pStart = &(*m_DataIt);
    while( m_DataIt != m_DataItEnd && !IsLineEnd( *m_DataIt ) ) {
        ++m_DataIt;
    }

    // In some cases we should ignore this 'usemtl' command, this variable helps us to do so
    bool skip = false;

    // Get name
    std::string strName(pStart, &(*m_DataIt));
    strName = trim_whitespaces(strName);
    if (strName.empty())
        skip = true;

    // If the current mesh has the same material, we simply ignore that 'usemtl' command
    // There is no need to create another object or even mesh here
    if (m_pModel->m_pCurrentMaterial && m_pModel->m_pCurrentMaterial->MaterialName == aiString(strName))
        skip = true;

    if (!skip)
    {
        // Search for material
        std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find(strName);
        if (it == m_pModel->m_MaterialMap.end())
        {
            // Not found, use default material
            m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial;
            DefaultLogger::get()->error("OBJ: failed to locate material " + strName + ", skipping");
            strName = m_pModel->m_pDefaultMaterial->MaterialName.C_Str();
        }
        else
        {
            // Found, using detected material
            m_pModel->m_pCurrentMaterial = (*it).second;
        }

        if (needsNewMesh(strName))
            createMesh(strName);

        m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex(strName);
    }

    // Skip rest of line
    m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
}
示例#6
0
size_t ObjFileParser::getNumComponentsInLine() {
    size_t numComponents( 0 );
    const char* tmp( &m_DataIt[0] );
    while( !IsLineEnd( *tmp ) ) {
        if ( !SkipSpaces( &tmp ) ) {
            break;
        }
        SkipToken( tmp );
        ++numComponents;
    }
    return numComponents;
}
示例#7
0
// -------------------------------------------------------------------
//  Get material library from file.
void ObjFileParser::getMaterialLib()
{
    // Translate tuple
    m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
    if( m_DataIt == m_DataItEnd ) {
        return;
    }

    char *pStart = &(*m_DataIt);
    while( m_DataIt != m_DataItEnd && !IsLineEnd( *m_DataIt ) ) {
        ++m_DataIt;
    }

    // Check for existence
    const std::string strMatName(pStart, &(*m_DataIt));
    std::string absName;
    if ( m_pIO->StackSize() > 0 ) {
        std::string path = m_pIO->CurrentDirectory();
        if ( '/' != *path.rbegin() ) {
          path += '/';
        }
        absName = path + strMatName;
    } else {
        absName = strMatName;
    }
    IOStream *pFile = m_pIO->Open( absName );

    if (!pFile ) {
        DefaultLogger::get()->error("OBJ: Unable to locate material file " + strMatName);
        std::string strMatFallbackName = m_originalObjFileName.substr(0, m_originalObjFileName.length() - 3) + "mtl";
        DefaultLogger::get()->info("OBJ: Opening fallback material file " + strMatFallbackName);
        pFile = m_pIO->Open(strMatFallbackName);
        if (!pFile) {
            DefaultLogger::get()->error("OBJ: Unable to locate fallback material file " + strMatName);
            m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
            return;
        }
    }

    // Import material library data from file.
    // Some exporters (e.g. Silo) will happily write out empty
    // material files if the model doesn't use any materials, so we
    // allow that.
    std::vector<char> buffer;
    BaseImporter::TextFileToBuffer( pFile, buffer, BaseImporter::ALLOW_EMPTY );
    m_pIO->Close( pFile );

    // Importing the material library
    ObjFileMtlImporter mtlImporter( buffer, strMatName, m_pModel );
}
// -------------------------------------------------------------------
//  Get values for a new material description
void ObjFileParser::getMaterialDesc()
{
    // Each material request a new object.
    // Sometimes the object is already created (see 'o' tag by example), but it is not initialized !
    // So, we create a new object only if the current on is already initialized !
    if (m_pModel->m_pCurrent != NULL &&
        (   m_pModel->m_pCurrent->m_Meshes.size() > 1 ||
            (m_pModel->m_pCurrent->m_Meshes.size() == 1 && m_pModel->m_Meshes[m_pModel->m_pCurrent->m_Meshes[0]]->m_Faces.size() != 0)  )
        )
        m_pModel->m_pCurrent = NULL;

    // Get next data for material data
    m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
    if (m_DataIt == m_DataItEnd)
        return;

    char *pStart = &(*m_DataIt);
    while( m_DataIt != m_DataItEnd && !IsLineEnd( *m_DataIt ) ) {
        ++m_DataIt;
    }

    // Get name
    std::string strName(pStart, &(*m_DataIt));
    if ( strName.empty())
        return;

    // Search for material
    std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strName );
    if ( it == m_pModel->m_MaterialMap.end() )
    {
        // Not found, use default material
        m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial;
        DefaultLogger::get()->error("OBJ: failed to locate material " + strName + ", skipping");
    }
    else
    {
        // Found, using detected material
        m_pModel->m_pCurrentMaterial = (*it).second;
        if ( needsNewMesh( strName ))
        {
            createMesh();
        }
        m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex( strName );
    }

    // Skip rest of line
    m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
}
示例#9
0
// -------------------------------------------------------------------
//  Loads a color definition
void ObjFileMtlImporter::getColorRGBA( aiColor3D *pColor )
{
    ai_assert( NULL != pColor );

    float r( 0.0f ), g( 0.0f ), b( 0.0f );
    m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, r );
    pColor->r = r;

    // we have to check if color is default 0 with only one token
    if( !IsLineEnd( *m_DataIt ) ) {
        m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, g );
        m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, b );
    }
    pColor->g = g;
    pColor->b = b;
}
示例#10
0
// ------------------------------------------------------------------------------------------------
// Remove line comments from a file
void CommentRemover::RemoveLineComments(const char* szComment,
	char* szBuffer, char chReplacement /* = ' ' */)
{
	// validate parameters
	ai_assert(NULL != szComment && NULL != szBuffer && *szComment);

	const size_t len = strlen(szComment);
	while (*szBuffer)	{

		// skip over quotes
		if (*szBuffer == '\"' || *szBuffer == '\'')
			while (*szBuffer++ && *szBuffer != '\"' && *szBuffer != '\'');

		if (!strncmp(szBuffer,szComment,len)) {
			while (!IsLineEnd(*szBuffer))
				*szBuffer++ = chReplacement;
		}
		++szBuffer;
	}
}
示例#11
0
// -------------------------------------------------------------------
//	Get values for a new face instance
void ObjFileParser::getFace(aiPrimitiveType type)
{
	copyNextLine(m_buffer, BUFFERSIZE);
	if (m_DataIt == m_DataItEnd)
		return;

	char *pPtr = m_buffer;
	char *pEnd = &pPtr[BUFFERSIZE];
	pPtr = getNextToken<char*>(pPtr, pEnd);
	if (pPtr == pEnd || *pPtr == '\0')
		return;

	std::vector<unsigned int> *pIndices = new std::vector<unsigned int>;
	std::vector<unsigned int> *pTexID = new std::vector<unsigned int>;
	std::vector<unsigned int> *pNormalID = new std::vector<unsigned int>;
	bool hasNormal = false;

	const int vSize = m_pModel->m_Vertices.size();
	const int vtSize = m_pModel->m_TextureCoord.size();
	const int vnSize = m_pModel->m_Normals.size();

	const bool vt = (!m_pModel->m_TextureCoord.empty());
	const bool vn = (!m_pModel->m_Normals.empty());
	int iStep = 0, iPos = 0;
	while (pPtr != pEnd)
	{
		iStep = 1;

		if (IsLineEnd(*pPtr))
			break;

		if (*pPtr=='/' )
		{
			if (type == aiPrimitiveType_POINT) {
				DefaultLogger::get()->error("Obj: Separator unexpected in point statement");
			}
			if (iPos == 0)
			{
				//if there are no texture coordinates in the file, but normals
				if (!vt && vn) {
					iPos = 1;
					iStep++;
				}
			}
			iPos++;
		}
		else if ( isSeparator(*pPtr) )
		{
			iPos = 0;
		}
		else 
		{
			//OBJ USES 1 Base ARRAYS!!!!
			const int iVal = atoi( pPtr );

			// increment iStep position based off of the sign and # of digits
			int tmp = iVal;
			if (iVal < 0)
			    ++iStep;
			while ( ( tmp = tmp / 10 )!=0 )
				++iStep;

			if ( iVal > 0 )
			{
				// Store parsed index
				if ( 0 == iPos )
				{
					pIndices->push_back( iVal-1 );
				}
				else if ( 1 == iPos )
				{	
					pTexID->push_back( iVal-1 );
				}
				else if ( 2 == iPos )
				{
					pNormalID->push_back( iVal-1 );
					hasNormal = true;
				}
				else
				{
					reportErrorTokenInFace();
				}
			}
			else if ( iVal < 0 )
			{
				// Store relatively index
				if ( 0 == iPos )
				{
					pIndices->push_back( vSize + iVal );
				}
				else if ( 1 == iPos )
				{
					pTexID->push_back( vtSize + iVal );
				}
				else if ( 2 == iPos )
				{
					pNormalID->push_back( vnSize + iVal );
					hasNormal = true;
				}
				else
				{
					reportErrorTokenInFace();
				}
			}
		}
		pPtr += iStep;
	}

	if ( pIndices->empty() ) 
	{
		DefaultLogger::get()->error("Obj: Ignoring empty face");
		m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
		return;
	}

	ObjFile::Face *face = new ObjFile::Face( pIndices, pNormalID, pTexID, type );
	
	// Set active material, if one set
	if (NULL != m_pModel->m_pCurrentMaterial) 
		face->m_pMaterial = m_pModel->m_pCurrentMaterial;
	else 
		face->m_pMaterial = m_pModel->m_pDefaultMaterial;

	// Create a default object, if nothing is there
	if ( NULL == m_pModel->m_pCurrent )
		createObject( "defaultobject" );
	
	// Assign face to mesh
	if ( NULL == m_pModel->m_pCurrentMesh )
	{
		createMesh();
	}
	
	// Store the face
	m_pModel->m_pCurrentMesh->m_Faces.push_back( face );
	m_pModel->m_pCurrentMesh->m_uiNumIndices += (unsigned int)face->m_pVertices->size();
	m_pModel->m_pCurrentMesh->m_uiUVCoordinates[ 0 ] += (unsigned int)face->m_pTexturCoords[0].size(); 
	if( !m_pModel->m_pCurrentMesh->m_hasNormals && hasNormal ) 
	{
		m_pModel->m_pCurrentMesh->m_hasNormals = true;
	}
	// Skip the rest of the line
	m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
}
示例#12
0
// ------------------------------------------------------------------------------------------------
void Tokenize(TokenList& output_tokens, const char* input)
{
    ai_assert(input);

    // line and column numbers numbers are one-based
    unsigned int line = 1;
    unsigned int column = 1;

    bool comment = false;
    bool in_double_quotes = false;
    bool pending_data_token = false;

    const char* token_begin = NULL, *token_end = NULL;
    for (const char* cur = input;*cur;column += (*cur == '\t' ? ASSIMP_FBX_TAB_WIDTH : 1), ++cur) {
        const char c = *cur;

        if (IsLineEnd(c)) {
            comment = false;

            column = 0;
            ++line;
        }

        if(comment) {
            continue;
        }

        if(in_double_quotes) {
            if (c == '\"') {
                in_double_quotes = false;
                token_end = cur;

                ProcessDataToken(output_tokens,token_begin,token_end,line,column);
                pending_data_token = false;
            }
            continue;
        }

        switch(c)
        {
        case '\"':
            if (token_begin) {
                TokenizeError("unexpected double-quote", line, column);
            }
            token_begin = cur;
            in_double_quotes = true;
            continue;

        case ';':
            ProcessDataToken(output_tokens,token_begin,token_end,line,column);
            comment = true;
            continue;

        case '{':
            ProcessDataToken(output_tokens,token_begin,token_end, line, column);
            output_tokens.push_back(new_Token(cur,cur+1,TokenType_OPEN_BRACKET,line,column));
            continue;

        case '}':
            ProcessDataToken(output_tokens,token_begin,token_end,line,column);
            output_tokens.push_back(new_Token(cur,cur+1,TokenType_CLOSE_BRACKET,line,column));
            continue;

        case ',':
            if (pending_data_token) {
                ProcessDataToken(output_tokens,token_begin,token_end,line,column,TokenType_DATA,true);
            }
            output_tokens.push_back(new_Token(cur,cur+1,TokenType_COMMA,line,column));
            continue;

        case ':':
            if (pending_data_token) {
                ProcessDataToken(output_tokens,token_begin,token_end,line,column,TokenType_KEY,true);
            }
            else {
                TokenizeError("unexpected colon", line, column);
            }
            continue;
        }

        if (IsSpaceOrNewLine(c)) {

            if (token_begin) {
                // peek ahead and check if the next token is a colon in which
                // case this counts as KEY token.
                TokenType type = TokenType_DATA;
                for (const char* peek = cur;  *peek && IsSpaceOrNewLine(*peek); ++peek) {
                    if (*peek == ':') {
                        type = TokenType_KEY;
                        cur = peek;
                        break;
                    }
                }

                ProcessDataToken(output_tokens,token_begin,token_end,line,column,type);
            }

            pending_data_token = false;
        }
        else {
            token_end = cur;
            if (!token_begin) {
                token_begin = cur;
            }

            pending_data_token = true;
        }
    }
}
示例#13
0
int ReadInLine(FILE* pFile, REC_INFO* pLineInfo)
{
    char* pLine = NULL;
    int ret = 0;
    unsigned int readPos = 0;
    unsigned int eleLen = 0;
    size_t lineLen = 0;
    REC_INFO* pEleEnd = pLineInfo;
    enum ELE_SEPERATOR_TYPE sepType = SEP_END;

    pLine = (char*)malloc(MAX_LINE_CHAR_COUNT);
    OutString(DBG_RES, "Malloc Local pLine\n");
    if(pLine == NULL)
    {
        return -1;
    }
    memset(pLine, 0, MAX_LINE_CHAR_COUNT);

    ret = -2;
    while(fgets(pLine, MAX_LINE_CHAR_COUNT, pFile) != NULL)
    {
        lineLen = strlen(pLine);
        for(readPos = 0, eleLen = 0; readPos < lineLen; ++readPos)
        {
            if(IsSeperator(pLine[readPos],&sepType))
            {
                if(eleLen > 0)
                {
                    pEleEnd = PushEleEnd(pEleEnd, ELE_TEXT, pLine + readPos - eleLen, eleLen);
                    if(pEleEnd == NULL)
                    {
                        ret = -3;
                        goto FREE_AND_RETURN;
                    }
                    eleLen = 0;
                }

                pEleEnd = PushEleEnd(pEleEnd, ELE_SEPERATOR, &sepType, 0);
                if(pEleEnd == NULL)
                {
                    ret = -3;
                    goto FREE_AND_RETURN;
                }
            }
            else
            {
                ++eleLen;
            }
        } 
        if(eleLen != 0)
        {
            pEleEnd = PushEleEnd(pEleEnd, ELE_TEXT, pLine + readPos - eleLen, eleLen);
            if(pEleEnd == NULL)
            {
                ret = -3;
                goto FREE_AND_RETURN;
            }
            eleLen = 0;
        }
        if(lineLen == 0)
        {
            ret = -4;
            goto FREE_AND_RETURN;
        }
        if(IsLineEnd(pLine[lineLen - 1]))
        {
            ret = 0;
            goto FREE_AND_RETURN;
        }
    }
    
FREE_AND_RETURN:
    free(pLine);
    OutString(DBG_RES, "FREE Local pLine\n");
    return ret;
}
示例#14
0
void Font::SplitTextToStrings(const WideString & text, const Vector2 & targetRectSize, Vector<WideString> & resultVector)
{
	int32 targetWidth = (int32)(targetRectSize.dx * Core::GetVirtualToPhysicalFactor());

	enum
	{
		SKIP = 0,
		GOODCHAR,	// all characters we like (symbols, special chars, except \n and space
		FINISH,	// process last line
		EXIT,
	};

    // Yuri Coder, 2013/12/10. Replace "\n" occurrences (two chars) to '\n' (one char) is done by Yaml parser,
    // so appropriate code (state NEXTLINE)is removed from here. See please MOBWOT-6499.

    
    SeparatorPositions separator;
    
	resultVector.clear();
	int state = SKIP;
	int totalSize = (int)text.length();
	
	Vector<float32> sizes;
	GetStringSize(text, &sizes);
    if(sizes.size() == 0)
    {
        return;
    }

    bool wasSeparator = false;
	
	for(int pos = 0; state != EXIT; pos++)
	{
		char16 t = 0;
		if(pos < totalSize)
		{
			t = text[pos];
		}
        bool isSeparator = IsWordSeparator(t);

		switch (state) 
		{
			case SKIP:
				if (t == 0){ state = FINISH; break; } // if end of string process FINISH state and exit
				else if (IsSpace(t))break; // if space continue with the same state
                else if(IsLineEnd(t))
				{
					// this block is copied from case NEXTLINE: if(t == 'n')
					// unlike in NEXTLINE where we ignore 2 symbols, here we ignore only one
					// so last position is pos instead of (pos-1)
					if (separator.IsLineInitialized()) // if we already have something in current line we add to result
					{
                        AddCurrentLine(text, pos, separator, resultVector);
					}else
					{
						resultVector.push_back(L""); // here we add empty line if there was no characters in current line
					}
					state = SKIP; //always switch to SKIP because we do not know here what will be next
					break;
				}
				else // everything else is good characters
				{
					state = GOODCHAR;
					separator.lastWordStart = pos;
					separator.lastWordEnd = pos;
					if (!separator.IsLineInitialized()) separator.currentLineStart = pos;
				}
				break;
			case GOODCHAR:
                {
                    
                    if(IsSpace(t) || IsLineEnd(t) || t == 0 || (wasSeparator && !isSeparator)) // if we've found any possible separator process current line
				    {
                    
                        //calculate current line width
					    float32 currentLineWidth = 0;

					    int32 startPos = (separator.IsLineInitialized()) ? separator.currentLineStart : 0;
					    for (int i = startPos; i < pos ; i++)
					    {
						    currentLineWidth += sizes[i];
					    }
                    
                        if((currentLineWidth < targetWidth) || ((IsSpace(t) || isSeparator) && 0 == targetWidth))
                        {   // pos could be the end of line. We need to save it
                            if(IsLineEnd(t) || t == 0)
                            {
                                AddCurrentLine(text, pos, separator, resultVector);
                            }
                            else
                            {
                                separator.currentLineEnd = pos;
                                separator.lastWordEnd = pos;
                            }
                        }
                        else if(currentLineWidth == targetWidth)
                        {   // line fit all available space
                            DVASSERT(pos > separator.currentLineStart);
                        
                            AddCurrentLine(text, pos, separator, resultVector);
                        }
                        else
                        {   //currentLineWidth > targetWidth
                            int32 currentLineLength = separator.currentLineEnd - separator.currentLineStart;
                            if((currentLineLength > 0))
                            {   // use previous position of separator to split text
                            
                                pos = separator.currentLineEnd;
                                AddCurrentLine(text, pos, separator, resultVector);
                                t = 0;
                                if(pos + 1 < totalSize)
		                        {
			                        t = text[pos + 1];
		                        }
                                if(IsSpace(t) || IsLineEnd(t) || t == 0)
                                {
							        state = SKIP;
                                }
                                else
                                {
                                    state = GOODCHAR;
					                separator.lastWordStart = pos;
					                separator.lastWordEnd = pos;
					                if (!separator.IsLineInitialized()) separator.currentLineStart = pos;
                                }
							    break;
                            }
                            else if(pos)
                            {   // truncate text by symbol for very long word
                                if(0 == targetWidth)
                                {
                                    AddCurrentLine(text, pos, separator, resultVector);
                                }
                                else
                                {
								    int32 endPos = (separator.IsLineInitialized()) ? separator.currentLineStart : 0;
                                    for (int i = pos-1; i >= endPos; --i)
                                    {
                                        currentLineWidth -= sizes[i];
                                        if(currentLineWidth <= targetWidth)
                                        {
                                            separator.currentLineEnd = i;
                                            int32 currentLineLength = separator.currentLineEnd - separator.currentLineStart;
                                            if((currentLineLength > 0)) // use previous position of separator to split text
                                            {
                                                pos = separator.currentLineEnd-1;
                                            
                                                AddCurrentLine(text, separator.currentLineEnd, separator, resultVector);
                                            }
                                        
                                            break;
                                        }
                                    
                                        DVASSERT(i);
                                    }
                                }

							    state = SKIP;
							    break;
                            }
                            else
                            {
                                DVASSERT(0);
                            }
                        }
                    }

					if (IsSpace(t) || IsLineEnd(t)) state = SKIP; // if cur char is space go to skip
					else if (t == 0) state = FINISH;
                    else if(wasSeparator && !isSeparator)
                    {
                        // good char after separator
					    separator.lastWordStart = pos;
					    separator.lastWordEnd = pos;
					    if (!separator.IsLineInitialized()) separator.currentLineStart = pos;
                    }
                }
				break;
			case FINISH:
				if (separator.IsLineInitialized()) // we check if we have something left in currentline and add this line to results
				{
                    DVASSERT(separator.currentLineEnd > separator.currentLineStart);
                    AddCurrentLine(text, separator.currentLineEnd, separator, resultVector);
				}
				state = EXIT; // always exit from here
				break;
		};
        wasSeparator = isSeparator;
	};
}