Exemple #1
0
inline void FTSimpleLayoutImpl::WrapTextI(const T *buf, const int len,
                                          FTPoint position, int renderMode,
                                          FTBBox *bounds)
{
    FTUnicodeStringItr<T> breakItr(buf);          // points to the last break character
    FTUnicodeStringItr<T> lineStart(buf);         // points to the line start
    float nextStart = 0.0;     // total width of the current line
    float breakWidth = 0.0;    // width of the line up to the last word break
    float currentWidth = 0.0;  // width of all characters on the current line
    float prevWidth;           // width of all characters but the current glyph
    float wordLength = 0.0;    // length of the block since the last break char
    int charCount = 0;         // number of characters so far on the line
    int breakCharCount = 0;    // number of characters before the breakItr
    float glyphWidth, advance;
    FTBBox glyphBounds;

    // Reset the pen position
    pen.Y(0);

    // If we have bounds mark them invalid
    if(bounds)
    {
        bounds->Invalidate();
    }

    // Scan the input for all characters that need output
    FTUnicodeStringItr<T> prevItr(buf);
    for (FTUnicodeStringItr<T> itr(buf); *itr; prevItr = itr++, charCount++)
    {
        // Find the width of the current glyph
        glyphBounds = currentFont->BBox(itr.getBufferFromHere(), 1);
        glyphWidth = glyphBounds.Upper().Xf() - glyphBounds.Lower().Xf();

        advance = currentFont->Advance(itr.getBufferFromHere(), 1);
        prevWidth = currentWidth;
        // Compute the width of all glyphs up to the end of buf[i]
        currentWidth = nextStart + glyphWidth;
        // Compute the position of the next glyph
        nextStart += advance;

        // See if the current character is a space, a break or a regular character
        if((currentWidth > lineLength) || (*itr == '\n'))
        {
            // A non whitespace character has exceeded the line length.  Or a
            // newline character has forced a line break.  Output the last
            // line and start a new line after the break character.
            // If we have not yet found a break, break on the last character
            if(breakItr == lineStart || (*itr == '\n'))
            {
                // Break on the previous character
                breakItr = prevItr;
                breakCharCount = charCount - 1;
                breakWidth = prevWidth;
                // None of the previous words will be carried to the next line
                wordLength = 0;
                // If the current character is a newline discard its advance
                if(*itr == '\n') advance = 0;
            }

            float remainingWidth = lineLength - breakWidth;

            // Render the current substring
            FTUnicodeStringItr<T> breakChar = breakItr;
            // move past the break character and don't count it on the next line either
            ++breakChar; --charCount;
            // If the break character is a newline do not render it
            if(*breakChar == '\n')
            {
                ++breakChar; --charCount;
            }

            if(breakCharCount >= 0)
            {
                OutputWrapped(lineStart.getBufferFromHere(), breakCharCount,
                              //breakItr.getBufferFromHere() - lineStart.getBufferFromHere(),
                              position, renderMode, remainingWidth, bounds);
            }

            // Store the start of the next line
            lineStart = breakChar;
            // TODO: Is Height() the right value here?
            pen -= FTPoint(0, currentFont->LineHeight() * lineSpacing);
            // The current width is the width since the last break
            nextStart = wordLength + advance;
            wordLength += advance;
            currentWidth = wordLength + advance;
            // Reset the safe break for the next line
            breakItr = lineStart;
            charCount -= breakCharCount;
        }
        else if(iswspace(*itr))
        {
            // This is the last word break position
            wordLength = 0;
            breakItr = itr;
            breakCharCount = charCount;

            // Check to see if this is the first whitespace character in a run
            if(buf == itr.getBufferFromHere() || !iswspace(*prevItr))
            {
                // Record the width of the start of the block
                breakWidth = currentWidth;
            }
        }
        else
        {
            wordLength += advance;
        }
    }

    float remainingWidth = lineLength - currentWidth;
    // Render any remaining text on the last line
    // Disable justification for the last row
    if(alignment == FTGL::ALIGN_JUSTIFY)
    {
        alignment = FTGL::ALIGN_LEFT;
        OutputWrapped(lineStart.getBufferFromHere(), -1, position, renderMode,
                      remainingWidth, bounds);
        alignment = FTGL::ALIGN_JUSTIFY;
    }
    else
    {
        OutputWrapped(lineStart.getBufferFromHere(), -1, position, renderMode,
                      remainingWidth, bounds);
    }
}
Exemple #2
0
inline void FTSimpleLayoutImpl::WrapTextI(const T *buf, const int len,
                                          FTPoint position, int renderMode,
                                          FTBBox *bounds)
{
    FTUnicodeStringItr<T> breakItr(buf);          // points to the last break character
    FTUnicodeStringItr<T> lineStart(buf);         // points to the line start
    float nextStart = 0.0;     // total width of the current line
    float breakWidth = 0.0;    // width of the line up to the last word break
    float currentWidth = 0.0;  // width of all characters on the current line
    float prevWidth;           // width of all characters but the current glyph
    float wordLength = 0.0;    // length of the block since the last break char
    int charCount = 0;         // number of characters so far on the line
    int breakCharCount = 0;    // number of characters before the breakItr
    float glyphWidth, advance;
    FTBBox glyphBounds;
	bool refresh = false;
	
    // Reset the pen position
    pen.Y(0);
	
    // If we have bounds mark them invalid
    if(bounds)
    {
		bounds->Invalidate();
    }
	//XLOGXN("FTGL1");
	// Check if the incoming string is different to the previously
	// cached string.
	unsigned int i = 0;
	for (FTUnicodeStringItr<T> itr(buf); *itr; itr++)
	{
		XBREAK(i >= 4096);
		if (i >= stringCacheCount ||
			stringCache[i++] != (unsigned int)*itr)
		{
			refresh = true;
			break;
		}
	}
	
	//XLOGXN("FTGL2");
	if (refresh)
	{
		//XLOGXN("FTGL3");
		stringCacheCount = 0;
        layoutGlyphCache.clear();
		
		// Scan the input for all characters that need output
		FTUnicodeStringItr<T> prevItr(buf);
		for (FTUnicodeStringItr<T> itr(buf); *itr; prevItr = itr++, charCount++)
		{
			XBREAK(stringCacheCount >= 4096);
			stringCache[stringCacheCount++] = (unsigned int)*itr;
			
			// Find the width of the current glyph
			glyphBounds = currentFont->BBox(itr.getBufferFromHere(), 1);
			glyphWidth = glyphBounds.Upper().Xf() - glyphBounds.Lower().Xf();
			
			advance = currentFont->Advance(itr.getBufferFromHere(), 1);
			prevWidth = currentWidth;
			// Compute the width of all glyphs up to the end of buf[i]
			currentWidth = nextStart + glyphWidth;
			// Compute the position of the next glyph
			nextStart += advance;
			
			// See if the current character is a space, a break or a regular character
			if((currentWidth > lineLength) || (*itr == '\n'))
			{
				// A non whitespace character has exceeded the line length.  Or a
				// newline character has forced a line break.  Output the last
				// line and start a new line after the break character.
				// If we have not yet found a break, break on the last character
				if(breakItr == lineStart || (*itr == '\n'))
				{
					// Break on the previous character
					breakItr = prevItr;
					breakCharCount = charCount - 1;
					breakWidth = prevWidth;
					// None of the previous words will be carried to the next line
					wordLength = 0;
					// If the current character is a newline discard its advance
					if(*itr == '\n') advance = 0;
				}
				
				float remainingWidth = lineLength - breakWidth;
				
				// Render the current substring
				FTUnicodeStringItr<T> breakChar = breakItr;
				// move past the break character and don't count it on the next line either
				++breakChar; --charCount;
				// If the break character is a newline do not render it
				if(*breakChar == '\n')
				{
					++breakChar; --charCount;
				}
				
				layoutGlyphCacheItem_t cacheItem;
				cacheItem.buf = (T*)lineStart.getBufferFromHere();
				cacheItem.charCount = breakCharCount;
				cacheItem.position = FTPoint(position.X(), position.Y(), position.Z());
				cacheItem.remainingWidth = remainingWidth;
				cacheItem.penDiff = FTPoint(0, currentFont->LineHeight() * lineSpacing);
				layoutGlyphCache.push_back(cacheItem);
				
				lineStart = breakChar;
				// The current width is the width since the last break
				nextStart = wordLength + advance;
				wordLength += advance;
				currentWidth = wordLength + advance;
				// Reset the safe break for the next line
				breakItr = lineStart;
				charCount -= breakCharCount;
			}
			else if(iswspace(*itr))
			{
				// This is the last word break position
				wordLength = 0;
				breakItr = itr;
				breakCharCount = charCount;
				
				// Check to see if this is the first whitespace character in a run
				if(buf == itr.getBufferFromHere() || !iswspace(*prevItr))
				{
					// Record the width of the start of the block
					breakWidth = currentWidth;
				}
			}
			else
			{
				wordLength += advance;
			}
		}
		//XLOGXN("FTGL4");
		
		float remainingWidth = lineLength - currentWidth;
		// Render any remaining text on the last line
		// Disable justification for the last row
		//XLOGXN("FTGL5");
		if(alignment == FTGL::ALIGN_JUSTIFY)
		{
			alignment = FTGL::ALIGN_LEFT;
			layoutGlyphCacheItem_t cacheItem;
			cacheItem.buf = (T *)lineStart.getBufferFromHere();
			cacheItem.charCount = -1;
			cacheItem.position = FTPoint(position.X(), position.Y(), position.Z());
			cacheItem.penDiff = FTPoint(0,0,0);
			cacheItem.remainingWidth = remainingWidth;
			layoutGlyphCache.push_back(cacheItem);
			alignment = FTGL::ALIGN_JUSTIFY;
		}
		else
		{
			layoutGlyphCacheItem_t cacheItem;
			cacheItem.buf = (T *)lineStart.getBufferFromHere();
			cacheItem.charCount = -1;
			cacheItem.position = FTPoint(position.X(), position.Y(), position.Z());
			cacheItem.penDiff = FTPoint(0,0,0);
			cacheItem.remainingWidth = remainingWidth;
			layoutGlyphCache.push_back(cacheItem);
		}
		//XLOGXN("FTGL6");
	}
	
	//XLOGXN("FTGL7");
	// Draw each of the glyphs in the cache.
	currentFont->PreRender();
	//XLOGXN("FTGL8");
    std::list<layoutGlyphCacheItem_t>::iterator it;
	for (it = layoutGlyphCache.begin(); it != layoutGlyphCache.end(); it++)
	{
		layoutGlyphCacheItem_t cacheItem = (*it);
		
		OutputWrapped((T*)cacheItem.buf,
					  cacheItem.charCount,
					  cacheItem.position,
					  renderMode,
					  cacheItem.remainingWidth,
					  bounds);
		pen -= cacheItem.penDiff;
	}
	//XLOGXN("FTGL9");
	currentFont->PostRender();
}