Esempio n. 1
0
	TextFragment subText(const TextFragment& frag, int start, int end)
	{		
		// this impl does an unneccesary copy, to keep TextFragment very simple for now.
		if(!frag) return TextFragment();
		if(start >= end) return TextFragment();
		
		
		// we won't know the output fragment size in bytes until iterating the code points. 
		int len = frag.lengthInBytes();
		SmallStackBuffer<char> temp(len);
		char* buf = temp.data();
		char* pb = buf;
		
		auto first = codepoint_iterator<const char*>(frag.getText());		
		auto it = first;
		for(int i=0; i<start; ++i)
		{
			++it;
		}
		
		for (int i=0; i<end - start; ++i) 
		{
			// write the codepoint as UTF-8 to the buffer
			if(!utf::internal::validate_codepoint(*it)) return TextFragment();
			pb = utf::internal::utf_traits<utf::utf8>::encode(*it, pb);
			++it;
		}	
		
		return TextFragment(buf, pb - buf);
	}
Esempio n. 2
0
TextFragmentIterator::TextFragment TextFragmentIterator::findNextTextFragment(float xPosition)
{
    // A fragment can either be
    // 1. line break when <br> is present or preserveNewline is on (not considered as whitespace) or
    // 2. whitespace (collasped, non-collapsed multi or single) or
    // 3. non-whitespace characters.
    // 4. content end.
    ASSERT(m_currentSegment != m_flowContents.end());
    unsigned startPosition = m_position;
    if (m_atEndOfSegment)
        ++m_currentSegment;

    if (m_currentSegment == m_flowContents.end())
        return TextFragment(startPosition, startPosition, 0, TextFragment::ContentEnd);
    if (isHardLineBreak(m_currentSegment))
        return TextFragment(startPosition, startPosition, 0, TextFragment::HardLineBreak);
    if (isSoftLineBreak(startPosition)) {
        unsigned endPosition = ++m_position;
        return TextFragment(startPosition, endPosition, 0, TextFragment::SoftLineBreak);
    }
    float width = 0;
    bool overlappingFragment = false;
    unsigned endPosition = skipToNextPosition(PositionType::NonWhitespace, startPosition, width, xPosition, overlappingFragment);
    unsigned segmentEndPosition = m_currentSegment->end;
    ASSERT(startPosition <= endPosition);
    if (startPosition < endPosition) {
        bool multipleWhitespace = startPosition + 1 < endPosition;
        bool isCollapsed = multipleWhitespace && m_style.collapseWhitespace;
        m_position = endPosition;
        return TextFragment(startPosition, endPosition, width, TextFragment::Whitespace, endPosition == segmentEndPosition, false, isCollapsed, m_style.collapseWhitespace);
    }
    endPosition = skipToNextPosition(PositionType::Breakable, startPosition, width, xPosition, overlappingFragment);
    m_position = endPosition;
    return TextFragment(startPosition, endPosition, width, TextFragment::NonWhitespace, endPosition == segmentEndPosition, overlappingFragment, false, false);
}
Esempio n. 3
0
	int SymbolTable::getSymbolID(const HashedCharArray& hsl)
	{
		int r = 0;
		
		// get the vector of symbol IDs matching this hash. It probably has one entry but may have more. 
		const std::vector<int>& bin = mHashTable[hsl.hash].mIDVector;
		{
			bool found = false;
			
			std::unique_lock<std::mutex> lock(mHashTable[hsl.hash].mMutex);			

			 for(int ID : bin)
			 {
				// there should be few collisions, so probably the first ID in the hash bin
				// will be the symbol we are looking for. Unfortunately to test for equality we may have to 
				// compare the entire string.	
			 
				TextFragment* binFragment = &mSymbolTextsByID[ID];
				if(compareSizedCharArrays(binFragment->getText(), binFragment->lengthInBytes(), hsl.pChars, hsl.len))
				{
					 r = ID;
					 found = true;
					 break;
				}
			 }
			
			if(!found)
			{	
				mSymbolTextsByID.emplace_back(TextFragment(hsl.pChars, static_cast<int>(hsl.len)));
				r = mSize++;
				mHashTable[hsl.hash].mIDVector.emplace_back(r);		
			}
		}
		return r;
	}
Esempio n. 4
0
	// add an entry to the table. The entry must not already exist in the table.
	// this must be the only way of modifying the symbol table.
	int SymbolTable::addEntry(const HashedCharArray& hsl)
	{		
		mSymbolTextsByID.emplace_back(TextFragment(hsl.pChars, static_cast<int>(hsl.len)));
		
		int newID = mSize++;
		mHashTable[hsl.hash].mIDVector.emplace_back(newID);		
		return newID;
	}
Esempio n. 5
0
void TextParser::ReadText (OptionalType<TextFragment>& result, const TCHAR delimiters[])
{
	uint32 marker = ForwardSkip (_T("\t "));

	uint32 endPoint = ReadText(delimiters, marker);

	if ( (endPoint != marker) && (endPoint < Length()) )
	{
		result = TextFragment(*this, marker, endPoint - marker);
		Forward(endPoint);
	}
}
Esempio n. 6
0
void PathParser::Parse (const TextFragment& input)
{
	TextParser parser (input);
	OptionalType<TextFragment> info;

	parser.ReadText(info, _T(":"));

	if ((info.IsSet()) && (info.Value().Length() == 1))
	{
		m_Drive = *(info.Value().Data());
		parser.Skip(1);
	}

	// Find the last '/ or \ from the back, after the drive
	uint32 index = parser.ReverseFind(_T("\\/"));

	if (index != NUMBER_MAX_UNSIGNED(uint32))
	{
		m_Path = TextFragment(parser, 0, index);
		parser.Skip(index+1);
	}

	// Now we are ate the complete filename
	m_FileName = TextFragment (parser, 0, NUMBER_MAX_UNSIGNED(uint32));

	// Find the extension from the current parser...
	index = parser.ReverseFind(_T("."));

	if (index == NUMBER_MAX_UNSIGNED(uint32))
	{
		// oops there is no extension, BaseFileName == Filename
		m_BaseFileName = m_FileName;
	}
	else
	{
		m_BaseFileName = TextFragment (parser, 0, index);
		m_Extension = TextFragment(parser, index + 1, NUMBER_MAX_UNSIGNED(uint32));
	}
}
Esempio n. 7
0
bool gfxr_font_calculate_size(Common::Array<TextFragment> &fragments, gfx_bitmap_font_t *font, int max_width,
	const char *text, int *width, int *height, int *line_height_p, int *last_offset_p, int flags) {

	int maxheight = font->line_height;
	int last_breakpoint = 0;
	int last_break_width = 0;
	int maxwidth = 0, localmaxwidth = 0;
	const char *breakpoint_ptr = NULL;
	unsigned char curChar;

	if (line_height_p)
		*line_height_p = font->line_height;


	fragments.push_back(TextFragment(text));

	while ((curChar = *text++)) {
		if (curChar >= font->chars_nr) {
			error("Invalid char 0x%02x (max. 0x%02x) encountered in text string '%s', font %04x",
			        curChar, font->chars_nr, text, font->ID);
			if (font->chars_nr > ' ')
				curChar = ' ';
			else {
				return false;
			}
		}

		if (((curChar == '\n') || (curChar == 0x0d)) && !(flags & kFontNoNewlines)) {
			fragments.back().length = text - 1 - fragments.back().offset;

			if (*text)
				maxheight += font->line_height;

			if (curChar == 0x0d && *text == '\n')
				text++; // Interpret DOS-style CR LF as single NL

			fragments.push_back(TextFragment(text));

			if (localmaxwidth > maxwidth)
				maxwidth = localmaxwidth;

			localmaxwidth = 0;

		} else { // curChar != '\n'
			localmaxwidth += font->widths[curChar];

			if (localmaxwidth > max_width) {
				int blank_break = 1; // break is at a blank char, i.e. not within a word

				maxheight += font->line_height;

				if (last_breakpoint == 0) { // Text block too long and without whitespace?
					last_breakpoint = localmaxwidth - font->widths[curChar];
					last_break_width = 0;
					--text;
					blank_break = 0; // non-blank break
				} else {
					text = breakpoint_ptr + 1;
					assert(breakpoint_ptr);
				}

				if (last_breakpoint == 0) {
					warning("[GFX] maxsize %d too small for '%s'", max_width, text);
				}

				if (last_breakpoint > maxwidth)
					maxwidth = last_breakpoint;

				fragments.back().length = text - blank_break - fragments.back().offset;
				fragments.push_back(TextFragment(text));

				localmaxwidth = localmaxwidth - last_breakpoint;
				if (!(flags & kFontCountWhitespace))
					localmaxwidth -= last_break_width;
				last_breakpoint = localmaxwidth = 0;

			} else if (*text == ' ') {
				last_breakpoint = localmaxwidth;
				last_break_width = font->widths[curChar];
				breakpoint_ptr = text;
			}

		}
	}

	if (localmaxwidth > maxwidth)
		*width = localmaxwidth;
	else
		*width = maxwidth;

	if (last_offset_p)
		*last_offset_p = localmaxwidth;

	if (height)
		*height = maxheight;

	fragments.back().length = text - fragments.back().offset - 1;

	return true;
}