int Font::Index (const char* s, int len, int offset, boolean between) {
    register XFontStruct* i = (XFontStruct*)rep->info;
    register const char* p;
    register int n, w;
    int coff, cw;

    if (offset < 0 || *s == '\0' || len == 0) {
	return 0;
    }
    if (IsFixedWidth(i)) {
	cw = i->min_bounds.width;
	n = offset / cw;
	coff = offset % cw;
    } else {
	w = 0;
	for (p = s, n = 0; *p != '\0' && n < len; ++p, ++n) {
	    cw = XTextWidth(i, p, 1);
	    w += cw;
	    if (w > offset) {
		break;
	    }
	}
	coff = offset - w + cw;
    }
    if (between && coff > cw/2) {
	++n;
    }
    return min(n, len);
}
Exemple #2
0
bool Text::FilterImplicitAttributes(XMLElement& dest) const
{
    if (!UISelectable::FilterImplicitAttributes(dest))
        return false;

    if (!IsFixedWidth())
    {
        if (!RemoveChildXML(dest, "Size"))
            return false;
        if (!RemoveChildXML(dest, "Min Size"))
            return false;
        if (!RemoveChildXML(dest, "Max Size"))
            return false;
    }

    return true;
}
Exemple #3
0
void Text::UpdateText(bool onResize)
{
    rowWidths_.clear();
    printText_.clear();

    if (font_)
    {
        FontFace* face = font_->GetFace(fontSize_);
        if (!face)
            return;

        rowHeight_ = face->GetRowHeight();

        int width = 0;
        int height = 0;
        int rowWidth = 0;
        auto rowHeight = RoundToInt(rowSpacing_ * rowHeight_);

        // First see if the text must be split up
        if (!wordWrap_)
        {
            printText_ = unicodeText_;
            printToText_.resize(printText_.size());
            for (unsigned i = 0; i < printText_.size(); ++i)
                printToText_[i] = i;
        }
        else
        {
            int maxWidth = GetWidth();
            unsigned nextBreak = 0;
            unsigned lineStart = 0;
            printToText_.clear();

            for (unsigned i = 0; i < unicodeText_.size(); ++i)
            {
                unsigned j;
                unsigned c = unicodeText_[i];

                if (c != '\n')
                {
                    bool ok = true;

                    if (nextBreak <= i)
                    {
                        int futureRowWidth = rowWidth;
                        for (j = i; j < unicodeText_.size(); ++j)
                        {
                            unsigned d = unicodeText_[j];
                            if (d == ' ' || d == '\n')
                            {
                                nextBreak = j;
                                break;
                            }
                            const FontGlyph* glyph = face->GetGlyph(d);
                            if (glyph)
                            {
                                futureRowWidth += glyph->advanceX_;
                                if (j < unicodeText_.size() - 1)
                                    futureRowWidth += face->GetKerning(d, unicodeText_[j + 1]);
                            }
                            if (d == '-' && futureRowWidth <= maxWidth)
                            {
                                nextBreak = j + 1;
                                break;
                            }
                            if (futureRowWidth > maxWidth)
                            {
                                ok = false;
                                break;
                            }
                        }
                    }

                    if (!ok)
                    {
                        // If did not find any breaks on the line, copy until j, or at least 1 char, to prevent infinite loop
                        if (nextBreak == lineStart)
                        {
                            while (i < j)
                            {
                                printText_.push_back(unicodeText_[i]);
                                printToText_.push_back(i);
                                ++i;
                            }
                        }
                        // Eliminate spaces that have been copied before the forced break
                        while (printText_.size() && printText_.back() == ' ')
                        {
                            printText_.pop_back();
                            printToText_.pop_back();
                        }
                        printText_.push_back('\n');
                        printToText_.push_back(Min(i, unicodeText_.size() - 1));
                        rowWidth = 0;
                        nextBreak = lineStart = i;
                    }

                    if (i < unicodeText_.size())
                    {
                        // When copying a space, position is allowed to be over row width
                        c = unicodeText_[i];
                        const FontGlyph* glyph = face->GetGlyph(c);
                        if (glyph)
                        {
                            rowWidth += glyph->advanceX_;
                            if (i < unicodeText_.size() - 1)
                                rowWidth += face->GetKerning(c, unicodeText_[i + 1]);
                        }
                        if (rowWidth <= maxWidth)
                        {
                            printText_.push_back(c);
                            printToText_.push_back(i);
                        }
                    }
                }
                else
                {
                    printText_.push_back('\n');
                    printToText_.push_back(Min(i, unicodeText_.size() - 1));
                    rowWidth = 0;
                    nextBreak = lineStart = i;
                }
            }
        }

        rowWidth = 0;

        for (unsigned i = 0; i < printText_.size(); ++i)
        {
            unsigned c = printText_[i];

            if (c != '\n')
            {
                const FontGlyph* glyph = face->GetGlyph(c);
                if (glyph)
                {
                    rowWidth += glyph->advanceX_;
                    if (i < printText_.size() - 1)
                        rowWidth += face->GetKerning(c, printText_[i + 1]);
                }
            }
            else
            {
                width = Max(width, rowWidth);
                height += rowHeight;
                rowWidths_.push_back(rowWidth);
                rowWidth = 0;
            }
        }

        if (rowWidth)
        {
            width = Max(width, rowWidth);
            height += rowHeight;
            rowWidths_.push_back(rowWidth);
        }

        // Set at least one row height even if text is empty
        if (!height)
            height = rowHeight;

        // Set minimum and current size according to the text size, but respect fixed width if set
        if (!IsFixedWidth())
        {
            if (wordWrap_)
                SetMinWidth(0);
            else
            {
                SetMinWidth(width);
                SetWidth(width);
            }
        }
        SetFixedHeight(height);

        charLocationsDirty_ = true;
    }
    else
    {
        // No font, nothing to render
        pageGlyphLocations_.clear();
    }

    // If wordwrap is on, parent may need layout update to correct for overshoot in size. However, do not do this when the
    // update is a response to resize, as that could cause infinite recursion
    if (wordWrap_ && !onResize)
    {
        UIElement* parent = GetParent();
        if (parent && parent->GetLayoutMode() != LM_FREE)
            parent->UpdateLayout();
    }
}
Exemple #4
0
void FlexGrid::Layout()
{
	std::vector<double> heights(rows.size(), 0.0);
	std::vector<double> widths(defaultCols.size(), 0.0);
	Vec2 totalSize(0, 0);

	Vec2 padding2x = padding;
	padding2x *= 2;

	// First, measure each of the cells to determine the height of each row
	// and width of each column.
	auto heightIter = heights.begin();
	auto widthIter = widths.begin();
	for (auto &cols : rows) {
		for (auto &cell : cols) {
			if (cell) {
				Vec3 size = cell->Measure();
				size += padding2x;

				if (size.x > *widthIter) {
					*widthIter = size.x;
				}
				if (size.y > *heightIter) {
					*heightIter = size.y;
				}
			}
			++widthIter;
		}

		++heightIter;
		widthIter = widths.begin();
	}

	// If a fixed size is set, then scale the dimensions.
	if (IsFixedWidth()) {
		ScaleDimension(widths, fixedSize.x, padding.x, margin.x);
	}
	if (IsFixedHeight()) {
		ScaleDimension(heights, fixedSize.y, padding.y, margin.y);
	}

	// Move each cell contents into position.
	heightIter = heights.begin();
	widthIter = widths.begin();
	double x = 0;
	double y = 0;
	for (auto &cols : rows) {
		for (auto &cell : cols) {
			if (cell) {
				cell->SetExtents(x, y, *widthIter, *heightIter,
					padding.x, padding.y);
			}
			x += *widthIter + padding2x.x;
			if (x > totalSize.x) {
				totalSize.x = x;
			}
			x += margin.x;
			++widthIter;
		}

		y += *heightIter + padding2x.y;
		totalSize.y = y;
		y += margin.y;
		++heightIter;
		x = 0;
		widthIter = widths.begin();
	}

	// Update the calculated size of the grid.
	size = totalSize;
	SUPER::SetSize(totalSize);
}
Exemple #5
0
void Text::UpdateText()
{
    int width = 0;
    int height = 0;

    rowWidths_.Clear();
    printText_.Clear();

    PODVector<unsigned> printToText;

    if (font_)
    {
        const FontFace* face = font_->GetFace(fontSize_);
        if (!face)
            return;

        rowHeight_ = face->rowHeight_;
        int rowWidth = 0;
        int rowHeight = (int)(rowSpacing_ * rowHeight_);

        // First see if the text must be split up
        if (!wordWrap_)
        {
            printText_ = unicodeText_;
            printToText.Resize(printText_.Size());
            for (unsigned i = 0; i < printText_.Size(); ++i)
                printToText[i] = i;
        }
        else
        {
            int maxWidth = GetWidth();
            unsigned nextBreak = 0;
            unsigned lineStart = 0;
            for (unsigned i = 0; i < unicodeText_.Size(); ++i)
            {
                unsigned j;
                unsigned c = unicodeText_[i];

                if (c != '\n')
                {
                    bool ok = true;

                    if (nextBreak <= i)
                    {
                        int futureRowWidth = rowWidth;
                        for (j = i; j < unicodeText_.Size(); ++j)
                        {
                            unsigned d = unicodeText_[j];
                            if (d == ' ' || d == '\n')
                            {
                                nextBreak = j;
                                break;
                            }
                            const FontGlyph* glyph = face->GetGlyph(d);
                            if (glyph)
                            {
                                futureRowWidth += glyph->advanceX_;
                                if (j < unicodeText_.Size() - 1)
                                    futureRowWidth += face->GetKerning(d, unicodeText_[j + 1]);
                            }
                            if (d == '-' && futureRowWidth <= maxWidth)
                            {
                                nextBreak = j + 1;
                                break;
                            }
                            if (futureRowWidth > maxWidth)
                            {
                                ok = false;
                                break;
                            }
                        }
                    }

                    if (!ok)
                    {
                        // If did not find any breaks on the line, copy until j, or at least 1 char, to prevent infinite loop
                        if (nextBreak == lineStart)
                        {
                            while (i < j)
                            {
                                printText_.Push(unicodeText_[i]);
                                printToText.Push(i);
                                ++i;
                            }
                        }
                        printText_.Push('\n');
                        printToText.Push(Min((int)i, (int)unicodeText_.Size() - 1));
                        rowWidth = 0;
                        nextBreak = lineStart = i;
                    }

                    if (i < unicodeText_.Size())
                    {
                        // When copying a space, position is allowed to be over row width
                        c = unicodeText_[i];
                        const FontGlyph* glyph = face->GetGlyph(c);
                        if (glyph)
                        {
                            rowWidth += glyph->advanceX_;
                            if (i < text_.Length() - 1)
                                rowWidth += face->GetKerning(c, unicodeText_[i + 1]);
                        }
                        if (rowWidth <= maxWidth)
                        {
                            printText_.Push(c);
                            printToText.Push(i);
                        }
                    }
                }
                else
                {
                    printText_.Push('\n');
                    printToText.Push(Min((int)i, (int)unicodeText_.Size() - 1));
                    rowWidth = 0;
                    nextBreak = lineStart = i;
                }
            }
        }

        rowWidth = 0;

        for (unsigned i = 0; i < printText_.Size(); ++i)
        {
            unsigned c = printText_[i];

            if (c != '\n')
            {
                const FontGlyph* glyph = face->GetGlyph(c);
                if (glyph)
                {
                    rowWidth += glyph->advanceX_;
                    if (i < printText_.Size() - 1)
                        rowWidth += face->GetKerning(c, printText_[i + 1]);
                }
            }
            else
            {
                width = Max(width, rowWidth);
                height += rowHeight;
                rowWidths_.Push(rowWidth);
                rowWidth = 0;
            }
        }

        if (rowWidth)
        {
            width = Max(width, rowWidth);
            height += rowHeight;
            rowWidths_.Push(rowWidth);
        }

        // Set row height even if text is empty
        if (!height)
            height = rowHeight;

        // Store position & size of each character
        charPositions_.Resize(unicodeText_.Size() + 1);
        charSizes_.Resize(unicodeText_.Size());

        unsigned rowIndex = 0;
        int x = GetRowStartPosition(rowIndex);
        int y = 0;
        for (unsigned i = 0; i < printText_.Size(); ++i)
        {
            charPositions_[printToText[i]] = IntVector2(x, y);
            unsigned c = printText_[i];
            if (c != '\n')
            {
                const FontGlyph* glyph = face->GetGlyph(c);
                charSizes_[printToText[i]] = IntVector2(glyph ? glyph->advanceX_ : 0, rowHeight_);
                if (glyph)
                {
                    x += glyph->advanceX_;
                    if (i < printText_.Size() - 1)
                        x += face->GetKerning(c, printText_[i + 1]);
                }
            }
            else
            {
                charSizes_[printToText[i]] = IntVector2::ZERO;
                x = GetRowStartPosition(++rowIndex);
                y += rowHeight;
            }
        }
        // Store the ending position
        charPositions_[unicodeText_.Size()] = IntVector2(x, y);
    }

    // Set minimum and current size according to the text size, but respect fixed width if set
    if (!IsFixedWidth())
    {
        SetMinWidth(wordWrap_ ? 0 : width);
        SetWidth(width);
    }
    SetFixedHeight(height);
}
boolean Font::FixedWidth () {
    register XFontStruct* i = (XFontStruct*)rep->info;
    return IsFixedWidth(i);
}