Non Native textLayout do not handle maxHeight


#1

Hi Jules,

 

It looks like that the default TextLayout implementation do not handle maxHeight

 

Any idea what would be the best way to implement this ?

 

Thanks,


#2

Looks like that it doesn't handle word wrapping either.

Some try regarding  maximum height though.

 

We definitly needs a better solution for tex tLayout in general in Juce.

 


void createLayout (const AttributedString& text, TextLayout& layout)
        {
            tokens.ensureStorageAllocated (64);
            layout.ensureStorageAllocated (totalLines);
            addTextRuns (text);
            layoutRuns (layout.getWidth());
            int charPosition = 0;
            int lineStartPosition = 0;
            int runStartPosition = 0;
            ScopedPointer<TextLayout::Line> currentLine;
            ScopedPointer<TextLayout::Run> currentRun;
            bool needToSetLineOrigin = true;
            for (int i = 0; i < tokens.size(); ++i)
            {
                const Token& t = *tokens.getUnchecked (i);
                Array<int> newGlyphs;
                Array<float> xOffsets;
                t.font.getGlyphPositions (getTrimmedEndIfNotAllWhitespace (t.text), newGlyphs, xOffsets);
                if (currentRun == nullptr)  currentRun  = new TextLayout::Run();
                if (currentLine == nullptr) currentLine = new TextLayout::Line();
                if (newGlyphs.size() > 0)
                {
                  if (Rectangle<float>(0.f, 0.f, layout.getWidth(), layout.getHeight()).contains(t.area))
                  {
                    currentRun->glyphs.ensureStorageAllocated (currentRun->glyphs.size() + newGlyphs.size());
                    const Point<float> tokenOrigin (t.area.getPosition().translated (0, t.font.getAscent()));
                    if (needToSetLineOrigin)
                    {
                        needToSetLineOrigin = false;
                        currentLine->lineOrigin = tokenOrigin;
                    }
                    const Point<float> glyphOffset (tokenOrigin - currentLine->lineOrigin);
                    for (int j = 0; j < newGlyphs.size(); ++j)
                    {
                        const float x = xOffsets.getUnchecked (j);
                        currentRun->glyphs.add (TextLayout::Glyph (newGlyphs.getUnchecked(j),
                                                                   glyphOffset.translated (x, 0),
                                                                   xOffsets.getUnchecked (j + 1) - x));
                    }
                  }
                  charPosition += newGlyphs.size();
                }
                if (t.isWhitespace || t.isNewLine)
                    ++charPosition;
                const Token* const nextToken = tokens [i + 1];
                if (nextToken == nullptr) // this is the last token
                {
                    addRun (*currentLine, currentRun.release(), t, runStartPosition, charPosition);
                    currentLine->stringRange = Range<int> (lineStartPosition, charPosition);
                    if (! needToSetLineOrigin)
                        layout.addLine (currentLine.release());
                    needToSetLineOrigin = true;
                }
                else if (Rectangle<float>(0.f, 0.f, layout.getWidth(), layout.getHeight()).contains(nextToken->area))
                {
                    if (t.font != nextToken->font || t.colour != nextToken->colour)
                    {
                        addRun (*currentLine, currentRun.release(), t, runStartPosition, charPosition);
                        runStartPosition = charPosition;
                    }
                    if (t.line != nextToken->line)
                    {
                        if (currentRun == nullptr)
                            currentRun = new TextLayout::Run();
                        addRun (*currentLine, currentRun.release(), t, runStartPosition, charPosition);
                        currentLine->stringRange = Range<int> (lineStartPosition, charPosition);
                        if (! needToSetLineOrigin)
                            layout.addLine (currentLine.release());
                        runStartPosition = charPosition;
                        lineStartPosition = charPosition;
                        needToSetLineOrigin = true;
                    }
                }
            }
            if ((text.getJustification().getFlags() & (Justification::right | Justification::horizontallyCentred)) != 0)
            {
                const float totalW = layout.getWidth();
                const bool isCentred = (text.getJustification().getFlags() & Justification::horizontallyCentred) != 0;
                for (int i = 0; i < layout.getNumLines(); ++i)
                {
                    float dx = totalW - layout.getLine(i).getLineBoundsX().getLength();
                    if (isCentred)
                        dx /= 2.0f;
                    layout.getLine(i).lineOrigin.x += dx;
                }
            }
        }

#3

bump :)